wpfdatagridobservablecollectionlistcollectionview

WPF DataGrid dynamic columns based on object type and subtype


I'm building a WPF software to manage a stock of electronics components.

I have the following structure:

public class Part
{
    public string Manufacturer { get; set; }
    public string PartNumber { get; set; }
}
public class Resistor : Part
{
    public string Resistance { get; set;}
    public string Power { get; set;}
} 
public class Capacitor : Part
{
    public string Capacitance { get; set; }
    public string Voltage { get; set; }
}

Resistor and Capacitor are subtypes of Part.

I'm binding a DataGrid to an ObservableCollection<Part>, and using a ListCollectionView to add filtering and grouping functionality.

What I'm trying to accomplish is when I filter the ListCollectionView to get only the Resistor subtype, I want the DataGrid to update it's columns to show the properties of Resistor type and it's base class Part (so I would get the columns Manufacturer, PartNumber, Resistance and Power). At the same time, if I filter the ListCollectionView to get Capacitor subtype, the DataGrid should have the Capacitor class public properties and the Part public properties (Manufacturer, PartNumber, Capacitance and Voltage). Finally, If there's no filtering applied, the DataGrid would show only Part properties (Manufacturer and PartNumber).

I tried to use the AutoGenerateColumns=true but the DataGrid only shows Part properties, even if I filter the ListCollectionView to have only Resistors. I also tried to change the type of the ObservableCollection to dynamic and it didn't work either.

How can I change the DataGrid columns based on type of the object contained in the ObservableCollection?


Solution

  • Here is the solution using autogenerate. Simply implement the ITypedList interface on the observable collection...

    public class Parts : ObservableCollection<Part>, ITypedList
    {
        public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
        {
            if(Count == 0)
            {
                return TypeDescriptor.GetProperties(typeof(Part));
            }
            else
            {
                PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(this[0]);
                return pdc;
            }
        }
    
        public string GetListName(PropertyDescriptor[] listAccessors)
        {
            return "Parts";
        }
    }