从枚举自动生成DataGrid列

时间:2014-07-23 20:28:59

标签: c# wpf datagrid enums

我正在使用WPF DataGrid控件的列自动生成功能。它的一个列是一个选择列 - 基于一些枚举。

枚举看起来像这样:

public enum MyTypes {
  Integer = 1,
  Float = 2
  IntegerArray = 3,
  FloatArray = 4
}

我想将array类型显示为不是IntegerArray,FloatArray,而是显示为Integer [], 在自动生成的下拉列表中浮动[]。

换句话说 - 单元格将包含一个下拉列表,其值为Integer,Float,IntegerArray,FloatArray,我希望它们是Integer,Float,Integer [],Float []。显然,我无法在MyTypes声明中将IntegerArray更改为Integer []。

我该怎么做?

修改

下面的Pushpray的答案只能部分起作用 - 我得到枚举字段描述(所以不是在ComboBox中使用FloatArr我得到Float [],而是在保持{{{ 1}}失去焦点,然后我得到ComboBox

3 个答案:

答案 0 :(得分:4)

以下是我提供解决问题的方法

结果

result

我们首先将所需的值定义为枚举值

Description属性
public enum MyTypes
{
    Integer = 1,
    Float = 2,
    [Description("Integer[]")]
    IntegerArray = 3,
    [Description("Float[]")]
    FloatArray = 4
}

然后使用一种方法创建一个类,该方法枚举枚举类型中的列表,如果应用了将描述属性考虑在内

namespace CSharpWPF
{
    public class EnumHelper
    {
        public static IEnumerable<string> GetEnumDescriptions(Type enumType)
        {
            foreach (var item in Enum.GetNames(enumType))
            {
                FieldInfo fi = enumType.GetField(item);

                DescriptionAttribute[] attributes =
                    (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

                if (attributes != null && attributes.Length > 0)
                    yield return attributes[0].Description;
                else
                    yield return item;
            }
        }
    }
}

最后使用ObjectDataProvider在类GetEnumDescriptions中使用枚举器方法EnumHelper,并使用与DataGridComboBoxColumn的ItemsSource

的源相同的方法

示例xaml

<DataGrid xmlns:l="clr-namespace:CSharpWPF">
    <DataGrid.Columns>
        <DataGridComboBoxColumn Header="EnumValues" >
            <DataGridComboBoxColumn.ItemsSource>
                <Binding>
                    <Binding.Source>
                        <ObjectDataProvider MethodName="GetEnumDescriptions"
                                            ObjectType="{x:Type l:EnumHelper}">
                            <ObjectDataProvider.MethodParameters>
                                <x:Type TypeName="l:MyTypes" />
                            </ObjectDataProvider.MethodParameters>
                        </ObjectDataProvider>
                    </Binding.Source>
                </Binding>
            </DataGridComboBoxColumn.ItemsSource>
        </DataGridComboBoxColumn>
    </DataGrid.Columns>
</DataGrid>

使用自动生成列

<DataGrid x:Name="dGrid" 
          AutoGenerateColumns="True" 
          AutoGeneratingColumn="DataGrid_OnAutoGeneratingColumn"
          xmlns:l="clr-namespace:CSharpWPF">
    <DataGrid.Resources>
        <l:EnumHelper x:Key="EnumHelper" />
        <ObjectDataProvider x:Key="EnumValues"
                            MethodName="GetEnumDescriptions"
                            ObjectType="{x:Type l:EnumHelper}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="l:MyTypes" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
        <DataTemplate x:Key="MyTypesCellTemplate">
            <TextBlock Text="{Binding EnumValue, Converter={StaticResource EnumHelper}}"/>
        </DataTemplate>
        <DataTemplate x:Key="MyTypesCellEditingTemplate">
            <ComboBox  SelectedItem="{Binding EnumValue, Converter={StaticResource EnumHelper}}"
                ItemsSource="{Binding Source={StaticResource EnumValues}}" />
        </DataTemplate>
    </DataGrid.Resources>
</DataGrid>

事件处理程序

    private void DataGrid_OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if (e.PropertyType == typeof(MyTypes))
        {
            DataGridTemplateColumn templateColumn = new DataGridTemplateColumn();
            templateColumn.Header = e.Column.Header;
            templateColumn.CellTemplate = (DataTemplate)dGrid.Resources["MyTypesCellTemplate"];
            templateColumn.CellEditingTemplate = (DataTemplate)dGrid.Resources["MyTypesCellEditingTemplate"];
            e.Column = templateColumn;
        }
    }

EnumHelper类

public class EnumHelper : IValueConverter
{
    public static IEnumerable<string> GetEnumDescriptions(Type enumType)
    {
        foreach (var item in Enum.GetNames(enumType))
        {
            FieldInfo fi = enumType.GetField(item);

            DescriptionAttribute[] attributes =
                (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes != null && attributes.Length > 0)
                yield return attributes[0].Description;
            else
                yield return item;
        }
    }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return string.Empty;

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

        DescriptionAttribute[] attributes =
            (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if (attributes != null && attributes.Length > 0)
            return attributes[0].Description;
        else
            return value.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return MyTypes.Float;

        Type enumType = typeof(MyTypes);
        foreach (var item in Enum.GetNames(enumType))
        {
            FieldInfo fi = enumType.GetField(item);

            DescriptionAttribute[] attributes =
                (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes != null && attributes.Length > 0 && string.Equals(attributes[0].Description, value))
                return Enum.Parse(enumType, item);
        }
        return Enum.Parse(enumType, value.ToString());
    }
}

<强>演示

以下是基于上述答案的工作示例代码

DataGridEnumsSample.zip(VS 2013)

MD5校验和:9C34BB81857C78375582FAC0E1C8A95D

答案 1 :(得分:0)

我有另一个解决方案,允许您使用自动生成的列在DataGrid中显示枚举。这适用于使用反射创建的枚举类型。

首先,创建一个继承自EnumTemplateColumn

DataGridBoundColumn
public class EnumTemplateColumn : DataGridBoundColumn
{
    private readonly Type enumType;

    public EnumTemplateColumn(Type enumType)
    {
        this.enumType = enumType;
    }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        string columnHeader = cell.Column.Header.ToString();
        TextBlock textBlock = new TextBlock();
        var dataRowView = (DataRowView) dataItem;
        var enumValue = dataRowView[columnHeader];

        textBlock.Text = Enum.GetName(this.enumType, enumValue);

        return textBlock;
    }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        throw new NotImplementedException();
    }
}

接下来,使用OnAutoGeneratingColumn的{​​{1}}事件来使用DataGrid

EnumTemplateColumn

WPF组件:

    private void DataGrid_OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if (e.PropertyType.IsEnum)
        {
            e.Column = new EnumTemplateColumn(e.PropertyType)
            {
                Header = e.Column.Header,
            };
        }
    }

答案 2 :(得分:0)

我是这样做的:在 AutoGeneratingColumnDataGrid 事件中,将默认的 DataGridComboBoxColumn 替换为 DataGridTextColumn,并手动添加绑定和转换器。< /p>

    private void dataGrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if (e.PropertyType.IsEnum)
        {
            //(e.Column as DataGridComboBoxColumn)

            var col = new DataGridTextColumn
            {
                Header = e.PropertyName
            };

            col.Binding = new Binding(e.PropertyName)
            {
                Converter = new WPFCommon.BindingConverters.EnumConverter()
            };

            // Replace the auto-generated column with the new one.
            e.Column = col;
        }
    }

转换器类,

namespace WPFCommon.BindingConverters
{
    public class EnumConverter:IValueConverter
    {
        //** this does not work for enum value in DataTable
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null || string.IsNullOrEmpty(value.ToString()))
                return DependencyProperty.UnsetValue;

            return ((Enum)value).GetDescription();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }
    }
}

枚举扩展类,

public static class EnumExtensions
{
    public static string GetDisplayName(this Enum enu)
    {
        DisplayAttribute attr = GetDisplayAttribute(enu);
        return attr != null ? attr.Name : enu.ToString();
    }

    public static string GetDescription(this Enum enu)
    {
        DescriptionAttribute attr = GetDescriptionAttribute(enu);
        return attr != null ? attr.Description : enu.ToString();
    }

    private static DescriptionAttribute GetDescriptionAttribute(object value)
    {
        Type type = value.GetType();
        if (!type.IsEnum)
        {
            throw new ArgumentException(string.Format("Type {0} is not an enum", type));
        }

        // Get the enum field.
        var field = type.GetField(value.ToString());
        return field == null ? null : field.GetCustomAttribute<DescriptionAttribute>();
    }

    private static DisplayAttribute GetDisplayAttribute(object value)
    {
        Type type = value.GetType();
        if (!type.IsEnum)
        {
            throw new ArgumentException(string.Format("Type {0} is not an enum", type));
        }

        // Get the enum field.
        var field = type.GetField(value.ToString());
        return field == null ? null : field.GetCustomAttribute<DisplayAttribute>();
    }
}