0

由于我对 WPF 和 MVVM 很陌生,这可能是非常明显和微不足道的事情,所以请耐心等待。

无论如何,我有一个具有这些属性的视图模型:

class ViewModel : INotifyPropertyChanged {
    ICollectionView Items; // a list of Items object, wraps _items field, each Item has a Date property
    string Filter; // a filter key, wraps _filter field and calls ApplyFilter() as it is changed
    void ApplyFilter(); // based on the filter key, _items.Filter gets set to some predicate
}

属性在设置时引发 PropertyChanged 事件以及所有常见的 MVVM 内容。在视图中,我有一个简单的 ItemsControl,它绑定到 Items 属性,以及一些花哨的数据模板来显示每个 Item。

已请求显示按天分组的项目,以便您看到每天的日期标题以及其 Date 属性与标题中的日期相对应的项目列表。

由于这严格来说是一个显示问题,因此我决定保留视图模型,但使用转换器将 ICollectionView 项转换为字典,其中键是日期,集合是具有该日期的项的子集。

ItemsControl 现在有一个 StackPanel 和一个 TextBlock 来显示日期标题(字典键)和另一个 ItemsControl,它基本上是旧版本的副本,它只列出了项目(字典值)。

视图渲染得很好,但过滤器不再起作用。由于控件绑定到项目,并且 ICollectionView 实现了 INotifyCollectionChanged,我希望过滤器在更改项目列表时工作,并且转换器将重新运行以重建字典。好吧,事实并非如此。更改过滤器确实调用 ApplyFilter(),并且 _items.Filter 被设置为所需的谓词,但视图永远不会改变。我也尝试过从 ApplyFilter 调用 Items 的 PropertyChanged,但这也不起作用。

显然,我设计的这个应该如何工作的场景是错误的,老实说,我没有想法,除了创建将日期和项目列表作为属性的新对象,然后使用 VM 中的列表。但是,正如我所说,在我看来,这完全是一个视图问题,所以模型只需要提供一个项目列表,视图的责任就是决定如何呈现它们。

非常感谢任何帮助,并在此先感谢您。

编辑:现在我在想,如果我要更改 _filter.Filter,那么项目的 PropertyChanged 事件实际上永远不会引发,因为它实际上没有改变(内部结构已经改变,但项目本身仍然是相同的ICollectionView)。因此,转换器不再被触发。

如果是这种情况,我该如何触发转换器?在执行 ApplyFilter() 之后提高 Items 的 PropertyChanged 也没有做任何事情。

4

1 回答 1

1

也许使用 ListView 而不是简单的 ItemsControl+converter 是更好的主意?ListView 有很多不错的功能。如虚拟化、分组等。您所要做的就是修改您的ICollectionView分组属性并应用模板(GroupStyle)

至于您的问题,您当前的行为对我来说很有意义。如果你想重新运行转换器,你应该创建新方法 RefreshBinding() 并做这样的事情;

var referenceCopy = Items;
Items = null;//make sure INotifyPropertyCHanged is fired.
Items = referenceCopy; //converter should be called again. 

在您需要重新运行转换器后,您将调用它。但老实说,只需使用 ICollectionView+Grouping 属性和 ListView。或者您可以自己实现 ListView 功能。使用转换器似乎不是一个好的解决方案。

于 2012-08-24T10:30:10.180 回答