我在MVVM ViewModel地狱

时间:2010-01-20 21:05:18

标签: wpf mvvm multithreading polling

到目前为止,我对应用程序从各处的典型点击事件处理程序转换到完成GUI解耦的过程非常满意。现在我遇到了一些我无法弄清楚的东西,它与我想要弹出GUI的窗口有关,它需要显示模型中的信息。

我想我的问题的简短版本是,在MVVM中绝对禁止允许模型引用ViewModel吗?这是我的场景:我有一组LED可以非常快速地循环显示RGB值。我想在我的GUI中有一个窗口,通过使用ViewModel进行数据绑定来显示更新的颜色。我在测试应用程序中使用模型ViewModel使Window + UserControl正常工作,但现在我必须将此Window放入我的实际应用程序中。

我正在运行的特定模式模拟硬件正在做什么。当我命令模型循环遍历颜色时,它会启动一个更改必要的类成员变量值的线程。

我目前对MVVM的实现基本上都是轮询。为了让其他LED在其他地方更新,我运行了一个调用ViewModel函数的线程。这会更新属性,因此GUI会自动更新,因为我正在使用数据绑定。我的LED示例中的问题是模拟颜色序列是在线程中完成的,因此如果我需要对值进行ViewModel轮询,则由于LED变量的过度锁定,它可能会很慢。

因此,我希望有人可以推荐另一种解决此问题的方法。到目前为止,我唯一能想到的就是让Window datacontext成为一个LEDViewModel,然后将LEDViewModel传递给Model。然后,当我调用RGB循环函数时,它可以根据需要更改必要的ViewModel属性,我根本不需要使用任何锁定。

这有意义吗?任何建议都会非常感激。

3 个答案:

答案 0 :(得分:7)

您是否尝试过在模型上实现INotifyPropertyChanged界面?

在我看来,这应该表现得足够好。当模型上的颜色状态发生变化时,您可以触发PropertyChanged事件,从该通知更新视图模型状态,并通过视图模型上的绑定更新视图。

答案 1 :(得分:3)

为什么不在您的应用程序的某种消息代理上使用事件?

最简单的方法是在MVVMFoundation中使用Messenger:http://mvvmfoundation.codeplex.com/

这方面的一个例子是:

public class MyHardwareModel
{
     private void OnHardwareLEDChanged() // or whatever
     {
          SharedMessages.Messenger.NotifyColleagues(SharedMessages.LEDCHANGED);
     }
}

然后在您的视图模型中,当它旋转时,您在视图模型的实例处于活动状态时注册这些消息的通知:

public class MyHardwareViewModel
{
     public MyHardwareViewModel()
     {
          SharedMessages.Messenger.Register(SharedMessages.LEDCHANGED, UpdateLeds);
     }

     private void UpdateLeds()
     {
          //Update ObservableCollection here.
     }
}

消息中介/代理模式在这些情况下非常有用,而不仅仅是这个。 MVVMFoundation内置的Messenger功能非常强大......在我的示例中,我使用的是非常通用的消息,但您可以使用参数发送更多类型的消息。

如果您使用的是EventAggregator,则Prism / Composite Application Guidance中内置了类似的功能。它以类似的方式使用。

希望这有帮助。

答案 2 :(得分:0)

一个简单的方法是定期进行轮询,比如说每50毫秒。这可以使用计时器非常容易地完成,并且比来自线程的常量轮询更少资源消耗。 50ms似乎是一个合理的间隔,即使你的LED实际上循环更快,因为用户无论如何都没有时间看到颜色变化......