簡體   English   中英

數據綁定WPF中的Enum屬性

[英]Data binding Int property to Enum in WPF

以下是我所擁有的課程的簡化示例:

public class ExampleClassDto 
{
     public int DriverTypeId
}

我還有一個Enum,它將DriverType的Ids映射到有意義的名稱:

public enum DriverType
{
    None,
    Driver1,
    Driver2,
    Driver3
}

但是我希望將它在XAML中綁定到一個組合框。 不幸的是,由於類型不匹配,它不喜歡這個。 所以在我的ViewModel中,我必須創建第二個屬性來映射這兩個

public class ExampleViewModel
{
    private ExampleClassDto _selectedExampleClass;
    public ExampleClassDto SelectedExampleClass
    {
        get { return _selectedExampleClass; }
        set
        {
            _selectedExampleClass = value;
            SelectedDriverType = (DriverType)_selectedExampleClass.DriverTypeId;
            OnPropertyChanged("SelectedDeviceType");
        }
    }

public DriverType SelectedDriverType
{
    get
        {
            if (_selectedDeviceType != null) 
            { 
                return (DriverType)_selectedDeviceType.DriverTypeId;
            }
            return DriverType.None;
        }
        set
        {
            _selectedDeviceType.DriverTypeId = (int) value;
            OnPropertyChanged("SelectedDriverType");
        }
}
}

然后我綁定到新屬性。

<ComboBox ItemsSource="{Binding Source={StaticResource DriverTypeEnum}}" SelectedValue="{Binding SelectedDriverType, Mode=TwoWay}"/>

現在,這個工作,但感覺非常嚴重。 它使用SelectedDriverType作為轉換器。 我想避免讓DTO的屬性變成另一種類型。 還有其他更優雅的解決方案嗎?

謝謝!

您可以使用一個通用的轉換器說EnumConverter ,它將convert int to Enum以在XAML上顯示它,並convert back from Enum to int以在ViewModel類中重新設置。

它適用於任何枚舉類型。 你只需要在轉換器參數中傳遞枚舉類型。

public class EnumConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
                          System.Globalization.CultureInfo culture)
    {
        Enum enumValue = default(Enum);
        if (parameter is Type)
        {
            enumValue = (Enum)Enum.Parse((Type)parameter, value.ToString());
        }
        return enumValue;
     }

     public object ConvertBack(object value, Type targetType, object parameter, 
                               System.Globalization.CultureInfo culture)
     {
         int returnValue = 0;
         if (parameter is Type)
         {
             returnValue = (int)Enum.Parse((Type)parameter, value.ToString());
         }
         return returnValue;
     }
}

XAML用法:

<ComboBox ItemsSource="{Binding Source={StaticResource DriverTypeEnum}}"
          SelectedValue="{Binding DriverTypeId,
                                Converter={StaticResource EnumConverter}, 
                                ConverterParameter={x:Type local:DriverType}}"/>

local是聲明DriverType的名稱空間。

接受的答案要求您在每個綁定上將枚舉類型指定為轉換器參數。

如果綁定到枚舉屬性,則轉換器可以從targetType屬性確定枚舉類型,這可能更符合人體工程學且不易出錯。

public sealed class BidirectionalEnumAndNumberConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return null;

        if (targetType.IsEnum)
        {
            // convert int to enum
            return Enum.ToObject(targetType, value);
        }

        if (value.GetType().IsEnum)
        {
            // convert enum to int
            return System.Convert.ChangeType(
                value,
                Enum.GetUnderlyingType(value.GetType()));
        }

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // perform the same conversion in both directions
        return Convert(value, targetType, parameter, culture);
    }
}

無論基礎枚舉類型( intshortbyte ...)如何,這也都有效。

調用時,此轉換器僅基於valuetargetType值在int / enum值之間翻轉值的類型。 源代碼中沒有硬編碼的枚舉類型,因此它非常可重用。

首先將枚舉存儲為int是一個壞主意。 無論如何,我會使用雙向代理屬性而不是單獨的類:

public int DriverTypeId { get; set; }

public DriverType IntAsEnum // proxy property, doesn't store any value, only does the conversion
{
    get { return (DriverType)DriverTypeId; }
    set { DriverTypeId = (int)value; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM