我有一个DataGrid,我用DataView填充(使用DataContext)。我试图在一个单独的线程中做到这一点,但UI仍然冻结。我想在填充DataGrid时阻止UI冻结。
这是我到目前为止的代码:
private void btnOK_Click(object sender, RoutedEventArgs e)
{
GetFieldsBLL getFieldsBLL = new GetFieldsBLL();
DataView dv = getFieldsBLL.GetWholeView(ViewName);
Task task = new Task(() => ucDataExtracViewControl.PopulateGrid(dv));
task.Start();
}
public void PopulateGrid(DataView dv)
{
dgView.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate{
dgView.Columns.Clear();
dgView.AutoGenerateColumns = false;
foreach (DataColumn column in dv.Table.Columns)
{
var gridColumn = new DataGridTextColumn()
{
Header = column.ColumnName,
Binding = new Binding("[" + column.ColumnName + "]")
};
dgView.Columns.Add(gridColumn);
}
dgView.DataContext = dv;
DataView = dv;
}));
}
提前致谢!
编辑: 我重新创建列的原因是因为某些列名称的名称中有一个点。例如,“作业编号”在使用绑定时不会产生任何数据。在此处阅读更多内容:What is it about DataTable Column Names with dots that makes them unsuitable for WPF's DataGrid control?不能对数据库进行更改。 -
答案 0 :(得分:2)
我在WPF DataGrid上做了很多工作,渲染是一个问题。最后,渲染时间将减少到您要显示的列数和行数。当DataGrid呈现它必须绘制每个时,这意味着加载和测量内容的大小。
我发现通过设置固定的列宽和行高可以提高速度。当与下面的DelayedDataGridTextColumn结合使用时,UI线程几乎没有阻塞,因为每个单元格都是单独呈现的,因此允许在具有更高优先级的UI线程上发生其他事情。
public class DelayedDataGridTextColumn : DataGridTextColumn
{
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
var textBlock = new TextBlock();
textBlock.SetValue(FrameworkElement.StyleProperty, ElementStyle);
Dispatcher.BeginInvoke(
DispatcherPriority.Loaded,
new Action<TextBlock>(x => x.SetBinding(TextBlock.TextProperty, Binding)),
textBlock);
return textBlock;
}
}
请注意,您可以调整DispatcherPriority以适应所需的渲染速度。优先级越低,您获得的幕布效果越多。优先级越高,渲染时处理的其他项就越少。
答案 1 :(得分:1)
将DispatcherPriority更改为背景。
dgView.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(delegate{
// your code
};
答案 2 :(得分:0)
你实际上并没有在一个单独的线程中运行它,因为你要做的第一件事是将它发送回UI-Thread
问题是为什么你自己重新创建列?
这确实会产生与将AutoGenerateColumns
设置为true无关的结果吗?
如果您正确使用WPF的绑定功能,我认为您可以改进这一点,但只有很少的代码可以对此做出好的建议。
答案 3 :(得分:0)
您可以使用BackgroundWorker类来执行后台进程:
将以下任务分配给DoWork回调
将UI更新代码(dgView.DataContext = dv;)移至RunWorkerCompleted回调。
注意:您需要为DataView创建一个类变量,以便它可以用于DoWork和RunWorkerCompleted回调。
答案 4 :(得分:0)
我解决了这个问题。 C# 代码不是 UI 冻结的原因,而是 DataGrid 上记录的呈现。
放
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
ScrollViewer.CanContentScroll="True"
在数据网格中
实际上,DataGrid 冻结了大数据上的 UI。所以启用虚拟化可以解决问题