C# 如何惰性地评估wpf:DataGrid,仅在需要时检索数据

C# 如何惰性地评估wpf:DataGrid,仅在需要时检索数据,c#,wpf,datagrid,wpfdatagrid,lazy-evaluation,C#,Wpf,Datagrid,Wpfdatagrid,Lazy Evaluation,我有一个WPF数据网格,绑定到一个由数据库中的linq to sql填充的列表。绑定是双向的,允许用户更改每行中的值 <wpf:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding MyList}" SelectedItem="{Binding SelectedItem}" > 当显示大约20000行时,程序会在初始化列表时发生内存不足异常

我有一个WPF数据网格,绑定到一个由数据库中的linq to sql填充的列表。绑定是双向的,允许用户更改每行中的值

        <wpf:DataGrid AutoGenerateColumns="False" 
              ItemsSource="{Binding MyList}" 
              SelectedItem="{Binding SelectedItem}" >

当显示大约20000行时,程序会在初始化列表时发生内存不足异常而崩溃。即使行数减少,性能也会变得非常慢

我知道在初始化时,datagrid会迭代每一行,以测量最大列宽和其他属性。它显然会对所有行执行此操作,而不管它们是否在屏幕上

我尝试将数据网格绑定到
myQuery.ToList()
(允许通过单击列对数据网格进行排序)或直接绑定到IQueryable。(排序与此不起作用)

两者产生相同的结果。仅包含20000个项目的ToList()不会导致大量内存消耗,只有当它绑定到datagrid时才会发生这种情况

忽略datagrid中20000行有多有用的问题(这些是当前的需求;要更改这些需求,请使用一个工作示例)

最简单的方法是什么,只懒洋洋地加载屏幕上当前显示的数据,并忽略所有其他内容,直到滚动到视图中

这可以在没有第三方库和主要代码更改的情况下完成吗


如果不是,建议的解决方法是什么?

在本例中绑定的属性假设您的
MyList
由MyFile对象(
List
)组成,那么您必须创建MyFile类,如下所示:

 class MyFile
    {
        public string FullPath { get; set; }

        public string Extension
        {
            get
            {
                return Path.GetExtension(FullPath);
            }
        }

        public string PathRoot
        {
            get
            {
                return Path.GetPathRoot(FullPath);
            }
        }

        public DateTime CreationTime
        {
            get
            {
                return File.GetCreationTime(FullPath);
            }
        }

    }

这样,您将在每个对象中存储较少的信息,并对网格中显示的少数项调用get方法。而不是将实际值存储在类中。希望这有帮助

事实证明,问题完全是我的用户错误:

WPF Datagrid可以很好地进行UI虚拟化:仅在需要时才绘制消耗内存的行对象;如果一行在datagrid的可见边界之外,它将不会被实例化

但是,如果datagrid包含在ScrollViewer中,则这将不起作用。 在scrollviewer中,datagrid的每个部分实际上都是可见的,因此将呈现整个datagrid。然后,scrollviewer仅显示此渲染数据网格中适合UI窗口的部分

由于scrollviewer中的datagrid看起来就像是管理自己的滚动条的datagrid,所以我没有注意到scrollviewer

移除scrollviewer后,即使高度和宽度可变,大量行也不会产生任何问题。datagrid只填充可用空间,只根据需要实例化新行


简而言之,我的问题的解决方案是:不要在scrollviewer中放置datagrid

您需要datagrid吗?数据网格是一只猪。ListView Gridview将一部分资源作为DataGrid。您是否给DataGrid一个*高度,因为如果这样,它将不会虚拟化。确保获得垂直滚动条并转到GridView。@不确定是否需要DataGrid,但根据和DataGrid将是默认选择,因为我需要编辑和排序。我需要设置什么样的高度?我得到了一个滚动条好。与GridView你需要实现排序,但这并不难。GridView不支持编辑。我要做的是在右边有一个编辑细节,在那里他们可以编辑所选的行。用户喜欢速度(而不是锁定)。@Blam不幸的是,MS Excel允许就地编辑,并且对大量数据没有问题,因此用户可以直接指向Excel并说它应该像我说的那样工作,列表本身可以毫无问题地放入内存中。内存消耗仅在将其绑定到datagrid时发生。据我所知,因为datagrid将在初始化时遍历每一行,并检索和存储渲染信息。因此,在每个对象中存储更少不会改变任何事情,使用我展示的技术,您不会存储更少。您将在网格中显示所需的内容时加载这些内容。此技术将显著提高网格上的性能。