Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 大型wpf数据网格中移动/隐藏列的性能问题_C#_Wpfdatagrid - Fatal编程技术网

C# 大型wpf数据网格中移动/隐藏列的性能问题

C# 大型wpf数据网格中移动/隐藏列的性能问题,c#,wpfdatagrid,C#,Wpfdatagrid,我使用wpf datagrid显示大量数据(大约100列和1000行)。这些列绑定到使用TypeDescriptor动态添加的属性。默认情况下,datagrid显示所有列,但是我们添加了功能,允许用户仅查看所有列的子集,并且他们还可以更改显示列的顺序。我目前通过切换列的可见性属性并更改它们的displayindex来实现这一点。然而,这样做的表现真的很糟糕 下面是一个重现该问题的示例 XAML看起来非常直截了当 <Window x:Class="WpfDataGridTestApplica

我使用wpf datagrid显示大量数据(大约100列和1000行)。这些列绑定到使用TypeDescriptor动态添加的属性。默认情况下,datagrid显示所有列,但是我们添加了功能,允许用户仅查看所有列的子集,并且他们还可以更改显示列的顺序。我目前通过切换列的可见性属性并更改它们的displayindex来实现这一点。然而,这样做的表现真的很糟糕

下面是一个重现该问题的示例

XAML看起来非常直截了当

<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行…您必须考虑减少行数,然后问题就会消失。感谢您的建议。实际上,我们有一个选项可以将行分页为但是业务设计还需要一个选项,允许用户查看和比较所有的行(窗口通常延伸到两个监视器上,这样他们可以看到许多行)。我也有同样的问题,您找到了解决方法吗?谢谢您的回答。是的,我同意应该为大型数据网格启用虚拟化(或内存占用太高)。这归结为在启用虚拟化的情况下提高滚动性能。我已经尝试过延迟滚动。我认为这只会改变用户界面体验。无论哪种情况下,只要网格需要重新绘制,性能问题都会出现。如果您有能力,我们仍在试图找到解决滚动性能问题的方法若要了解任何情况,请更新。我们已经处理类似场景一段时间了。谢谢!