具有AutoGenerateColumns的WPF DataGrid中的枚举值的描述​​属性 [英] Description attribute on enum values in WPF DataGrid with AutoGenerateColumns

查看:194
本文介绍了具有AutoGenerateColumns的WPF DataGrid中的枚举值的描述​​属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的枚举:

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 EnumDescriptionsBinding 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆