具有AutoGenerateColumns的WPF DataGrid中的枚举值的描述属性 [英] Description attribute on enum values in WPF DataGrid with AutoGenerateColumns
问题描述
这是我的枚举:
enum Foo
{
[Description("the quick")]
Bar,
[Description("brown fox")]
Baz,
[Description("jumped over")]
Qux
}
这是我的ViewModel的一部分:
Here's part of my ViewModel:
class MainWindowViewModel : ViewModelBase
{
public ObservableCollection<RowViewModel> Rows { get { ... } }
}
class RowViewModel : ViewModelBase
{
public String Name { get { ... } set { ... } }
public Foo Foo { get { ... } set { ... } }
}
这是我的XAML:
<DataGrid AutoGeneratingColumn="OnAutoGeneratingColumn" ItemsSource="{Binding Path=Rows}" />
因为MainWindowViewModel.Rows[n].Foo
是一个枚举,所以WPF会自动生成一个DataGridComboBoxColumn
,其中的枚举成员作为组合框下拉值,到目前为止效果很好.
Because MainWindowViewModel.Rows[n].Foo
is an enum, WPF will automatically generate a DataGridComboBoxColumn
with the enum members as combobox drop-down values, so far so good.
我希望组合框在组合框下拉菜单和显示中使用[Description("")]
值.因此,我实现了IValueConverter
.然后,我为OnAutoGeneratingColumn
添加了处理程序:
I want the combobox to use the [Description("")]
values in the combobox drop-down and display. So I implemented an IValueConverter
. I then added a handler for OnAutoGeneratingColumn
:
private void OnAutoGeneratingColumn(Object sender, DataGridAutoGeneratingColumnEventArgs e)
{
DataGridComboBoxColumn dgCol = e.Column as DataGridComboBoxColumn;
if( dgCol != null && e.PropertyType.IsEnum ) {
Binding binding = new Binding( e.PropertyName );
binding.Converter = EnumDescriptionValueConverter.Instance;
dgCol.TextBinding = binding;
dgCol.SelectedItemBinding = binding;
}
}
不幸的是,这是行不通的:单元格具有值时显示为空,并且下拉列表框包含原始枚举值而不是描述.
Unfortunately this doesn't work: the cells appear empty when they have values and the combobox drop-down contains the original enum values rather than descriptions.
推荐答案
由于枚举不是可变项,因此您正在努力工作,因为在VM构建期间枚举枚举并将描述提取到列表中,然后将控件绑定到该列表.
You are working too hard to do this, since the enum is not a changeable item, during the VM construction enumerate the enum and extract the descriptions into a list then bind the control to that list.
接受我们的枚举
public enum TheNums
{
[Description("One")]
Alpha,
[Description("Two")]
Beta,
[Description("Three")]
Gamma
}
提取描述的扩展方法
public static class AttributeExtension
{
/// <summary>If an attribute on an enumeration exists, this will return that
/// information</summary>
/// <param name="value">The object which has the attribute.</param>
/// <returns>The description string of the attribute or string.empty</returns>
public static string GetAttributeDescription(this object value)
{
string retVal = string.Empty;
try
{
retVal = value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.OfType<DescriptionAttribute>()
.First()
.Description;
}
catch (NullReferenceException)
{
//Occurs when we attempt to get description of an enum value that does not exist
}
finally
{
if (string.IsNullOrEmpty(retVal))
retVal = "Unknown";
}
return retVal;
}
}
创建我们的字符串列表List<string> EnumDescriptions { get; set; }
:
The creation of our list of strings List<string> EnumDescriptions { get; set; }
:
EnumDescriptions = new List<string>()
{
TheNums.Alpha.GetAttributeDescription(),
TheNums.Beta.GetAttributeDescription(),
TheNums.Gamma.GetAttributeDescription()
};
为简单起见,我将其添加到页面的数据上下文中,因此不必 path 进入名为EnumDescriptions
的列表.
For the sake of simplicity I will add it to the page's datacontext so I don't have to path into the list named EnumDescriptions
.
public List<string> EnumDescriptions { get; set; }
public MainWindow()
{
InitializeComponent();
EnumDescriptions = new List<string>()
{
TheNums.Alpha.GetAttributeDescription(),
TheNums.Beta.GetAttributeDescription(),
TheNums.Gamma.GetAttributeDescription()
};
DataContext = EnumDescriptions;
}
然后在我的页面上,我将直接绑定到它,因为Listbox会继承页面的数据上下文,而 是EnumDescriptions
.
Then on my page I will bind to it directly, since Listbox inheirits the page's datacontext which is the EnumDescriptions
.
<ListBox ItemsSource="{Binding}" Width="100" Height="200"/>
结果是:
请注意,在MVVM实现中,整个VM实例很可能是页面的数据上下文,因此绑定需要知道数据上下文/VM实例之外的属性名称(其绑定path
),因此使用Binding EnumDescriptions
或Binding Path=EnumDescriptions
.
Note that in an MVVM implementation, most likely the whole VM instance would be the page's data context, so the binding needs to know the property name (its binding path
) off of the data context/ the VM instance, so use Binding EnumDescriptions
or Binding Path=EnumDescriptions
.
这篇关于具有AutoGenerateColumns的WPF DataGrid中的枚举值的描述属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!