You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将DataTable绑定到WinUI3的DataGrid控件?

WinUI3 DataGrid绑定DataTable解决方案

WinUI3的CommunityToolkit DataGrid要求ItemsSource实现IBindableIterable接口,而DataTable本身不满足这个约束,这就是绑定失败的核心原因。以下针对基础绑定和“表头为第一列而非第一行”的特殊需求给出具体实现方案:


一、基础绑定:将DataTable绑定到DataGrid

如果只需要实现DataTable的基础绑定(默认列头为DataTable的列名),可以通过以下两种方式处理:

1. ViewModel中转换为DataView

DataView实现了IBindableIterable,可以直接作为ItemsSource的绑定源:

private DataTable _dataTable;
// 暴露DataView给绑定
public DataView DataTableView => _dataTable?.DefaultView;

XAML绑定:

<controls:DataGrid 
    ItemsSource="{Binding DataTableView}" 
    AutoGenerateColumns="True"
    CanUserSortColumns="False" 
    CanUserReorderColumns="True"
    ... />

2. 使用ValueConverter转换DataTable

创建转换器类:

using Microsoft.UI.Xaml.Data;
using System.Data;

public class DataTableToDataViewConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return value is DataTable table ? table.DefaultView : null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

在页面资源中声明转换器:

<Page.Resources>
    <local:DataTableToDataViewConverter x:Key="DataTableConverter"/>
</Page.Resources>

绑定DataTable时应用转换器:

<controls:DataGrid 
    ItemsSource="{Binding DataTableViewModel, Converter={StaticResource DataTableConverter}}"
    AutoGenerateColumns="True"
    ... />

二、实现“表头为第一列”的需求

如果需要将DataTable的第一列内容作为每行的表头(或实现行列转置的表格展示),需要手动构建DataGrid的列,步骤如下:

1. 转置DataTable(按需选择)

如果需要将原表格的行列互换(原列名作为第一列,原行作为后续数据列),在ViewModel中实现转置逻辑:

public DataTable TransposedDataTable
{
    get
    {
        if (_dataTable == null) return null;
        
        var transposedTable = new DataTable();
        // 第一列存储原表格的列名(作为新表头)
        transposedTable.Columns.Add("Header");
        // 为原表格的每一行创建一个新列
        foreach (DataRow row in _dataTable.Rows)
        {
            transposedTable.Columns.Add(row[0].ToString());
        }
        // 将原表格的列转换为新表格的行
        foreach (DataColumn col in _dataTable.Columns)
        {
            var newRow = transposedTable.NewRow();
            newRow["Header"] = col.ColumnName;
            for (int i = 0; i < _dataTable.Rows.Count; i++)
            {
                newRow[i + 1] = _dataTable.Rows[i][col];
            }
            transposedTable.Rows.Add(newRow);
        }
        return transposedTable;
    }
}

2. 手动/动态生成DataGrid列

关闭自动列生成,手动定义第一列作为表头,再动态添加数据列:

方式1:使用Repeater动态生成列

确保项目引用WinUI的Repeater控件,XAML代码:

<controls:DataGrid 
    ItemsSource="{Binding TransposedDataTable.DefaultView}" 
    AutoGenerateColumns="False"
    ...>
    <!-- 固定第一列作为表头 -->
    <controls:DataGridTextColumn 
        Header="表头" 
        Binding="{Binding Header}" 
        IsReadOnly="True"/>
    <!-- 动态生成数据列 -->
    <controls:DataGrid.Columns>
        <x:Repeater ItemsSource="{Binding ColumnNames}">
            <x:Repeater.ItemTemplate>
                <DataTemplate>
                    <controls:DataGridTextColumn 
                        Header="{Binding}" 
                        Binding="{Binding [Binding]}" 
                        IsReadOnly="True"/>
                </DataTemplate>
            </x:Repeater.ItemTemplate>
        </x:Repeater>
    </controls:DataGrid.Columns>
</controls:DataGrid>

ViewModel中提供列名集合:

public ObservableCollection<string> ColumnNames { get; set; }

// 初始化时填充列名
ColumnNames = new ObservableCollection<string>(
    TransposedDataTable?.Columns.Cast<DataColumn>().Skip(1).Select(c => c.ColumnName) ?? Enumerable.Empty<string>()
);

方式2:代码后台动态添加列

在页面Loaded事件中添加列:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    var viewModel = (ViewModel)DataContext;
    if (viewModel.TransposedDataTable == null) return;

    // 添加固定表头列
    MyDataGrid.Columns.Add(new DataGridTextColumn 
    { 
        Header = "表头", 
        Binding = new Binding("Header"), 
        IsReadOnly = true 
    });

    // 动态添加数据列
    foreach (DataColumn col in viewModel.TransposedDataTable.Columns.Cast<DataColumn>().Skip(1))
    {
        MyDataGrid.Columns.Add(new DataGridTextColumn 
        { 
            Header = col.ColumnName, 
            Binding = new Binding($"[{col.ColumnName}]"), 
            IsReadOnly = true 
        });
    }
}

内容的提问来源于stack exchange,提问作者Enki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 06:09:19