【问题标题】:How can I hook a WPF UserControl to an event of a bound ViewModel object?如何将 WPF UserControl 挂钩到绑定 ViewModel 对象的事件?
【发布时间】:2012-07-19 15:45:52
【问题描述】:

假设我有一个 UserControl 和一个 DependencyProperty 来绑定到一个 ObservableCollection<Foo> 对象。 Foo 对象的集合实际上被发送到某个 Flash ActiveX 对象。因此,我不能“WPF 绑定”到 Foo 对象的属性。

当 Foo 对象的属性由 UserControl 以外的其他对象更新时,我希望通知 UserControl 以便它刷新(即将所有 Foo 对象重新发送到 Flash 对象)。

我不太确定如何处理这个问题。我能想到两种不太明显的可能性:

  1. UserControl 订阅了包含ObservableCollection<Foo> 对象的对象的某些事件。每当 Foo 对象的属性发生更改时,该事件就会触发,因此 UserControl 会知道将 Foo 对象重新发送到 Flash 对象。

  2. 让 UserControl 订阅 ObservableCOllection 对象的 CollectionChanged 事件,不知何故会导致 ObservableCOllection<Foo> 对象使用 Action NotifyCollectionChangedAction.Reset 引发事件。

    void OnFooCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (!_flashIsLoaded)
            return;
    
        if (e.Action == NotifyCollectionChangedAction.Reset) {
            ClearAndSendFoos(this, Foos);
            return;
        }
        ....
    

知道如何完成上述两项工作,或者如何让 UserControl 知道是时候刷新集合了吗?

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    这里似乎有些不对劲。你用 MVVM 标记了这篇文章,所以我想你正在使用它。

    看,使用 Model、View、ViewModel,您应该在 ViewModel 和 Model 之间完成这项工作。因此 ViewModel 将订阅模型的事件并进行更新。如果 Model 没有这样的事件,那么继承它并添加它。然后因为 ViewModel 实现了 INotifyPropertyChanged 并且因为它使用了 ObservableCollection,所以 View 已经更新了。

    让 ViewModel 的 ObservableCollection 发生变化,您不必让 UserControl 订阅任何事件。

    视图应该只显示 ViewModel 更新。

    【讨论】:

    • 改变的不是 ObservableCollection 本身,而是它的一个项目。无论如何,我不确定如何回答这个问题。您是否阅读过我提到“Foo 对象的集合实际上发送到某个 Flash ActiveX 对象的部分。因此,我不能“WPF 绑定”到 Foo 对象的属性。”?
    • 试图回答这个问题。但似乎与其说是 MVVM / WPF 问题,不如说是闪存托管问题。
    • @MareInfinitus:我的闪存托管工作得很好,但在我尝试坚持 MVVM 模式时它会带来挑战。
    • 是的,我读过那部分。我明白了。你有一个清单。当列表中的项目更改时,列表不会更新。它对性能不友好,但您可以让 ViewModel 在项目更改时重新创建列表。或者您可以删除并重新插入该项目。或者您可以手动调用 CollectionChanged。无论哪种方式都有效。我喜欢 Mare Infinitus 的回答,所以选择那个。当我说:“如果模型没有这样的事件,那么继承它并添加它。”
    【解决方案2】:

    您应该考虑拥有多个 ViewModel。

    如果您对您拥有的项目中发生的更改感兴趣 您的 ViewModel,为这些项目创建一个 ViewModel 并更改 ViewModel 集合到ObservableCollection<ItemViewModel>

    这样,您可以绑定到您真正感兴趣的属性。

    举个例子:

    // the overall viewModel:
    public class OverallViewModel : ViewModelBase
    {
        public ObservableCollection<ProductViewModel> Products { get; set; };
    }
    
    // the item viewmodel:
    public class ProductViewModel : ViewModelBase
    {
        public string ProductName { get; set; }
        public int CountOfSold { get; set; }
    }
    

    所以,你卖了 5 根香蕉。 Banana 的销售数量发生了变化。 由于您直接绑定到项目,因此不再有任何 需要有一个额外的事件,视图(在你的情况下是用户控件) 无需人工收听即可更新 事件。

    我对 Flash 了解不多,但可能有一个转换器 托管闪存的用户控件可以提供帮助。至少你会 不必爬取所有列表,只需爬取单个项目。

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 2016-07-23
      相关资源
      最近更新 更多