c# WPF DataGrid -将类中的字典处理成数据网格中的列组件
本文关键字:数据 数据网 网格 组件 处理 字典 WPF DataGrid | 更新日期: 2023-09-27 17:55:02
我正在尝试使用WPF的Datagrid来显示对象的内容。通常,当您试图显示某些内容时,这是非常简单的,当类是这样的:
class Employee
{
public string Name { get; set; }
public string Phone { get; set; }
public bool Active { get; set; }
}
然而,假设你有更复杂的东西,像这样:
class Employee
{
public Employee()
{
SecurityAccesses = new public Dictionary<string, bool>();
}
public string Name { get; set; }
public string Phone { get; set; }
public bool Active { get; set; }
public Dictionary<string, bool> SecurityAccesses { get; }
}
如果你将它分配给ItemSource, DataGrid将不知道如何处理securityaccess,并且将只显示一个名为securityaccess的列,单元格将显示为一个集合。
我想做的是让Datagrid意识到它应该获得字典的所有键来显示列名,当然还有要在Datagrid中作为复选框显示的值。
我可以用一些代码来做到这一点,但我正试图尽可能多地使用XAML,所以是否有一种方法可以做到这一点。非常感谢您的推荐。
您是否可以在您的Datagrid列中尝试以下方法
<DataGrid.Columns>
<DataGridTextColumn Header="Key" Binding="{Binding Path=[Key]}" />
<DataGridTextColumn Header="Value" Binding="{Binding Path=[Value]}" />
</DataGrid.Columns>
你的DataGrid可以绑定到一个可观察集合employees。然后,您的员工DataGrid可以包含一个DataGridTemplateColumn,该DataGrid包含绑定到每个员工的securityaccess属性的(子)DataGrid。子DataGrid的数据上下文将是绑定到父DataGrid行上的单个雇员。比如:
<DataGrid ItemsSource="{Binding Employees}" ... >
<DataGrid.Columns>
<DataGridTextColumn Header="Access" Binding="{Binding Path=Key}" />
<!-- more Employee columns here -->
<DataGridTemplateColumn Header="SecurityAccesses">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid AutoGenerateColumns="False" CanUserAddRows="False"
CanUserDeleteRows="False" ItemsSource="{Binding SecurityAccesses}">
<DataGrid.Columns>
<DataGridTextColumn Header="Access" Binding="{Binding Path=Key}" />
<ComboBox Margin="4" ItemsSource="{Binding Value,
NotifyOnTargetUpdated=True,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
为了跟进那些试图帮助我的人,我发现了一个试图做我想做的事情的人的例子:
http://blogs.msmvps.com/deborahk/populating-a-datagrid-with-dynamic-columns-in-a-silverlight-application-using-mvvm/我重用了本例中指定的几乎所有内容,除了用于组成列列表的部分。我没有从指定列名的地方创建一个单独的字符串列表,而是重用了模型并实现了一个转换器,用于从模型中获取字符串列表。下面是xaml代码:
<DataGrid ItemsSource="{Binding LeftLegPartsAnomalies}"
AutoGenerateColumns="False"
IsReadOnly="{Binding IsFormCanBeAccessed, Converter={StaticResource NegateBooleanConverter}}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding LegPartName}" Header="Name" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}},
Path=DataContext.LeftLegPartsAnomalies,
Converter={StaticResource LegPartsAnomaliesToListAnomaliesNameConverter}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="70">
<TextBlock Text="{Binding}" TextAlignment="Center"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Anomalies}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="70">
<CheckBox Margin="20,0,0,0" IsChecked="{Binding Spotted}" HorizontalAlignment="Center" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
获取字符串列表的"魔法"是在LegPartsAnomaliesToListAnomaliesNameConverter:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var listLegParts = value as ObservableCollection<LegPartAnomaly>;
if (listLegParts == null || listLegParts.Count == 0)
return null;
List<string> convertedList = new List<string>();
foreach (var legPart in listLegParts)
{
foreach (var anomaly in legPart.Anomalies)
{
if(convertedList.Contains(anomaly.Name))
{
continue;
}
convertedList.Add(anomaly.Name);
}
}
return convertedList;
}
从我的可观察集合LeftLegPartsAnomalies中,我获得了内部定义的所有异常,并提取了每个异常的名称(一次,不允许重复)。这是转换器的工作!
顺便说一下,我知道这与安全访问无关。我使用安全访问的例子并不是为了详细说明我所做的事情,但是主体是一样的。
谢谢你的帮助!