【问题标题】:LINQ filtering in IEnumerable property breaks bindingIEnumerable 属性中的 LINQ 过滤会破坏绑定
【发布时间】:2013-07-19 20:45:34
【问题描述】:

我的 UI 中有一个 TextBlock 绑定到属性的 .Count() 扩展名。我想为该属性添加 LINQ 过滤,但这样做会破坏绑定。

这可以正常工作并更新 UI:

public IEnumerable<Worker> WorkersTest
{
    get
    {
        return DataManager.Data.Workers; 
    }
}

添加 LINQ 过滤后,WorkersTest 不会更新 TextBlock,尽管 MessageBox 确认属性正在被修改。但是,在初始化数据时,值会正确显示:

public IEnumerable<Worker> WorkersTest
{
    get
    {
        return DataManager.Data.Workers.Where(w => w.Gender == Gender.Male); 
    }
}

有什么方法可以在不破坏绑定的情况下保持 LINQ 过滤?

更新:我需要澄清的一件事是DataManager.Data.WorkersObservableCollection

据我所知,任何 LINQ 操作都会破坏绑定,但 AsEnumerable() 除外,它没有任何效果。

另外,对于 Andres 的回答,Count() 不是问题所在。如果我将此属性绑定到DataGrid,我会得到相同的结果。使用 LINQ,它不会更新。没有 LINQ,它确实如此。是否有任何解决方法,最好是不涉及ICollectionView 或任何类似性质的解决方法?

更新: 有人知道Where 等LINQ 扩展在使用时是否返回新对象?我无法在网上找到任何有关此的文档。但是,如果是这种情况,那可能就是问题所在。

更新:我插入了一个断点,发现了一些可能有用的有趣信息:

没有 LINQ:

使用 LINQ:

也许这可以揭示真正发生的事情,并希望让我更接近解决方案。

假设CollectionChangedPropertyChanged 为空是问题的根源,我是否正确?如果是这样,我该怎么做才能解决这个问题?

【问题讨论】:

  • 你的绑定模式设置了吗?模式=双向。
  • 这会引发 InvalidOperationException。 Count 属性是只读的。
  • Linq 查询将是惰性的,在评估之前它什么都不做,即调用 ToList()。绑定到这样的查询也不是很好。绑定到在 INotifyPropertyChanged 中引发 PropertyChanged 事件的属性:msdn.microsoft.com/en-us/library/… 这将告诉 UI 它需要更新。
  • 问题是集合的setter永远不会被调用。

标签: c# linq ienumerable


【解决方案1】:

您的问题源于不了解可观察的集合。 DataManager.Data.WorkersObservableCollection 或类似的东西。这意味着,它会在添加/删除项目时引发事件。然后 UI 可以监听这些事件并进行适当的更新。

LINQ 对可观察集合一无所知。它只是一次以一种方式读取数据并将其转换为新的集合。因此,使用 LINQ 进行过滤是行不通的。或者至少不是没有某种黑客攻击。

肯定有几种方法,例如Filtering an ObservableCollection?Sorts and filters on ObservableCollection。但没有什么比在上面扔一个简单的 LINQ 更容易的了。或者Reactive Extensions 可以在这里为您提供帮助。但是我从来没有使用过它,所以我不知道设置一个过滤的 observable 集合有多容易。

【讨论】:

  • 我不喜欢 CollectionViews,因为它们必须手动刷新。我今天发现了一个名为 OLinq 的扩展,它允许 LINQ 是可绑定的。我正在尝试,所以我们会看看结果如何。如果有一种方法可以自动刷新一个完美的 CollectionView ......不幸的是我还没有找到方法。
【解决方案2】:

尝试在 Where 子句的末尾添加 .ToList()。

return DataManager.Data.Workers.Where(w => w.Gender == Gender.Male).ToList(); 

不允许绑定到方法,因此可能发生的情况是您绑定到 Count 属性而不是方法。 List 包含 Count 属性,而 IEnumerable 不包含。

【讨论】:

  • 原版可能有效,因为DataManager.Data.Workers 是一个列表。
  • 对不起,我应该澄清DataManager.Data.WorkersObservableCollection。我尝试将其更改为列表并添加ToList(),但它仍然不起作用。
  • 实际上,添加 ToList() 会破坏第一个示例的绑定(没有 LINQ)。
  • 另外,当数据初始化时,它会显示正确的值。它只是不更新​​。
猜你喜欢
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 2010-12-25
  • 2012-02-06
  • 1970-01-01
  • 2021-10-09
  • 2016-07-01
  • 2016-12-17
相关资源
最近更新 更多