代码之家  ›  专栏  ›  技术社区  ›  Michal Ciechan

WPF将列表框绑定到枚举,显示Description属性

  •  33
  • Michal Ciechan  · 技术社区  · 14 年前

    3 回复  |  直到 14 年前
        1
  •  93
  •   Stacked Emily M    5 年前

    是的,这是可能的。这就行了。假设我们有枚举

    public enum MyEnum
    {
        [Description("MyEnum1 Description")]
        MyEnum1,
        [Description("MyEnum2 Description")]
        MyEnum2,
        [Description("MyEnum3 Description")]
        MyEnum3
    }
    

    然后我们可以使用ObjectDataProvider作为

    xmlns:MyEnumerations="clr-namespace:MyEnumerations"
    
    <ObjectDataProvider MethodName="GetValues"
                    ObjectType="{x:Type sys:Enum}"
                    x:Key="MyEnumValues">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="MyEnumerations:MyEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
    

    <ListBox Name="c_myListBox" SelectedIndex="0" Margin="8"
            ItemsSource="{Binding Source={StaticResource MyEnumValues}}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Converter={StaticResource EnumDescriptionConverter}}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    在转换器中,我们得到描述并返回

    public class EnumDescriptionConverter : IValueConverter
    {
        private string GetEnumDescription(Enum enumObj)
        {
            FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
    
            object[] attribArray = fieldInfo.GetCustomAttributes(false);
    
            if (attribArray.Length == 0)
            {
                return enumObj.ToString();
            }
            else
            {
                DescriptionAttribute attrib = attribArray[0] as DescriptionAttribute;
                return attrib.Description;
            }
        }
    
        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Enum myEnum = (Enum)value;
            string description = GetEnumDescription(myEnum);
            return description;
        }
    
        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return string.Empty;
        }
    }
    

    GetEnumDescription方法可能应该放在其他地方,但是您得到的想法是:)

    支票 GetEnumDescription as extension method .

        2
  •  3
  •   Community vonPryz    7 年前

    如果绑定到枚举,则可以通过IValueConverter将其转换为描述。

    Binding ComboBoxes to enums... in Silverlight! 关于如何实现这一点的描述。

    http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx 更多信息。

        3
  •  2
  •   chviLadislav    5 年前

    另一个解决方案是 MarkupExtension 从枚举类型生成项的。这使得xaml更加紧凑和可读。

    using System.ComponentModel;
    
    namespace EnumDemo
    {
        public enum Numbers
        {
            [Description("1")]
            One,
    
            [Description("2")]
            Two,
    
            Three,
        }
    }
    

    用法示例:

    <Window x:Class="EnumDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:EnumDemo">
    
        <ListBox ItemsSource="{local:EnumToCollection EnumType={x:Type local:Numbers}}"/>
    
    </Window>
    

    MarkupExtension实现

    using System;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows.Markup;
    
    namespace EnumDemo
    {
        public class EnumToCollectionExtension : MarkupExtension
        {
            public Type EnumType { get; set; }
    
            public override object ProvideValue(IServiceProvider serviceProvider)
            {
                if (EnumType == null) throw new ArgumentNullException(nameof(EnumType));
    
                return Enum.GetValues(EnumType).Cast<Enum>().Select(EnumToDescriptionOrString);
            }
    
            private string EnumToDescriptionOrString(Enum value)
            {
                return value.GetType().GetField(value.ToString())
                           .GetCustomAttributes(typeof(DescriptionAttribute), false)
                           .Cast<DescriptionAttribute>()
                           .FirstOrDefault()?.Description ?? value.ToString();
            }
        }
    }
    
        4
  •  1
  •   peter70    7 年前

    "YellowCars" : "Yellow Cars",
    "RedCars" : "Red Cars",
    

    等等。。。

    键等于枚举项,如下所示:

    public enum CarColors
    {
        YellowCars,
        RedCars
    }
    

    当您使用WPF时,可以在XAML代码中实现如下内容:

    <ComboBox ItemsSource="{Binding Source={StaticResource CarColors}}" SelectedValue="{Binding CarColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Converter={StaticResource CarColorConverter}}" />
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
    

    然后你必须写你的转换器,像这样:

    using System;
    using System.Globalization;
    using System.Resources;
    using System.Windows.Data;
    
    public class CarColorConverter : IValueConverter
    {
        private static ResourceManager CarColors = new ResourceManager(typeof(Properties.CarColors));
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var key = ((Enum)value).ToString();
            var result = CarColors.GetString(key);
            if (result == null) {
                result = key;
            }
    
            return result;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    我的答案已经晚了7年;—)但也许可以被别人使用!