在 WPF DataGrid 中显示 3 维数据

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

我正在尝试通过

DataGrid
绑定在 WPF
DataTable
中显示 3 维数据。由于
DataGrid
只有行和列(2D),我的想法是对单元格进行模板化,以便它们托管
ListView
(或其他一些控件),并显示垂直堆叠的第三维值。

想要的结果是这样的:

这是一个带有模拟数据的高度简化但可重现的代码,我尝试创建这样一个

DataTable

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        ViewModel vm = new();

        MyDataGrid.DataContext = vm.Table.DefaultView;
        MyDataGrid.IsReadOnly = true;
    }

    public class ViewModel
    {
        public DataTable Table { get; init; }

        public ViewModel()
        {
            Table = new DataTable();

            Table.Columns.Add(" ");
            Table.Columns.Add("c1");
            Table.Columns.Add("c2");
            Table.Columns.Add("c3");

            for (int i = 1; i <= 3; i++ )
            {
                DataRow row = Table.NewRow();

                row[0] = new List<object>() { "r" + i } ;
                row[1] = new List<object>() { 10 * i, 20 * i, 25 * i } ;
                row[2] = new List<object>() { 12 * i, 26 * i, 30 * i } ;
                row[3] = new List<object>() { 16 * i, 28 * i, 36 * i };

                Table.Rows.Add(row);
            }
        }
    }
}

如您所见,我将 List 分配给每个单元格,想法是这创建了第三个维度,在单个单元格中存储多个值。

问题是,我不知道如何在 WPF 标记中对 DataGrid 进行模板化,以便正确解包并显示第三个维度,就像我上面显示的图像一样。我试过这个:

<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding}">
    <DataGrid.Resources>
        <DataTemplate x:Key="DataGridTemplate">
            <ListView ItemsSource="{Binding}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}"/>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </DataTemplate>
    </DataGrid.Resources>

    <DataGrid.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="ContentTemplate" Value="{StaticResource DataGridTemplate}"/>
        </Style>
    </DataGrid.CellStyle>
</DataGrid>

但是当我编译并运行它时,

DataGrid
只显示空单元格,即使没有绑定错误。如果我不使用任何模板,单元格将显示
System.Data.DataRowView System.Collections.Generic.List
1[System.Object]`。

如果有人可以看一下(我上面提供的代码是完全可重现的示例),并让我知道如何创建正确的模板,我将非常感激?或者,如果我以错误的方式处理这个问题,我也愿意接受其他建议。

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

您的代码存在一些问题。

1 - 为复杂列添加
Type

问题 1 是您的列未键入,这似乎导致

DataRow["c1"]
等显示为
string
类型的
System.Collections.Generic.List1[System.Int32]
值,而不是集合本身。请参阅下面的调试器屏幕截图:

您将需要更新这些列并添加如下所示的类型(请注意,我还命名了第一列,以便我们可以引用它)。

Table.Columns.Add("c0");
Table.Columns.Add("c1", typeof(IList));
Table.Columns.Add("c2", typeof(IList));
Table.Columns.Add("c3", typeof(IList));

2 - 使用
DataGridTemplateColumn
构建复杂的列

第二个挑战是我认为您无法通过自动生成的列来完成您想要的任务。如果我将您的

CellTemplate
更改为仅绑定到
TextBlock
,您可以看到这些单元格的数据上下文实际上是整个
DataRowView
对象,而不仅仅是绑定的列:

<DataGrid.Resources>
    <DataTemplate x:Key="DataGridTemplate">
        <TextBlock Text="{Binding}" />
    </DataTemplate>
</DataGrid.Resources>

更新您的

DataGrid
,如下所示,我能够生成我认为您正在寻找的内容。

<DataGrid x:Name="MyDataGrid"
            ItemsSource="{Binding}"
            AutoGenerateColumns="False">
    <DataGrid.Resources>
        <DataTemplate x:Key="DataGridTemplate">
            <ListView ItemsSource="{Binding}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </DataTemplate>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding c0}" />
        <DataGridTemplateColumn CellEditingTemplate="{StaticResource ResourceKey=DataGridTemplate}"
                                Header="c1">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ListView ItemsSource="{Binding c1}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn CellEditingTemplate="{StaticResource ResourceKey=DataGridTemplate}"
                                Header="c2">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ListView ItemsSource="{Binding c2}" />
                </DataTemplate>

            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn CellEditingTemplate="{StaticResource ResourceKey=DataGridTemplate}"
                                Header="c3">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ListView ItemsSource="{Binding c3}" />
                </DataTemplate>

            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

结果

© www.soinside.com 2019 - 2024. All rights reserved.