【问题标题】:How to lazy-evaluate a wpf:DataGrid, retrieving data only as needed如何延迟评估 wpf:DataGrid,仅根据需要检索数据
【发布时间】:2012-05-12 10:47:07
【问题描述】:

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

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

当显示大约 20000 行时,程序在列表初始化期间因内存不足异常而崩溃。即使行数较少,性能也会变得难以忍受。

我知道在初始化时数据网格会遍历每一行以测量最大列宽和其他属性。无论它们是否在屏幕上,它显然都会对所有行执行此操作。

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

两者产生相同的结果。仅具有 20000 个项目的 ToList() 不会导致大量内存消耗,只有在绑定到数据网格时才会发生这种情况。

忽略数据网格中的 20000 行有多大用处的问题(这些是当前要求;更改这些工作示例会有所帮助)。

什么是最简单的方法来延迟加载当前显示在屏幕上的数据,而忽略其他所有内容,直到它被滚动到视图中?

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

如果不是,推荐的解决方法是什么?

【问题讨论】:

  • 你需要DataGrid吗? DataGrid 是一头猪。 ListView Gridview 将一小部分资源作为DataGrid。您是否给 DataGrid 一个 * 高度,因为如果是这样,它将不会虚拟化。确保获得垂直滚动条并转到 GridView。
  • @Blam 不确定我是否需要DataGrid,但根据this answerthis answer,Datagrid 将是默认选择,因为我想要编辑和排序。我需要设置什么样的高度?我得到一个滚动条了。
  • 使用 GridView 您需要实现排序,但这并不难。 GridView 不支持编辑。我所做的是在右侧有一个编辑详细信息,他们可以在其中编辑所选行。用户喜欢速度(而不是锁定)。
  • @Blam 不幸的是 MS Excel 允许就地编辑并且对大量数据没有问题,因此用户只需指向 Excel 并说它应该像那样工作

标签: c# wpf datagrid wpfdatagrid lazy-evaluation


【解决方案1】:

在这种情况下,您绑定的属性假设您的 MyList 由 MyFile 对象 (List&lt;MyFile&gt;) 组成,那么您必须将 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 方法。与将实际值存储在类中相比。希望这会有所帮助

【讨论】:

  • 正如我所说,列表本身可以毫无问题地放入内存中。内存消耗仅在将其绑定到数据网格时发生。据我所知,因为 datagrid 在初始化时将遍历每一行并检索和存储渲染信息。所以在每个对象中存储更少不会改变任何东西
  • 使用我展示的技术,您并没有减少存储量。您将加载您需要的东西,因为它们显示在网格中。这种技术应该会显着提高网格的性能。
【解决方案2】:

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

WPF Datagrid 可以很好地进行 UI 虚拟化:仅在需要时才绘制消耗内存的行对象;如果一行超出数据网格的可见范围,则不会实例化。

但是,如果数据网格包含在 ScrollViewer 中,这将不起作用。 在滚动查看器中,数据网格的每个部分都是虚拟可见的,因此将呈现整个数据网格。然后,滚动查看器仅显示此渲染数据网格中适合 UI 窗口的部分。

由于滚动查看器中的数据网格看起来就像管理自己的滚动条的数据网格,所以我没有注意到滚动查看器。

移除滚动查看器后,即使高度和宽度可变,大量行也不会有任何问题。数据网格只是填充可用空间,并且只根据需要实例化新行。

简而言之,我的问题的解决方案是:不要将数据网格放在滚动查看器中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多