先决条件:.Net Framework 4.5.1
我正在使用ITypedList
和ICustomTypeDescriptor
来DataGrid
动态生成列。为了提供用户友好的列名,我创建了向其构造函数提供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
}
}
答案 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();
}
}
}