使用autogenerated datagrid

时间:2015-05-13 14:20:54

标签: c# wpf datagrid enums

我看到Description attribute on enum values in WPF DataGrid with AutoGenerateColumns但是对于使用Enum的自动生成的列没有答案。我尝试过几种不同的方法但没有成功。

我基本上只想在自动生成的列中显示枚举的Description属性。

我已经尝试过将DataTemplates用于单元格和细胞,单元格工作正常,它会按照预期的描述值显示文本块。然而,细胞模板中的组合框不能正确结合。奇怪的是,当我切换它们并使用cellediting模板进行celltemplate时,它在组合框中显示正确的值。似乎传递给celleditingtemplate的绑定值是整个datagridrow。

是否有办法缩小范围,以便我可以提取枚举类型并将其传递给转换器以填充所选项目的列表或...

我已经在墙上撞了一会儿,已经无处可去了!

if (e.PropertyType.IsEnum)
{
    EnumDataGridTemplateColumn col = new EnumDataGridTemplateColumn();
    col.ColumnName = e.PropertyName;
    col.SortMemberPath = e.PropertyName;
    col.CellTemplate = (DataTemplate)FindResource("EnumDataGridTemplate");
    col.CellEditingTemplate = (DataTemplate)FindResource("EnumDataGridTemplateEdit");
    e.Column = col;
}

在AutoGeneratingColumn中,模板的xaml是:

<DataTemplate x:Key="EnumDataGridTemplate">
    <ContentPresenter Content="{Binding Path=., Mode=OneWay, Converter={StaticResource enumToStringConverter}}" VerticalAlignment="Center"/>
</DataTemplate>

<DataTemplate x:Key="EnumDataGridTemplateEdit">
    <ComboBox
            ItemsSource="{Binding Path=., Converter={StaticResource enumToListConverter}}"
            SelectedItem="{Binding Path=., Mode=TwoWay}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock  Text="{Binding Path=.,Mode=OneWay,
                        Converter={StaticResource enumToStringConverter}}"
                        VerticalAlignment="Center"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</DataTemplate>

不确定我应该采用不同的方法吗?

转换器:

public class EnumToListConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        if (value is Enum)
        {
            return EnumConverter.EnumToList(value.GetType());
        }
        return EnumConverter.EnumToList(typeof(dummy));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new Exception("Cant convert back");
    }
}

这里的问题是传递给转换器的值是viewmodel,而不是预期的单个属性(就像在celltemplate中一样)。

public class EnumDataGridTemplateColumn : DataGridTemplateColumn
{
    public string ColumnName
    {
        get;
        set;
    }

    public Type enumType
    {
        get;
        set;
    }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        // The DataGridTemplateColumn uses ContentPresenter with your DataTemplate.
        ContentPresenter cp = (ContentPresenter)base.GenerateElement(cell, dataItem);
        // Reset the Binding to the specific column. The default binding is to the DataRowView.
        BindingOperations.SetBinding(cp, ContentPresenter.ContentProperty, new Binding(this.ColumnName));
        return cp;
    }
}

非常感谢任何帮助。

谢谢。

1 个答案:

答案 0 :(得分:1)

我最终不得不在代码中完全构建自定义模板。不理想,但功能齐全:

    private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if (dataGridColumnInfo.ColumnInfo == null) return;

        try
        {
            string headername = e.Column.Header.ToString();

            bool cancel = true;

            foreach (ColumnInfo colInfo in dataGridColumnInfo.ColumnInfo)
            {
                if (colInfo.PropertyName != e.PropertyName) continue;
                cancel = false;
                if (e.PropertyType.IsEnum)
                {
                    var templateColumn = new DataGridTemplateColumn();
                    templateColumn.Header = colInfo.Header;
                    templateColumn.CellTemplate = this.BuildCustomCellTemplate(colInfo.PropertyName);
                    templateColumn.CellEditingTemplate = this.BuildCustomCellEditTemplate(colInfo.PropertyName, e.PropertyType);
                    templateColumn.SortMemberPath = colInfo.PropertyName;
                    e.Column = templateColumn;
                }
                colInfo.Apply(e.Column);
                break;
            }

            e.Cancel = cancel;
        }
        catch (Exception ex)
        {
            Log.CreateError("WPF", ex, Log.Priority.Emergency);
            throw;
        }
    }

    // builds custom template
    private DataTemplate BuildCustomCellTemplate(string columnName)
    {
        var template = new DataTemplate();

        var textBlock = new FrameworkElementFactory(typeof(TextBlock));
        template.VisualTree = textBlock;

        var binding = new Binding();
        binding.Path = new PropertyPath(columnName);
        binding.Converter = new EnumToStringConverter();
        textBlock.SetValue(TextBlock.TextProperty, binding);
        textBlock.SetValue(TextBlock.MarginProperty, new Thickness(0, 0, 6, 0)); 
        return template;
    }

    private DataTemplate BuildCustomCellEditTemplate(string columnName, Type enumType)
    {
        var template = new DataTemplate();
        var itemTemplate = new DataTemplate();

        var comboBox = new FrameworkElementFactory(typeof(ComboBox));
        template.VisualTree = comboBox;

        var enumList = Enum.GetValues(enumType);
        var binding = new Binding();
        binding.Source = enumList;
        comboBox.SetValue(ComboBox.ItemsSourceProperty, binding);


        var valueBinding = new Binding();
        valueBinding.Path = new PropertyPath(columnName);
        valueBinding.Mode = BindingMode.TwoWay;
        comboBox.SetValue(ComboBox.SelectedItemProperty, valueBinding);

        // Squeeze the pretty combobox in the cell
        comboBox.SetValue(ComboBox.MarginProperty, new Thickness(0));
        comboBox.SetValue(ComboBox.PaddingProperty, new Thickness(0));
        comboBox.SetValue(ComboBox.ItemTemplateProperty, itemTemplate);

        // Add the content presenter that will show the pretty value
        var content = new FrameworkElementFactory(typeof(ContentPresenter));
        itemTemplate.VisualTree = content;
        var contentBinding = new Binding();
        contentBinding.Path = new PropertyPath(".");
        contentBinding.Converter = new EnumToStringConverter();
        contentBinding.Mode = BindingMode.OneWay;
        content.SetValue(ContentPresenter.ContentProperty, contentBinding);
        content.SetValue(ContentPresenter.MarginProperty, new Thickness(0, 0, 6, 0));
        return template;
    }