3

如标题所示,我有一个 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;
    }

}

XAML 中的 DataGrid 定义:

<DataGrid x:Name="dataGrid" AutoGenerateColumns="True"  />

我这样设置 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;

其中controller.PartCloneSettingsControllers定义为:

public ObservableCollection<PartCloneSettingsController> PartCloneSettingsControllers {  get; private set; }

出于调试目的,我在 Winforms 控件主机中创建了一个 DataGridView 并将相同的 ViewModel 附加到它,瞧:Winforms 网格创建所有列并按我想要的方式显示数据,但是 WPF DataGrid 无法为我的自定义属性生成列(它适用于普通的普通属性)。

是否有人有使用 DataGrid、ICustomTypeDescriptor 和 AutoGenerateColumns=True 的工作解决方案(如果我在 XAML 中手动生成列,它工作正常,我可以绑定到我的所有属性......)

4

1 回答 1

6

如果您PartCloneSettingsControllers是除 之外的某些项类型的泛型集合object,它将使用泛型参数类型来填充列,而不是集合中项的运行时类型。

例如,如果您的集合是 1 IEnumerable<PartCloneSettingsController>,则网格将仅填充在PartCloneSettingsController 类型(及其基类型)上声明的属性的列1。它不会打扰检查集合中的实际对象,并且由于ICustomTypeDescriptor在实例级别公开属性,网格将看不到这些属性。

如果您可以选择在类型或集合级别而不是项目实例级别公开您的“动态”属性(例如,通过使用TypeDescriptionProvideror ITypedList),那可能是您最好的选择。否则,您将不得不使用网格无法推断项目类型的集合类型(例如,List<object>);这将迫使网格检查它遇到的第一个项目,以确定列应该是什么。


1网格最终使用TypeDescriptor.GetProperties(Type componentType)而不是 来解析属性TypeDescriptor.GetProperties(object component),因此如果没有要检查的实际项目,它无法知道各个项目公开了哪些“动态”属性。

于 2014-10-15T13:58:28.020 回答