WPF DataGrid 和 IAsyncEnumerable 项目

WPF DataGrid and IAsyncEnumerable items

可能吗? 怎么样?

我有一个异步方法从我的数据库中获取数据行。 我的结果是 IAsyncEnumerable<TItem>。 它应该是一种快速响应的完美数据类型 UI,但是 - 当我将它设置为我的网格的数据源时,它不起作用并且什么都不显示。

对此我有 2 个解决方法。首先显然是来自我的异步任务的 return 数组。第二个类似 - 我可以只对结果使用 ToArrayAsync()(来自 System.Linq.Async)。

我怀疑使用 ToArrayAsync() 比仅从任务中 returning 数组慢,所以它没有多大意义。

如果IAsyncEnumerable类型可以直接用作控件的数据源,那将很有意义。但是我可能需要实现某种 IObservable 接口或类似的东西。有人试过吗?

整个事情都很新,我找不到任何例子,甚至找不到一篇文章说它是可能的。我的意思是 - 如果您不能将它用于 UI,那么 IAsyncEnumerable 有什么用?

更新:我正在寻找的是 IAsyncEnumerable<TItem>ObservableCollection<TItem> 之间的转换。我找到了示例,但它们都完全按照我提到的解决方法工作 - 因此数据被放入数组中,然后添加到集合中。这会破坏所有 IAsyncEnumerable<T> 个好处。

引入

IAsyncEnumerable 以允许异步数据 generators/data 流。通常像 ItemsControl 这样显示数据项集合的控件是基于索引的。和 ICollectionView 基础。

通常控件通过原始集合的 ICollectionView 获取项目。由其在源集合 ICollectionView 中的索引标识的数据项被包装到 UIElement 容器中以进行呈现。
数据 stream/generator 不是基于索引的。 Enumerator(调用 IEnumerable.GetEnumerator 的结果)用于通过调用 IEnumerator.MoveNext 从一个元素步进到另一个元素(foreach 是一种语言结构,为了方便封装了实际的枚举涉及 IEnumerator).
的逻辑 除了异步数据流引入的潜在线程问题之外,基于索引的 ItemsControl 需要提前知道它的所有项目——这就是为什么你需要一个实现 INotifyCollectionChanged 的集合才能拥有 ItemsControl 更新其 Items 更改:视图被认为是被动的 - 它仅显示数据而不生成数据。
虽然不是强制性的,但 WPF 在设计时就考虑到了 MVVM。活动部分通常是模型或视图模型。数据生成通常发生在模型中。因此,将 IAsyncEnumerable 作为直接绑定源没有意义,因为这意味着被动 UI 元素必须直接 generate/consume 数据流。您可能希望这是视图模型/Binding.Source 的责任。同样,UI 旨在用于 ICollectionView 实现,而不是直接用于集合及其迭代器。

您可以做的是枚举 Binding.Source 中的 IAsyncEnumerable 并用生成的结果更新 ObservableCollection

public ObservableCollection<DataItem> ItemsSourceForDataGrid { get; }

private async Task GenerateDataItemsAsync(IAsyncEnumerable asyncDataStream)
{
  // Keep the GUI responsive while consuming an e.g. CPU intensive generator
  await foreach (DataItem item in asyncDataStream)
  {
    this.ItemsSourceForDataGrid.Add(item);
  }
}

另请注意,ToListAsyncToArrayAsync 等扩展方法可能会锁定应用程序。如果您不知道数据源,即生成器,您可能会在 ToListAsync 尝试完成数据流时锁定您的应用程序。但是根据定义,数据流可以是无限的,这将导致 ToListAsync 永远不会 return 或完成 returned Task 对象。如果您发现自己需要 ToArrayAsync 并且您是数据生成器的作者,那么您可能一开始就不应该使用 IAsyncEnumerable。像 ToArrayAsync 这样的异步终结器违背了 IAsyncEnumerable.

的想法