2010-03-12 100 views
5

我的WPF应用程序使用MVVM模式进行结构化。 ViewModel将与服务器异步通信,并且在返回请求的数据时,会触发ViewModel中的回调,并且它将对此数据执行某些操作。这将运行在不是UI线程的线程上。有时候这些回调涉及需要在UI线程上完成的工作,所以我需要Dispatcher。这可能是东西,如:ViewModel对象持有Dispatcher被认为是不好的做法吗?

  • 将数据添加到一个ObservableCollection显示在GUI中
  • 创建某种WPF对象
  • ,将设置什么触发棱镜命令。

我尽量避免后者,但这两个第一点,我发现ViewModels做的事情是合理的。所以; ViewModel可以让Dispatcher能够调用UI线程的命令吗?或者这被认为是不好的做法?为什么?

+0

我必须在控制器中做同样的事情 - 控制器订阅它创建的视图的Load事件,并且在那一刻抓取对视图调度器的引用。这对于执行已经传递的委托非常有用。 – slugster 2010-03-12 11:22:55

+0

Thx小费!我正在使用IoC容器,并且IoC容器是在App.xaml.cs中创建的。我假设这是在UI线程中运行的,因此计划是在创建IoC容器的位置获取当前调度器并将其添加到容器中。仍然看看这是否成功。 – stiank81 2010-03-12 11:56:21

+0

完美地工作。或者,您可以在任何您知道由UI线程运行的parh中简单地使用Dispatcher.CurrentDispatcher。像例如ViewModel构造函数 - 如果这些构造函数是在UI线程中构造的。 – stiank81 2010-03-12 13:00:18

回答

3

由于一个ObservableCollection 必须的线程上被更新它属于(假设GUI应用程序),和ObservableCollections应该是视图模型的一部分,则有一个为具有分派器的视图模型的明确的情况。

我看不到它是模型的一部分。

+0

它应该明确不是模型的一部分。你可以做的解决方法是创建一个新的ObservableCollection并用这个填充结果,但是对我来说真的听起来像是一个黑客。 – stiank81 2010-03-12 12:28:48

+0

我有一个MVVM的轻微变体: My Model是在工作线程上运行的非托管代码。 模型回调到我的.Net代码中,然后调用到GUI线程中。 在GUI线程中运行的派发函数将更新ViewModel。 这样,我的虚拟机不需要知道有关调度。 – Surfbutler 2010-04-22 21:37:29

1

我同意kyoryu,我想指出,它只会创建一个对ServiceModel文件(你已经拥有)的依赖关系,而不是视图本身,所以很少有人反对这个构造。

昨天我正在用WPF,一个简单的虚拟机和线程尝试了几件事情,并得出了我绝对需要将分派器传递给虚拟机的结论。

另见Using WPF UI thread should always ensure STA apartment mode, right?

+0

Thx为您的答案!我现在开始使用Dispatcher,它真的简化了一些事情。在我做这件事之前,我发现自己正在做一些非常有创意的(哈克)解决方案。使用Dispathcer我认为代码变得更好了。但我想你应该知道你做了什么 - 不要做任何事情*仅仅因为你可以...... – stiank81 2010-03-12 13:21:47

+0

将调度器传递给虚拟机?这可能不是我所要做的。我的观点是虚拟机可能需要一个分派器,因为它可能拥有需要Dipsatached的东西。通常,我喜欢在最后一刻执行我的调度。如果这是虚拟机,很好,如果它在视图中,没问题。如果我的View完全是xaml,我可能会试图让VM负责Dispatcher,只是为了保持View纯xaml。但这可能过于聪明。 – kyoryu 2010-03-12 17:59:20

+0

当然,这可能是因为在我的日常工作中,我正在研究基础设施位,并且我们试图拥有线程上下文,并且我很快得出结论:做到这一点更合理到尽可能真正关心的位,而不是集中它... – kyoryu 2010-03-12 18:00:28

2

理想情况下,ViewModel应该从使用的UI技术,完全独立。我们应该在理论上能够重用它Windows窗体(如果我们皮条客了Windows窗体控制一点点地支持更好的结合),用于网页(我想象某种花哨的机制,在这里,将编译ViewModel也纳入Javascript),以及任何未来的技术。并非所有这些技术都将使用Dispatcher模型。这就是说,我认为这是一个务实的妥协方案,现在在ViewModel中包含Dispatcher。在我ViewModel基类,我检查当前Dispatcher

protected override void OnPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (Deployment.Current.Dispatcher == null || Deployment.Current.Dispatcher.CheckAccess()) 
     { 
      base.OnPropertyChanged(sender, e); 
     } 
     else 
     { 
      Deployment.Current.Dispatcher.BeginInvoke(() => base.OnPropertyChanged(sender, e)); 
     } 
    } 

我仍然有当然System.Windows的依赖,但哦。 : - >

+0

能够重用您的ViewModels听起来不错,但我不完全同意这是目标。只需考虑诸如命令绑定之类的简单事情。在做MVVM时你确实需要命令绑定,但Winforms是否有ICommand?其实我不确定,但更早的时候我想让我的ViewModels在Mono上构建,至少Mono没有ICommand。 – stiank81 2010-03-12 13:25:46

+0

仍然 - 有价值的反馈! +1 – stiank81 2010-03-12 13:28:08

+1

@heartmaster,如果它(真的)是重用虚拟机的目标,则应该将调度程序隐藏在某个接口后面(也可以由WinForms InvokeRequired等重新实现)。 – 2010-03-12 13:28:49

0

您应该考虑使用AsyncOperation来代替。

相关问题