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

WPF DataGrid加载40×40数据耗时超1秒,UI冻结求优化方案

WPF DataGrid加载时保持UI响应的解决方案

针对40×40规模DataGrid加载导致UI冻结的问题,核心原因是列创建、数据绑定及布局渲染都在UI线程同步执行,阻塞了消息循环。以下是几个直接有效的解决思路:

1. 异步分步处理列创建

将列的创建拆分为异步步骤,利用Dispatcher的后台优先级让UI线程能同时处理其他交互:

修改DataGrid_Initialized方法:

private async void DataGrid_Initialized(object? sender, EventArgs e)
{
    dataGrid.ItemsSource = viewModel.Rows;
    dataGrid.AutoGenerateColumns = false;
    
    // 后台优先级分步创建列,避免阻塞UI
    for (int i = 0; i < ViewModel.numcol; ++i)
    {
        await Application.Current.Dispatcher.InvokeAsync(() =>
        {
            var col = new DataGridTextColumn();
            var binding = new Binding($"Columns[{i}]");
            col.Binding = binding;
            col.Header = $"Column {i}";
            col.Width = 80;
            dataGrid.Columns.Add(col);
        }, DispatcherPriority.Background);
        
        // 每创建5列让出一次线程,可根据情况调整间隔
        if (i % 5 == 0)
            await Task.Delay(1);
    }
}

2. 提前初始化DataGrid与列

不在点击按钮时临时创建DataGrid,而是在窗口初始化阶段完成列配置,点击时仅将其加入VisualTree并异步绑定数据:

修改MainWindow代码:

DataGrid? dataGrid;
ViewModel viewModel;
public MainWindow()
{
    InitializeComponent();
    viewModel = new ViewModel();
    
    // 提前创建并配置DataGrid列
    dataGrid = new DataGrid();
    dataGrid.AutoGenerateColumns = false;
    dataGrid.EnableRowVirtualization = true;
    dataGrid.EnableColumnVirtualization = true;
    
    for (int i = 0; i < ViewModel.numcol; ++i)
    {
        var col = new DataGridTextColumn();
        var binding = new Binding($"Columns[{i}]");
        col.Binding = binding;
        col.Header = $"Column {i}";
        col.Width = 80;
        dataGrid.Columns.Add(col);
    }
}

private async void Button_Click(object sender, RoutedEventArgs e)
{
    myContentControl.Content = dataGrid;
    
    // 异步绑定数据源,让UI先完成布局渲染
    await Application.Current.Dispatcher.InvokeAsync(() =>
    {
        dataGrid.ItemsSource = viewModel.Rows;
    }, DispatcherPriority.Background);
}

3. 启用DataGrid虚拟化

最大化窗口时DataGrid会渲染所有行,启用虚拟化后仅渲染可见区域元素,大幅减少视觉树节点数量:

在创建DataGrid时添加以下配置:

dataGrid.EnableRowVirtualization = true;
dataGrid.EnableColumnVirtualization = true;
dataGrid.VirtualizingStackPanel.VirtualizationMode = VirtualizationMode.Recycling;

4. 优化数据结构

如果数据不需要动态修改,将ObservableCollection<double>替换为普通List<double>或数组,减少不必要的通知开销:

修改ViewModel中的RowType:

public class RowType
{
    public IReadOnlyList<double> Columns { get; }

    public RowType(IReadOnlyList<double> columns)
    {
        Columns = columns;
    }
}

创建数据时改用List:

public ViewModel()
{
    Random autoRand = new Random();
    _Rows = new ObservableCollection<RowType>();

    for (int icol = 0; icol < numcol;++icol)
    {
        var rows = new List<double>();
        for (int irow = 0; irow < numrow; ++irow)
        {
            rows.Add(autoRand.NextDouble());
        }
        _Rows.Add(new RowType(rows));
    }
}

以上方案可以单独或组合使用,核心是让UI线程在加载过程中能处理用户输入,避免完全冻结。

内容的提问来源于stack exchange,提问作者J. Manzanero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 13:37:01