2017-02-28 81 views
1

我正在构建一个WPF软件来管理电子元件库存。WPF DataGrid基于对象类型和子类型的动态列

我有以下结构:

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(所以我会得到列制造商,PartNumber,电阻和电源)。同时,如果我筛选ListCollectionView以获得Capacitor子类型,则DataGrid应具有Capacitor类公共属性和Part公共属性(制造商,零件编号,电容和电压)。 最后,如果没有应用过滤,DataGrid将只显示Part属性(制造商和部件编号)。

我试图用AutoGenerateColumns=trueDataGrid只显示Part特性,即使我过滤ListCollectionView只具有Resistors。我也尝试将ObservableCollection的类型更改为dynamic,但它也不起作用。

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

回答

1

这是使用autogenerate的解决方案。只需在可观察集合上实现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"; 
    } 
} 
+0

这工作,但GetItemProperties仅在应用程序启动时调用。我需要在每次应用从ObservableCollection获取的ListViewCollection过滤时刷新它。这可能吗? – RHaguiuda

+1

是的,但不是很优雅... dataGrid.ItemsSource = null; dataGrid.ItemsSource = PartCollection; – AQuirky

+0

谢谢。很好地工作。 – RHaguiuda

2

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

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

我有点挣扎与结合能见度数据网格柱。找到答案在这里:Binding Visibility for DataGridColumn in WPF

设置列手动在我看来是最好的做法。如果你真的想自动生成它们,还有另一种方法可以做到这一点。您可以在集合上实现ICustomTypeDescriptor,以返回PropertyDescriptors以获取集合中包含的派生类型的属性。

+0

我用你的想法来创建布尔属性并将列可见性绑定到该属性。成功了! – RHaguiuda