WPF DataGrid doesn't create columns for ICustomTypeDescriptor properties (but Winforms DataGridView does)

As the name suggests, I have a DataGrid and ViewModel that both implement ICustomTypeDescriptor, adding a few properties at runtime.

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;
    }

}

      

DataGrid definition in XAML:

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

      

I have set ItemsSource like this:

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;

      

where is controller.PartCloneSettingsControllers

defined as:

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

      

For debugging purposes, I created a DataGridView on the Winforms control host and bound the same ViewModel to it, and voila: Winforms grid creates all columns and displays the data as I want, but WPF DataGrid cannot create columns for my custom properties (it works with normal , normal properties).

Does anyone have a working solution using DataGrid, ICustomTypeDescriptor and AutoGenerateColumns = True (if I create columns manually in XAML it works great and I can bind to all my properties ...)

+3


source to share


1 answer


If yours PartCloneSettingsControllers

is a generic set of some item type other than object

, it will use the generic parameter type to populate the columns, as opposed to the collection item runtime type.

For example, if your collection is IEnumerable<PartCloneSettingsController>

, the grid will only populate columns for properties declared in typePartCloneSettingsController

(and its base types) 1 . It will not check for actual objects in the collection, and since it ICustomTypeDescriptor

provides instance-level properties, the grid will not see those properties.

If you have the ability to expose your "dynamic" properties at the type or collection level instead of the element instance level (for example using TypeDescriptionProvider

or ITypedList

), this is probably your best bet. Otherwise, you will have to use a collection type for which the grid cannot infer the element type (for example List<object>

); which will force the grid to check the first element it encounters to figure out what the columns should be.




1 Ultimately the grid resolves properties using TypeDescriptor.GetProperties(Type componentType)

, as opposed to TypeDescriptor.GetProperties(object component)

, so without the actual element to check, it cannot know which "dynamic" properties are displayed by the individual elements.

+4


source







All Articles