WPF DataGrid动态列基于对象类型和亚型



我正在构建一个WPF软件来管理电子组件的库存。

我有以下结构:

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

电阻和电容器是部分的亚型。

我将DataGrid绑定到ObservableCollection<Part>,并使用ListCollectionView添加过滤和分组功能。

我要完成的工作是当我过滤ListCollectionView仅获取Resistor子类型时,我希望DataGrid更新其列以显示Resistor类型的属性,并且它的基础类Part(因此,我将获得列列制造商,党派,电阻和功率)。同时,如果我过滤ListCollectionView以获取Capacitor子类型,则DataGrid应具有Capacitor类公共属性和Part公共属性(制造商,Partnumber,电容和电压)。最后,如果没有使用过滤,DataGrid将仅显示Part属性(制造商和Partnumber)。

我尝试使用AutoGenerateColumns=true,但是DataGrid仅显示Part属性,即使我过滤ListCollectionView仅具有Resistors。我还尝试将ObservableCollection的类型更改为dynamic,并且也不起作用。

如何根据ObservableCollection中包含的对象的类型更改DataGrid列?

这是一种方法。不要自动生成列。设置每个可能的列。然后将每列的可见性绑定到确定列是否可见的转换器。

    <FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
    <DataGrid x:Name="dataGrid" ItemsSource="{Binding PartCollection}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Manufacturer" Binding="{Binding Manufacturer}"/>
            <DataGridTextColumn Header="Part Number" Binding="{Binding PartNumber}" />
            <DataGridTextColumn Header="Power" Binding="{Binding Power}" Visibility="{Binding DataContext.PartCollection, Source={x:Reference dummyElement}, Converter={StaticResource ColumnVisibility}, ConverterParameter=Resistor}"/>
            <DataGridTextColumn Header="Resistance" Binding="{Binding Resistance}" Visibility="{Binding DataContext.PartCollection, Source={x:Reference dummyElement}, Converter={StaticResource ColumnVisibility}, ConverterParameter=Resistor}"/>
            <DataGridTextColumn Header="Capacitance" Binding="{Binding Capacitance}" Visibility="{Binding DataContext.PartCollection, Source={x:Reference dummyElement}, Converter={StaticResource ColumnVisibility}, ConverterParameter=Capacitor}"/>
            <DataGridTextColumn Header="Voltage" Binding="{Binding Voltage}" Visibility="{Binding DataContext.PartCollection, Source={x:Reference dummyElement}, Converter={StaticResource ColumnVisibility}, ConverterParameter=Capacitor}"/>
        </DataGrid.Columns>
    </DataGrid>

这是转换器的静态资源...

<Window.Resources>
    <local:ColumnVisibilityConverter x:Key="ColumnVisibility"/>
</Window.Resources>

这是转换器...

    public class ColumnVisibilityConverter : IValueConverter
    {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        ObservableCollection<Part> collection = value as ObservableCollection<Part>;
        string collectionType = parameter as string;
        if(collection != null && collectionType != null && collection.Count > 0)
        {
            switch(collectionType)
            {
                case "Resistor": return collection[0].GetType() == typeof(Resistor) ? Visibility.Visible : Visibility.Hidden;
                case "Capacitor": return collection[0].GetType() == typeof(Capacitor) ? Visibility.Visible : Visibility.Hidden;
                default: return Visibility.Hidden;
            }
        }
        return Visibility.Hidden;
    }

我对数据网格列的可见性有些挣扎。在此处找到答案:wpf

中datagridcolumn的绑定可见性

在我看来,手动设置列是最佳实践。如果您真的想自动化它们,那么还有另一种方法可以做到这一点。您可以在集合上实现一个iCustomTypedScriptor,以返回集合中包含的派生类型的属性的属性描述器。

这是使用自动化的解决方案。只需在可观察的集合上实现ItypedList界面...

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

相关内容

  • 没有找到相关文章

最新更新