【问题标题】:Is it OK to subscribe to the ViewModel's .NET events from the View in MVVM?可以从 MVVM 中的视图订阅 ViewModel 的 .NET 事件吗?
【发布时间】:2013-04-30 12:30:22
【问题描述】:

我正在使用 MVVM 模式编写此major memory trainer,方法是在屏幕上为包含 2 位数字的标签设置动画,并要求用户快速输入每个数字的相应助记符。动画是如何完成的完全取决于 View,所以后面会有一些代码。当在 UI 中输入了正确的助记符或数字从屏幕上消失时,将从视图中执行命令以传达已发生的情况。

在 ViewModel 中,我想定期触发 View 动画的新数字(随心所欲)。

实现这一目标的最佳方法是什么?我可以在 ViewModel 中有一个 ObservableCollection,但我想做的不仅仅是简单地绑定到它,我需要在添加和删除数字时在后面的代码中执行一个方法。

是否符合 MVVM 在 ViewModel 中使用简单的 .NET 事件并通过以下方式订阅它们:DataContext.NumberAdded += new NumberAddedEventHandler(....) 还是我应该这样做的另一种方式?

【问题讨论】:

  • 另外,我相信你甚至不需要一个事件。您应该能够绑定到视图中的“当前挑战”集合,使用DataTemplate 渲染每个挑战并使用触发器处理动画。无需活动。

标签: wpf events mvvm viewmodel


【解决方案1】:

View 是 ViewModel 的用户友好反映。如果您要运行特定于视图的逻辑(例如触发动画),则没有理由不使用代码隐藏来运行它。

只要您将 UI 和数据层分开,就可以了。

也就是说,如果您仅从 View 层使用它,那么从 ViewModel 提供 NumberAdded 事件对我来说并没有什么意义。这混合了你的图层。

相反,我会简单地使用常规的CollectionChanged

((MyViewModel)this.DataContext).Numbers.CollectionChanged += 
    new CollectionChangedEventHandler(....);

根据您的集合与 UI 的绑定方式,您可能还可以使用 UI 事件,或者可能改为使用触发器。

我认为带有 ItemsSource 的元素会在添加或删除项目时引发事件,或者您可以简单地将 ItemsSource 属性转换为集合并在其中连接到 CollectionChanged 事件而无需引用 @ 987654327@

void SomeItemsControl_DataContextChanged(...)
{
    var collection = (SomeItemsControl.ItemsSource as ObservableCollection);
    if (collection != null)
        collection.CollectionChanged += new CollectionChangedEventHandler(....);
}

【讨论】:

  • 我认为这里唯一的偏好是我提到有一个 DP,而不是直接转换 DataContext 并订阅 Numbers 集合。这样,如果将来删除了绑定或切换了 ViewModel,您将不会有异常,并且只需查看 xaml,您就知道该 View 期望它的 DataContext 存在依赖关系。同样,这只是一种偏好,可以忽略。只是提供了一点面向未来的证明,以使视图可与不同的 VM 重用
  • @Viv 是的,DP 绝对是解决问题的另一个好方法,特别是如果整个集合没有绑定在 UI 中的某个位置。 :)
  • 是的,对我来说,可以灵活地将这个视图附加到另一个 ViewModel,而不需要太多变化,而不是可能的绑定属性名称似乎胜过依赖订阅:)
  • 将使用 Viv 的方法。我正在使用 Canvas 对数字进行动画处理,因此标签将存储在 canvas1.Children 中,并且会有两个 ObservableCollection,一个在 View 中,一个绑定到 ViewModel 中的一个。
【解决方案2】:

为什么你认为绑定到它是不好的?

我可能会从视图绑定到ObservableCollection<T>

在 View 中创建 ObservableCollection<T>DependencyProperty 并在 PropertyChanged 回调上订阅 OnCollectionChanged 事件,然后该事件可以根据 View 中 ObservableCollection<T> 的内容相应地处理动画。

这样,VM 只需使用您提到的这些数字更新集合,并且只要集合以它想要的方式发生变化,视图就会连接到操作

【讨论】:

  • 呸!终于设法将其连接起来,经过长时间的编码中断后,我相当生疏。我喜欢这种方式。
【解决方案3】:

使用Attached Behaviours 将您的视图模型属性绑定到您需要的任何自定义行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-11
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 2011-08-14
    相关资源
    最近更新 更多