C# 大型wpf数据网格中移动/隐藏列的性能问题
我使用wpf datagrid显示大量数据(大约100列和1000行)。这些列绑定到使用TypeDescriptor动态添加的属性。默认情况下,datagrid显示所有列,但是我们添加了功能,允许用户仅查看所有列的子集,并且他们还可以更改显示列的顺序。我目前通过切换列的可见性属性并更改它们的displayindex来实现这一点。然而,这样做的表现真的很糟糕 下面是一个重现该问题的示例 XAML看起来非常直截了当C# 大型wpf数据网格中移动/隐藏列的性能问题,c#,wpfdatagrid,C#,Wpfdatagrid,我使用wpf datagrid显示大量数据(大约100列和1000行)。这些列绑定到使用TypeDescriptor动态添加的属性。默认情况下,datagrid显示所有列,但是我们添加了功能,允许用户仅查看所有列的子集,并且他们还可以更改显示列的顺序。我目前通过切换列的可见性属性并更改它们的displayindex来实现这一点。然而,这样做的表现真的很糟糕 下面是一个重现该问题的示例 XAML看起来非常直截了当 <Window x:Class="WpfDataGridTestApplica
<Window x:Class="WpfDataGridTestApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowState="Maximized">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Height="Auto" Margin="5">
<CheckBox x:Name="ApplyColumns" Width="200" Margin="5" Checked="CheckBox_Checked" Unchecked="CheckBox_Checked">Show Predefined Columns</CheckBox>
</StackPanel>
<DataGrid
x:Name="Grid" EnableColumnVirtualization="False"
EnableRowVirtualization="False"
Grid.Row="1" SelectionUnit="Cell"
ItemsSource="{Binding MyDataView}">
</DataGrid>
</Grid>
显示预定义列
背后的代码如下
public partial class MainWindow : Window
{
/// <summary>
/// this dictionary stores the column name of columns to display and their displayIndex
/// </summary>
Dictionary<string,int> _predefinedColumns=new Dictionary<string, int>()
{
{"Column_8",0},
{"Column_9",1},
{"Column_11",2},
{"Column_14",3},
{"Column_12",4},
{"Column_34",5},
{"Column_78",6},
{"Column_54",7},
{"Column_88",8},
{"Column_98",9},
{"Column_90",10},
{"Column_51",11},
{"Column_100",12},
{"Column_35",13},
{"Column_112",14},
{"Column_101",15}
};
public MainWindow()
{
InitializeComponent();
DataContext = new MyClassViewModel();
}
/// <summary>
/// Toggle display of only subset of columns
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
if (ApplyColumns.IsChecked ?? false)
{
foreach (var col in this.Grid.Columns)
{
if (_predefinedColumns.ContainsKey(col.Header as string))
{
col.Visibility = Visibility.Visible;
col.DisplayIndex = _predefinedColumns[col.Header as string];
}
else
{
col.Visibility = Visibility.Collapsed;
}
}
}
else
{
foreach (var col in this.Grid.Columns)
{
col.Visibility = Visibility.Visible;
var header = col.Header.ToString();
col.DisplayIndex = Int32.Parse(header.Substring(7)) - 1;
}
}
}
}
公共部分类主窗口:窗口
{
///
///此字典存储要显示的列的列名及其displayIndex
///
字典_predefinedColumns=新字典()
{
{“第8列”,0},
{“第9列”,第1},
{“第11列”,第2},
{“第14列”,第3},
{“第12列”,第4},
{“第34列”,5},
{“第78列”,6},
{“第54列”,7},
{“第88列”,8},
{“第98列”,9},
{“第90列”,第10},
{“第51列”,11},
{“第100列”,12},
{“第35栏”,13},
{“第112列”,14},
{“第101列”,15}
};
公共主窗口()
{
初始化组件();
DataContext=新的MyClassViewModel();
}
///
///切换仅显示列的子集
///
///
///
已选中私有无效复选框(对象发送方、路由目标方)
{
if(ApplyColumns.IsChecked??false)
{
foreach(此.Grid.Columns中的var col)
{
if(_预定义的columns.ContainsKey(col.Header作为字符串))
{
col.Visibility=可见性.Visibility;
col.DisplayIndex=_预定义的列[列标题作为字符串];
}
其他的
{
col.Visibility=可见性。已折叠;
}
}
}
其他的
{
foreach(此.Grid.Columns中的var col)
{
col.Visibility=可见性.Visibility;
var header=col.header.ToString();
col.DisplayIndex=Int32.Parse(header.Substring(7))-1;
}
}
}
}
此viewmodel使用手动创建的DataTable复制大数据。然而,在实际代码中,datagrid绑定到使用TypeDescriptor添加动态属性的类
public class MyClassViewModel
{
public DataView MyDataView
{
get
{
var dt = new DataTable();
foreach (var colNum in Enumerable.Range(1, 120))
{
dt.Columns.Add(String.Format("Column_{0}", colNum), Type.GetType("System.Int32"));
}
var r = new Random();
for (int x = 1; x <= 1000; x++)
{
var dr = dt.NewRow();
foreach (var colNum in Enumerable.Range(1, 120))
{
dr[String.Format("Column_{0}", colNum)] = r.Next(100);
}
dt.Rows.Add(dr);
}
return dt.DefaultView;
}
}
}
公共类MyClassViewModel
{
公共数据视图MyDataView
{
得到
{
var dt=新数据表();
foreach(可枚举范围(1120)中的var colNum)
{
Add(String.Format(“Column_{0}”,colNum),Type.GetType(“System.Int32”);
}
var r=新的随机变量();
对于(int x=1;x在使用更大的数据集时,您确实应该让虚拟化保持开启状态,否则,即使没有在屏幕上呈现,每个单元格都会经历布局/度量过程。我使用ScrollViewer.IsDeferredScrollingEnabled=“False”取得了一些成功调整滚动行为,但总体而言,WPF datagrid中大数据集的性能不太好。谁将同时看到1000行?每页至少25-100行…您必须考虑减少行数,然后问题就会消失。感谢您的建议。实际上,我们有一个选项可以将行分页为但是业务设计还需要一个选项,允许用户查看和比较所有的行(窗口通常延伸到两个监视器上,这样他们可以看到许多行)。我也有同样的问题,您找到了解决方法吗?谢谢您的回答。是的,我同意应该为大型数据网格启用虚拟化(或内存占用太高)。这归结为在启用虚拟化的情况下提高滚动性能。我已经尝试过延迟滚动。我认为这只会改变用户界面体验。无论哪种情况下,只要网格需要重新绘制,性能问题都会出现。如果您有能力,我们仍在试图找到解决滚动性能问题的方法若要了解任何情况,请更新。我们已经处理类似场景一段时间了。谢谢!