WPF 将 ListBox 绑定到枚举,显示描述属性
Posted
技术标签:
【中文标题】WPF 将 ListBox 绑定到枚举,显示描述属性【英文标题】:WPF Binding a ListBox to an enum, displaying the Description Attribute 【发布时间】:2011-04-28 12:06:15 【问题描述】:是否可以使用 ObjectDataProvider 方法将 ListBox 绑定到枚举,并以某种方式设置其样式以显示 Description 属性?如果是这样,人们将如何去做...?
【问题讨论】:
***.com/questions/1281490/… 可能重复。 【参考方案1】:是的,这是可能的。这会做到的。假设我们有枚举
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,我们将 ItemsSource 设置为 MyEnumValues 并应用带有 Converter 的 ItemTemplate。
<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。
【讨论】:
谢谢,现在就试试看:) 爱它,gank它。我使用了一个小 linq 来配对 GetEnumDescription,你可以在这里找到它pastebin.com/XLm9hbhG 所以你必须为每种类型的枚举做一个转换器? 请注意,您必须创建转换器实例作为资源,例如:<helper:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
如果您在枚举上有不同的属性,这将中断 - 我建议将代码更改为 attrib = attribArray.OfType另一种解决方案是自定义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();
【讨论】:
这比最佳答案要容易得多。我只是有一个问题。当我绑定到存储枚举的属性时,它会正确更新,但在我加载窗口时不会自动显示该值。你知道我该如何解决这个问题吗? @EatATaco 你在使用组合框吗?如果是这样,请看这里:***.com/q/20479976/5612780【参考方案3】:如果您绑定到 Enum,您可能可以通过 IValueConverter 将其转换为描述。
请参阅Binding ComboBoxes to enums... in Silverlight!,了解如何完成此操作。
更多信息请参见http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx。
【讨论】:
【参考方案4】:您可以在项目中定义资源文件(*.resx 文件)。在此文件中,您必须定义“键值对”,如下所示:
"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 年 ;-) 但也许它可以被其他人使用!
【讨论】:
【参考方案5】:是的,可能。
ListBox
可以帮助我们做到这一点,无需转换器。
此方法的步骤如下: 创建一个 ListBox 并将 ListBox 的 ItemsSource 设置为枚举,并将 ListBox 的 SelectedItem 绑定到 selected 属性。
然后将创建每个 ListBoxItem。
第 1 步:定义您的枚举。public enum EnumValueNames
EnumValueName1,
EnumValueName2,
EnumValueName3
然后将以下属性添加到您的 DataContext(或 MVVM 的 ViewModel)中,该属性记录被选中的选定项。
public EnumValueNames SelectedEnumValueName get; set;
第 2 步:将枚举添加到 Window、UserControl 或 Grid 等的静态资源中。
<Window.Resources>
<ObjectDataProvider MethodName="GetValues"
ObjectType="x:Type system:Enum"
x:Key="EnumValueNames">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:EnumValueNames" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
第 3 步:使用列表框填充每个项目
<ListBox ItemsSource="Binding Source=StaticResource EnumValueNames"
SelectedItem="Binding SelectedEnumValueName, Mode=TwoWay" />
参考资料: https://www.codeproject.com/Articles/130137/Binding-TextBlock-ListBox-RadioButtons-to-Enums
【讨论】:
以上是关于WPF 将 ListBox 绑定到枚举,显示描述属性的主要内容,如果未能解决你的问题,请参考以下文章
WPF 绑定:如何将文件路径列表中的名称绑定到 ListBox 中 TextBlock 的文本?