【问题标题】:How to set Enum to ItemsSource WPF如何将枚举设置为 ItemsSource WPF
【发布时间】:2013-08-15 22:35:39
【问题描述】:

如何将枚举设置为 xaml 中的列表框。但是在列表框中,我需要显示描述而不是枚举的名称/值。然后,当我单击一个按钮时,我需要将选定的枚举通过 icommand 作为枚举而不是字符串传递给方法。 例如:

  public enum MyEnum 
  {
     EnumOne = 0,
     [Description("Enum One")]
     EnumTwo = 1,
     [Description("Enum Two")]
     EnumTwo = 2,
     [Description("Enum Three")]
  }

需要将这些枚举绑定到具有描述的 displaymemberpath 的列表框。然后在列表框中进行选择时,像这样传递选定的枚举:

  private void ButtonDidClick(MyEnum enum)
  {

  }

XAML:

  <ListBox ItemsSource="{Binding MyEnum"} /> ?

而且我知道如何将命令连接到按钮等其他工作。感谢您的帮助。

【问题讨论】:

  • 我使用将其转换为 Dictionary 并使用 Value 作为 DisplayMember
  • 我认为这个答案可以满足您的需求:stackoverflow.com/questions/11439920/…
  • 这是一个很好的例子。谢谢。

标签: wpf xaml enums


【解决方案1】:

来自生产应用
前一阵子把这个关掉了,找不到源
将 DisplayMememberPath 绑定到 Value

public static Dictionary<T, string> EnumToDictionary<T>()
    where T : struct
{
    Type enumType = typeof(T);

    // Can't use generic type constraints on value types,
    // so have to do check like this
    if (enumType.BaseType != typeof(Enum))
        throw new ArgumentException("T must be of type System.Enum");
    Dictionary<T, string> enumDL = new Dictionary<T, string>();
    foreach (T val in Enum.GetValues(enumType))
    {
        enumDL.Add(val, val.ToString());
    }
    return enumDL;
}

获取描述方法

对于那些想知道如何读取描述属性值的人。以下内容可以轻松转换为使用enum 或扩展。我发现这个实现更灵活。

使用此方法,将val.ToString() 替换为GetDescription(val)

    /// <summary>
    /// Returns the value of the 'Description' attribute; otherwise, returns null.
    /// </summary>
    public static string GetDescription(object value)
    {
        string sResult = null;

        FieldInfo oFieldInfo = value.GetType().GetField(value.ToString());

        if (oFieldInfo != null)
        {
            object[] oCustomAttributes = oFieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), true);

            if ((oCustomAttributes != null) && (oCustomAttributes.Length > 0))
            {
                sResult = ((DescriptionAttribute)oCustomAttributes[0]).Description;
            }
        }
        return sResult;
    }

【讨论】:

  • 非常好,效果很好。但是我需要字典中的值是枚举的描述而不是值,所以我之前编写了一个返回描述的 GetDescription(this enum value) 函数,所以我只是在 enumDL.Add() 中调用了该函数和将值作为枚举传递。很好用,谢谢帮助
【解决方案2】:

使用 ObjectDataProvider:

<ObjectDataProvider x:Key="enumValues"
   MethodName="GetValues" ObjectType="{x:Type System:Enum}">
      <ObjectDataProvider.MethodParameters>
           <x:Type TypeName="local:ExampleEnum"/>
      </ObjectDataProvider.MethodParameters>
 </ObjectDataProvider>

然后绑定到静态资源:

ItemsSource="{Binding Source={StaticResource enumValues}}"

找到这个解决方案here

【讨论】:

    【解决方案3】:

    您可以通过将 Enum 转换为 MyEnum 字符串元组列表并使用 ListBox 的 DisplayMemberPath 参数来显示描述项来实现。当你选择一个特定的元组时,只需抓住它的 MyEnum 部分,并使用它来设置 ViewModel 中的 SelectedEnumValue 属性。

    代码如下:

    XAML:

    <Window x:Class="EnumToListBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ListBox Grid.Row="0" 
                 ItemsSource="{Binding EnumToDescriptions}"
                 SelectedItem="{Binding SelectedEnumToDescription}"
                 DisplayMemberPath="Item2"/>
        <TextBlock Grid.Row="1" 
                   Text="{Binding SelectedEnumToDescription.Item2}"/>
    </Grid>
    

    背后的代码:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
    
    public class ViewModel : PropertyChangedNotifier
    {
        private List<Tuple<MyEnum, string>> _enumToDescriptions = new List<Tuple<MyEnum, string>>();
        private Tuple<MyEnum, string> _selectedEnumToDescription;
    
        public ViewModel()
        {
            Array Values = Enum.GetValues(typeof(MyEnum));
            foreach (var Value in Values)
            {
                var attributes = Value.GetType().GetField(Value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
                var attribute = attributes[0] as DescriptionAttribute;
                _enumToDescriptions.Add(new Tuple<MyEnum, string>((MyEnum)Value, (string)attribute.Description));
            }
        }
    
        public List<Tuple<MyEnum, string>> EnumToDescriptions
        {
            get
            {
                return _enumToDescriptions;
            }
            set
            {
                _enumToDescriptions = value;
                OnPropertyChanged("EnumToDescriptions");
            }
        }
    
        public Tuple<MyEnum, string> SelectedEnumToDescription
        {
            get
            {
                return _selectedEnumToDescription;
            }
            set
            {
                _selectedEnumToDescription = value;
                SelectedEnumValue = _selectedEnumToDescription.Item1;
                OnPropertyChanged("SelectedEnumToDescription");
            }
        }
    
        private MyEnum? _selectedEnumValue;
        public MyEnum? SelectedEnumValue
        {
            get
            {
                return _selectedEnumValue;
            }
            set
            {
                _selectedEnumValue = value;
                OnPropertyChanged("SelectedEnumValue");
            }
        }
    }
    
    public enum MyEnum
    {
        [Description("Item1Description")]
        Item1,
        [Description("Item2Description")]
        Item2,
        [Description("Item3Description")]
        Item3,
        [Description("Item4Description")]
        Item4
    }
    
    public class PropertyChangedNotifier : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            var propertyChanged = PropertyChanged;
            if (propertyChanged != null)
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    【讨论】:

    • 刚刚看到您想要的是描述,而不是名称 - 我会尝试修改我的代码以更好地反映您的问题。
    • 你到底为什么要一个元组而不是字典。
    • 无论哪种方式都可以——通常我会包装元组以公开具有比 'Item1' 和 'Item2' 或 'Key.Name' 和 'Value' 更多描述性名称的属性一个字典,使绑定更加明显,而无需查看 ViewModel 代码。
    • 是的,如果我不需要的话,我不是元组的粉丝。不过感谢您的回复。
    猜你喜欢
    • 2011-05-19
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 2016-11-30
    • 2023-04-09
    相关资源
    最近更新 更多