在代码隐藏中绑定到 DataTable 时,DataGrid 会部分更新

问题描述 投票:0回答:1

我有一个 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 用户控件的实例。任何想法将不胜感激。

c# wpf data-binding datatable datagrid
1个回答
0
投票

当您定义列时,您就是在执行此操作,显式定义列。不要将其与

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>
© www.soinside.com 2019 - 2024. All rights reserved.