her*_*zig 3 c# wpf datagrid icustomtypedescriptor
就像标题中一样,我有一个DataGrid和一个实现ICustomTypeDescriptor的ViewModel,并在运行时添加了一些属性。
public class PartCloneSettingsController : BaseController, ICustomTypeDescriptor
{
...
private List<StringPropertyDescriptor> generatedProperties;
private void generateProperties()
{
foreach (PartAttributeDefinition item in PartAttributes.DefinedAttributes)
{
var propertyDescriptor = new StringPropertyDescriptor(item.AttributeTitle, typeof(PartCloneSettingsController), item);
// attach value changed handler [ memory leak? TODO: Remove handler at some point...]
propertyDescriptor.AddValueChanged(this, OnGeneratedPropertyChanged);
generatedProperties.Add(propertyDescriptor);
}
}
public PropertyDescriptorCollection GetProperties()
{
// Get All Default (defined) properties
var properties = TypeDescriptor.GetProperties(this, true);
// concat default properties and generated properties into a single collection
var newProperties = new PropertyDescriptorCollection(properties.Cast<PropertyDescriptor>().Concat(generatedProperties).ToArray());
return newProperties;
}
}
Run Code Online (Sandbox Code Playgroud)
XAML中的DataGrid定义:
<DataGrid x:Name="dataGrid" AutoGenerateColumns="True" />
Run Code Online (Sandbox Code Playgroud)
我将ItemsSource设置如下:
controller.LoadAssembly(ofd.FileName); // loads the file and creates a ObservableCollection of PartCloneSettingsControllers...
// set data grid source, doesn't create columns for generated properties...
overviewGrid.ItemsSource = controller.PartCloneSettingsControllers
// set data source from a winforms DataGridView which generates columns properly...
((System.Windows.Forms.DataGridView)wfhost.Child).DataSource = controller.PartCloneSettingsControllers;
Run Code Online (Sandbox Code Playgroud)
其中controller.PartCloneSettingsControllers
定义为:
public ObservableCollection<PartCloneSettingsController> PartCloneSettingsControllers { get; private set; }
Run Code Online (Sandbox Code Playgroud)
出于调试目的,我在Winforms控件主机中创建了一个DataGridView并将相同的ViewModel附加到该主机上,瞧:Winforms网格创建所有列并根据需要显示数据,但是WPF DataGrid无法为我的自定义属性生成列(适用于普通的普通属性)。
是否有人使用DataGrid,ICustomTypeDescriptor和AutoGenerateColumns = True有可行的解决方案(如果我在XAML中手动生成列,则可以正常工作,并且可以绑定到我的所有属性...)
如果您PartCloneSettingsControllers
是而不是某些项目类型的通用集合object
,则它将使用通用参数类型来填充列,而不是集合中的项目的运行时类型。
例如,如果您的集合是an IEnumerable<PartCloneSettingsController>
,那么网格将仅填充PartCloneSettingsController
类型(及其基本类型)1上声明的属性的列。它不会打扰检查集合中的实际对象,并且由于ICustomTypeDescriptor
在实例级别公开了属性,因此网格将看不到那些属性。
如果您可以选择在类型或集合级别而不是在项目实例级别(例如,使用TypeDescriptionProvider
或ITypedList
)公开“动态”属性,那可能是最好的选择。否则,您将不得不使用网格无法推断项目类型的集合类型(例如List<object>
);这将迫使网格检查遇到的第一个项目,以找出列应该是什么。
1网格最终使用TypeDescriptor.GetProperties(Type componentType)
而不是来解析属性TypeDescriptor.GetProperties(object component)
,因此,如果没有要检查的实际项目,它就无法知道各个项目公开了哪些“动态”属性。