我有一个 WPF 窗口,其中一个 DataGrid 作为其子窗口之一。 DataGrid 中的列数仅在运行时确定。这是我的 window.xaml 文件中的 DataGrid 代码:
<DataGrid Name="pathLossGrid"
AutoGenerateColumns="True"
ItemsSource="{Binding }"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
HorizontalAlignment="Center"
GridLinesVisibility="All">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:PathLossCell/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
在 Windows.xaml.cs 中,我声明了 DataTable 属性的依赖属性:
public static DependencyProperty PathLossTableProperty = DependencyProperty.Register(nameof(PathLossTable), typeof(DataTable), typeof(PathLossSelector));
public DataTable PathLossTable
{
get => (DataTable)GetValue(PathLossTableProperty);
set => SetValue(PathLossTableProperty, value);
}
此时我应该注意,DataGrid 中的每个单元格都是自定义用户控件类型,我在示例代码中将其称为 PathLossCell,并且该用户控件是一个具有两列的简单网格:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.8*"/>
<ColumnDefinition Width="0.2*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding S2pId }"
MinWidth="50"/>
<Button Grid.Column="1"
Margin="3 0 0 0"
Command="{Binding SelectS2pFileCommand}">
<Viewbox Stretch="Uniform">
<ContentControl Content="{DynamicResource icon_plus}"/>
</Viewbox>
</Button>
</Grid>
我的 Windows.xaml.cs 文件的构造函数调用以下方法:
public void InitPathLossTable()
{
if (PathLossTable == null && SelectedPortList != null)
{
var tmpTable = new DataTable("pathLossTable");
foreach (var port in SelectedPortList)
{
var portLoss = 0;
DataColumn newColumn = new DataColumn($"{port} (Max Loss= {portLoss} dB)");
newColumn.DataType = typeof(PathLossCell);
tmpTable.Columns.Add(newColumn);
}
//add default row
DataRow newRow = tmpTable.NewRow();
for (int col = 0; col < tmpTable.Columns.Count; col++)
{
newRow[col] = new PathLossCell() { S2pFile = "no data", RowId = 0, ColumnId = col, PortName = tmpTable.Columns[col].ColumnName };
}
tmpTable.Rows.Add(newRow);
PathLossTable = tmpTable;
pathLossGrid.DataContext = PathLossTable.DefaultView;
}
}
根据我对此站点和其他来源的研究,这是将 DataTable 绑定到 DataGrid 的方法,我期望在窗口中看到的是一个具有 2 或 3 列的网格(取决于 SelectedPortList 中的项目数)和一行默认的 PathLossCell 项。运行此代码时,我看到的是一个具有正确列数(和正确的列标题)的表格,但只有位置 [0,0] 的单元格具有 PathLossCell 控件它和所有其他单元格显示 PathLossCell 的完全限定类型字符串,并以某种方式显示额外的行:
我尝试直接在 xaml 中将绑定设置为: ItemsSource="{Binding PathLossTable.DefaultView }",结果没有明显差异,也不包含 DataGridTemplateColumn 定义,在这种情况下,我什至看不到该定义第一列中的 PathLossCell 用户控件的实例。任何想法将不胜感激。
当您定义列时,您就是在执行此操作,显式定义列。不要将其与
DataTemplate
混淆,例如对于所有细胞。
如果将
DataGrid.AutogenerateColumns
设置为 true
,则 DataGrid
将通过向每列的 DataGridTextColumn
集合添加 DataGrid.Columns
来为您生成列定义。正如名称 DataGridTextColumn
所示,它仅显示文本(单元格项目的 object.ToString
值)。如果您需要更复杂的列布局,您可以定义支持自定义列布局的DataGridTemplateColumn
。这就是为什么名称DataGridTemplateColumn
包含“模板”一词。它不是所有列的模板,而是特定列定义的模板。
要为
DataGrid
的所有单元格创建默认模板,您只需为 Style
提供 DataGridCell
并将其分配给 DataGrid.CellStyle
属性即可。
关于您的
DataGrid.ItemsSource
绑定,您不必显式绑定到 DataTable.DataView
属性。绑定后会自动获取数据视图。
<DataGrid ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=PathLossTable}">
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<!-- The DataContext is the current cell value (not the row item) -->
<local:PathLossCell/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
</DataGrid>