未显示动态DataGrid列的显示名称

时间:2016-08-04 10:57:40

标签: c# wpf

先决条件:.Net Framework 4.5.1

我正在使用ITypedListICustomTypeDescriptorDataGrid动态生成列。为了提供用户友好的列名,我创建了向其构造函数提供DisplayNameAttribute的属性描述符,如下例所示。虽然调试器显示PropertyDescriptor.DisplayName属性获取我在属性DataGrid中提供的属性但不考虑此值,仍然显示属性名称而不是属性显示名称。我有什么想法吗?

示例WDataGridTest.xaml

<Window x:Class="Local.WGridViewTest"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:Local"
        Title="WGridViewTest" Height="300" Width="300">
    <Window.Resources>
        <l:DataTable x:Key="DataTable"/>
    </Window.Resources>
    <Grid>
        <DataGrid ItemsSource="{StaticResource ResourceKey=DataTable}"/>
    </Grid>
</Window>

WDataGridTest.xaml.cs背后的代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;

namespace Local {
    /// <summary>Interaction logic for WGridViewTest.xaml</summary>
    public partial class WGridViewTest : Window {
        public WGridViewTest() {
            InitializeComponent();
        }
    }

    public class DataTable : BindingList<DataRow>, ITypedList {
        private PropertyDescriptorCollection _PropertyDescriptors;

        public DataTable() :
            base() {
            AllowNew = false;
            AllowRemove = false;
            AllowEdit = true;
            _PropertyDescriptors = new PropertyDescriptorCollection(new PropertyDescriptor[0], false);
            _PropertyDescriptors.Add(new DataValuePropertyDescriptor("Column1"));
            _PropertyDescriptors.Add(new DataValuePropertyDescriptor("Column2"));
            _PropertyDescriptors.Add(new DataValuePropertyDescriptor("Column3"));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
        }

        #region ITypedList implementation
        public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] ListAccessors) {
            return _PropertyDescriptors;
        }
        public string GetListName(PropertyDescriptor[] ListAccessors) {
            return "Data Table";
        }
        #endregion ITypedList implementation
    }

    public class DataRow : ICustomTypeDescriptor {
        public DataRow(DataTable DataTable) {
            this.DataTable = DataTable;
        }

        public DataTable DataTable {
            get;
            private set;
        }

        public object GetValue(string ColumnName) {
            return String.Concat(ColumnName, "@", GetHashCode());
        }

        public void SetValue(string ColumnName, object Value) {
        }

        #region ICustomTypeDescriptor implementation
        public AttributeCollection GetAttributes() { return AttributeCollection.Empty; }
        public string GetClassName() { return GetType().FullName; }
        public string GetComponentName() { return GetType().Name; }
        public TypeConverter GetConverter() { return null; }
        public EventDescriptor GetDefaultEvent() { return null; }
        public PropertyDescriptor GetDefaultProperty() { return null; }
        public object GetEditor(Type EditorBaseType) { return null; }
        public EventDescriptorCollection GetEvents(Attribute[] Attributes) { return EventDescriptorCollection.Empty; }
        public EventDescriptorCollection GetEvents() { return EventDescriptorCollection.Empty; }
        public PropertyDescriptorCollection GetProperties(Attribute[] Attributes) { return DataTable.GetItemProperties(null); }
        public PropertyDescriptorCollection GetProperties() { return DataTable.GetItemProperties(null); }
        public object GetPropertyOwner(PropertyDescriptor PropertyDescriptor) { return this; }
        #endregion Property value tracking
    }

    public class DataValuePropertyDescriptor : PropertyDescriptor {
        public DataValuePropertyDescriptor(string Name) :
            base(Name, new Attribute[] { new DisplayNameAttribute(String.Concat("Display: ", Name)) }) {
        }

        #region PropertyDescriptor implementation
        public override Type ComponentType { get { return typeof(DataRow); } }
        public override Type PropertyType { get { return typeof(string); } }
        public override bool IsReadOnly { get { return false; } }
        public override bool CanResetValue(object DataRow) { return true; }
        public override object GetValue(object DataRow) { return ((DataRow)DataRow).GetValue(Name); }
        public override void ResetValue(object DataRow) { ((DataRow)DataRow).SetValue(Name, null); }
        public override void SetValue(object DataRow, object Value) { ((DataRow)DataRow).SetValue(Name, Value); }
        public override bool ShouldSerializeValue(object DataRow) { return false; }
        #endregion PropertyDescriptor implementation
    }
}

结果看起来像这样。
enter image description here

1 个答案:

答案 0 :(得分:0)

在具有相同结果的其他几个配置上尝试此示例后,我最终覆盖了默认列模板,如下所示。如果有人也会看到这个问题,这就是解决方法,但是应该记住,它会耦合到aero主题,因为Windows 7上没有aero2。如果你不需要支持windows 7,只需要替换aero aero2在您的项目中引用适当的程序集。

WDataGridTest.xaml

<Window x:Class="Local.WDataGridTest"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Local"
        xmlns:data="clr-namespace:System.Data;assembly=System.Data"
        xmlns:themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" 
        Title="WGridViewTest" Height="300" Width="300">
    <Window.Resources>
        <local:DataTable x:Key="DataTable"/>
        <local:DataColumnDisplayNameConverter x:Key="DataColumnDisplayNameConverter"/>
        <Style x:Key="DataGridColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
            <Setter Property="Width" Value="8"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Cursor" Value="SizeWE"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                        <Grid>
                            <themes:DataGridHeaderBorder BorderBrush="{TemplateBinding BorderBrush}" 
                                                         BorderThickness="{TemplateBinding BorderThickness}" 
                                                         Background="{TemplateBinding Background}" 
                                                         IsClickable="{TemplateBinding CanUserSort}" 
                                                         IsPressed="{TemplateBinding IsPressed}" 
                                                         IsHovered="{TemplateBinding IsMouseOver}" 
                                                         Padding="{TemplateBinding Padding}" 
                                                         SortDirection="{TemplateBinding SortDirection}" 
                                                         SeparatorBrush="{TemplateBinding SeparatorBrush}" 
                                                         SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
                                <TextBlock HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                           VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                           TextAlignment="Center"
                                           SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                           Text="{Binding Converter={StaticResource ResourceKey=DataColumnDisplayNameConverter}, ConverterParameter={StaticResource ResourceKey=DataTable}}"
                                           TextWrapping="Wrap"/>
                            </themes:DataGridHeaderBorder>
                            <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource DataGridColumnHeaderGripperStyle}"/>
                            <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource DataGridColumnHeaderGripperStyle}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <DataGrid ItemsSource="{Binding Source={StaticResource ResourceKey=DataTable}}" ColumnHeaderStyle="{StaticResource ResourceKey=DataGridColumnHeaderStyle}"/>
    </Grid>
</Window>

WDataGridTest.xaml.cs背后的代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
using System.Globalization;
using System.ComponentModel;

namespace Local {
    /// <summary>Interaction logic for WDataGridTest.xaml</summary>
    public partial class WDataGridTest : Window {
        public WDataGridTest() {
            InitializeComponent();
        }
    }

    public class DataTable : BindingList<DataRow>, ITypedList {
        private PropertyDescriptorCollection _PropertyDescriptors;

        public DataTable() :
            base() {
            AllowNew = false;
            AllowRemove = false;
            AllowEdit = true;
            _PropertyDescriptors = new PropertyDescriptorCollection(new PropertyDescriptor[0], false);
            _PropertyDescriptors.Add(new DataValuePropertyDescriptor("Column1"));
            _PropertyDescriptors.Add(new DataValuePropertyDescriptor("Column1"));
            _PropertyDescriptors.Add(new DataValuePropertyDescriptor("Column1"));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
            Items.Add(new DataRow(this));
        }

        #region ITypedList implementation
        public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] ListAccessors) {
            return _PropertyDescriptors;
        }
        public string GetListName(PropertyDescriptor[] ListAccessors) {
            return "Data Table";
        }
        #endregion ITypedList implementation
    }

    public class DataRow : ICustomTypeDescriptor {
        public DataRow(DataTable DataTable) {
            this.DataTable = DataTable;
        }

        public DataTable DataTable {
            get;
            private set;
        }

        public object GetValue(string ColumnName) {
            return string.Concat(ColumnName, "@", GetHashCode());
        }

        public void SetValue(string ColumnName, object Value) {
        }

        #region ICustomTypeDescriptor implementation
        public AttributeCollection GetAttributes() { return AttributeCollection.Empty; }
        public string GetClassName() { return GetType().FullName; }
        public string GetComponentName() { return GetType().Name; }
        public TypeConverter GetConverter() { return null; }
        public EventDescriptor GetDefaultEvent() { return null; }
        public PropertyDescriptor GetDefaultProperty() { return null; }
        public object GetEditor(Type EditorBaseType) { return null; }
        public EventDescriptorCollection GetEvents(Attribute[] Attributes) { return EventDescriptorCollection.Empty; }
        public EventDescriptorCollection GetEvents() { return EventDescriptorCollection.Empty; }
        public PropertyDescriptorCollection GetProperties(Attribute[] Attributes) { return DataTable.GetItemProperties(null); }
        public PropertyDescriptorCollection GetProperties() { return DataTable.GetItemProperties(null); }
        public object GetPropertyOwner(PropertyDescriptor PropertyDescriptor) { return this; }
        #endregion Property value tracking
    }

    public class DataValuePropertyDescriptor : PropertyDescriptor {
        public DataValuePropertyDescriptor(string Name) :
            base(Name, new Attribute[] { new DisplayNameAttribute(string.Concat("Display: ", Name)) }) {
        }

        #region PropertyDescriptor implementation
        public override Type ComponentType { get { return typeof(DataRow); } }
        public override Type PropertyType { get { return typeof(string); } }
        public override bool IsReadOnly { get { return false; } }
        public override bool CanResetValue(object DataRow) { return true; }
        public override object GetValue(object DataRow) { return ((DataRow)DataRow).GetValue(Name); }
        public override void ResetValue(object DataRow) { ((DataRow)DataRow).SetValue(Name, null); }
        public override void SetValue(object DataRow, object Value) { ((DataRow)DataRow).SetValue(Name, Value); }
        public override bool ShouldSerializeValue(object DataRow) { return false; }
        #endregion PropertyDescriptor implementation
    }

    public class DataColumnDisplayNameConverter : IValueConverter {
        public DataColumnDisplayNameConverter()
            : base() {
        }

        public object Convert(object Value, Type TargetType, object Parameter, CultureInfo Culture) {
            DataTable table = (DataTable)Parameter;
            string property = (string)Value;
            foreach (PropertyDescriptor descriptor in table.GetItemProperties(null)) {
                if (property == descriptor.Name) {
                    return descriptor.DisplayName;
                }
            }
            return DependencyProperty.UnsetValue;
        }

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