簡體   English   中英

將ComboBox的SelectedValue綁定到WPF中的枚舉

[英]Binding SelectedValue of ComboBox to enum in WPF

我想在ListView中顯示產品列表,其中一列是我想要綁定的ComboBox 這是我的枚舉:

public enum SelectionMode { One, Two }

和產品類:

public class Product
{
    public SelectionMode Mode { get; set; }

    public string Name { get; set; }
}

ViewModel類中,我有一個ProductObservableCollection

    private ObservableCollection<Product> _productList;
    public ObservableCollection<Product> ProductList
    {
        get
        {
            return _productList;
        }
        set
        {
            _productList = value;
        }
    }

    public MainViewModel()
    {
        ProductList = new ObservableCollection<Product>
                          {
                              new Product {Mode = SelectionMode.One, Name = "One"},
                              new Product {Mode = SelectionMode.One, Name = "One"},
                              new Product {Mode = SelectionMode.Two, Name = "Two"}
                          };
    }

最后我有一個帶有ListViewGrid ,它綁定到我的ProductList

<Window.Resources>
    <ObjectDataProvider x:Key="AlignmentValues" 
                    MethodName="GetNames" ObjectType="{x:Type System:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="ViewModel:SelectionMode" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

<Grid>
    <ListView Height="120" HorizontalAlignment="Left" 
                  VerticalAlignment="Top"
                  SelectionMode="Multiple" 
                  ItemsSource="{Binding ProductList}" >
        <ListView.View>
            <GridView>
                <GridViewColumn Width="120" Header="Product Name" DisplayMemberBinding="{Binding Path=Name}" />
                <GridViewColumn Header="Selection Mode">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Source={StaticResource AlignmentValues}}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

我的問題是; ComboBox SelectedValue綁定到Product類的SelectionMode屬性的方法是什么?

更新

好。 我在這個主題中找到了答案。 所以我必須添加轉換器類:

public class MyEnumToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (SelectionMode)Enum.Parse(typeof(SelectionMode), value.ToString(), true);
    }
}

並將其添加到窗口資源:

<Window.Resources>
    <ObjectDataProvider x:Key="AlignmentValues" 
                    MethodName="GetNames" ObjectType="{x:Type System:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="ViewModel:SelectionMode" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
    <Converters:MyEnumToStringConverter x:Key="MyEnumConverter"/>
</Window.Resources>

最后編輯ComboBox數據模板:

<ComboBox ItemsSource="{Binding Source={StaticResource AlignmentValues}}" 
                                      SelectedValue="{Binding Path=Mode, Converter={StaticResource MyEnumConverter}}"/>

就這樣。 希望它對別人有用:)

下面我將綁定枚舉用於列表/ combox

public enum EnumsAvailable
{
    [Description("Its an A")]
    a,
    [Description("Its a B")]
    b,
    [Description("Its a C")]
    c,
    [Description("Its a D")]
    d
} ;

這是我的XAML

        <ComboBox Grid.Column="4" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="cb_Application" VerticalAlignment="Top" Width="120"
              ItemsSource="{Binding Path=ListOfEnumValues,Converter={converters:ArrayStringToEnumDescriptionConverter}}"
              SelectedValue="{Binding Path=ChosenEnum,Converter={converters:DescriptionToEnumConverter},UpdateSourceTrigger=PropertyChanged}"
              Validation.ErrorTemplate="{x:Null}" TabIndex="5" />

我的視圖模型

    public EnumsAvailable ListOfEnumValues
    {
        get { return new EnumsAvailable(); }
    }

    public EnumsAvailable ChosenEnum { 
        get { return _ChosenEnum; }
        set
        {
            if (_ChosenEnum != value)
            {
                _ChosenEnum = value;
                RaisePropertyChanged(() => ChosenEnum);
            }
        } 
    }

和我的轉換器

public class ArrayStringToEnumDescriptionConverter : BaseEnumDescriptionConverter, IValueConverter
{
    public ArrayStringToEnumDescriptionConverter()
    {

    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var type = value.GetType();
        return !type.IsEnum ? null : base.GetEnumDescription(type);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

public abstract class BaseEnumDescriptionConverter : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    public IEnumerable<string> GetEnumDescription(Type destinationType)
    {
        var enumType = destinationType;

        var values = RetrieveEnumDescriptionValues(enumType);

        return new List<string>(values);
    }

    public object GetEnumFromDescription(string descToDecipher, Type destinationType)
    {
        var type = destinationType;
        if (!type.IsEnum) throw new InvalidOperationException();
        var staticFields = type.GetFields().Where(fld => fld.IsStatic);
        foreach (var field in staticFields)
        {
            var attribute = Attribute.GetCustomAttribute(field,
                typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (attribute != null)
            {
                if (attribute.Description == descToDecipher)
                {
                    return (Enum.Parse(type, field.Name, true));
                }
            }
            else
            {
                if (field.Name == descToDecipher)
                    return field.GetValue(null);
            }
        }
        throw new ArgumentException("Description is not found in enum list.");
    }

    public static string[] RetrieveEnumDescriptionValues(Type typeOfEnum)
    {
        var values = Enum.GetValues(typeOfEnum);

        return (from object fieldInfo in values select DescriptionAttr(fieldInfo)).ToArray();
    }



    public static string DescriptionAttr(object enumToQuery)
    {
        FieldInfo fi = enumToQuery.GetType().GetField(enumToQuery.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute), false);

        return attributes.Length > 0 ? attributes[0].Description : enumToQuery.ToString();
    }

    public static string GetDomainNameAttribute(object enumToQuery)
    {
        FieldInfo fi = enumToQuery.GetType().GetField(enumToQuery.ToString());

        DomainNameAttribute[] attributes = (DomainNameAttribute[])fi.GetCustomAttributes(
            typeof(DomainNameAttribute), false);

        return attributes.Length > 0 ? attributes[0].DomainName : enumToQuery.ToString();
    }

}

public class DescriptionToEnumConverter : BaseEnumDescriptionConverter, IValueConverter
{
    public DescriptionToEnumConverter(){}

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var enumValue = value;

        if (enumValue != null)
        {
            enumValue = GetEnumFromDescription(value.ToString(), targetType);
        }

        return enumValue;
    }
}

在我個人看來,它很清潔,高度可重復使用。 到目前為止,我發現的唯一缺陷是,如果您更新代碼中的選定值(不是通過UI),那么它不會在UI上更新。 但是這可以通過進一步的UI調整來克服。 我現在正在進行更改,一旦完成,我將更新此答案。

如果您准備更改ComboBox的ItemsSource的綁定,那么,只需SelectedValue="{Binding Mode,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"將起作用。

在這種情況下,您必須像這樣綁定ItemsSource: ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ViewClass}}, Path=ModeList}" ; 其中,ModeList是SelectionMode類型列表的簡單公共屬性,包含應該在ComboBox下拉列表中顯示的枚舉,而ViewClass是此屬性(ModeList)可用的類; 確保在xaml中添加了名稱空間的引用。

否則你必須使用轉換器,它應該將字符串轉換回枚舉類型。

我正在使用轉換器,它還允許定義將顯示的字符串而不是枚舉值: http//www.ageektrapped.com/blog/the-missing-net-7-displaying-enums-在-WPF /

暫無
暫無

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

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