Я создаю программное обеспечение 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
публичные свойства ( Производитель, номер детали, емкость и напряжение). Наконец, если фильтрация не применяется, DataGrid
будет отображать только свойства Part
(Manufacturer и PartNumber).
Я пытался использовать AutoGenerateColumns=true
, но DataGrid
показывает только свойства Part
, даже если я фильтрую ListCollectionView
, чтобы иметь только Resistors
. Я также попытался изменить тип ObservableCollection
на dynamic
, но это тоже не сработало.
Как я могу изменить столбцы DataGrid
в зависимости от типа объекта, содержащегося в ObservableCollection
?
2 ответа
Вот решение с использованием автогенерации. Просто реализуйте интерфейс 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";
}
}
Вот один из способов сделать это. Не создавать автоматически столбцы. Настройте каждый столбец, который возможен. Затем свяжите видимость каждого столбца с конвертером, который определяет, является ли столбец видимым.
<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;
}
Я немного боролся с привязкой видимости к столбцу таблицы данных. Нашел ответ здесь: Видимость привязки для DataGridColumn в WPF
На мой взгляд, установка колонок вручную - лучшая практика. Если вы действительно хотите их сгенерировать, есть другой способ сделать это. Вы можете реализовать ICustomTypeDescriptor в своей коллекции, чтобы возвращать PropertyDescriptors для свойств производного типа, который содержится в коллекции.
Похожие вопросы
Связанные вопросы
Новые вопросы
wpf
Windows Presentation Foundation, или WPF, является подсистемой для визуализации пользовательских интерфейсов в приложениях на основе Windows.