让 ViewModel 对象持有 Dispatcher 是否被认为是不好的做法?

发布于 2024-08-24 12:18:14 字数 392 浏览 6 评论 0原文

我的 WPF 应用程序是使用 MVVM 模式构建的。 ViewModel 将与服务器异步通信,当返回请求的数据时,将触发 ViewModel 中的回调,并且它将对此数据执行某些操作。这将在非 UI 线程的线程上运行。有时这些回调涉及需要在 UI 线程上完成的工作,因此我需要 Dispatcher。这可能是这样的:

  • 将数据添加到 ObservableCollection
  • 触发 Prism 命令,这些命令将设置要在 GUI 中显示的内容
  • 创建某种类型的 WPF 对象。

我试图避免后者,但我发现这里的前两点对于 ViewModel 来说是合理的。所以;让 ViewModel 持有 Dispatcher 以便能够为 UI 线程调用命令可以吗?或者这被认为是不好的做法?为什么?

My WPF application is structured using the MVVM pattern. The ViewModels will communicate asynchronously with a server, and when the requested data is returned a callback in the ViewModel is triggered, and it will do something with this data. This will run on a thread which is not the UI Thread. Sometimes these callbacks involve work that needs to be done on the UI thread, so I need the Dispatcher. This might be things such as:

  • Adding data to an ObservableCollection
  • Trigger Prism commands that will set something to be displayed in the GUI
  • Creating WPF objects of some kind.

I try to avoid the latter, but the two first points here I find to be reasonable things for ViewModels to do. So; is it okay to have ViewModels hold the Dispatcher to be able to Invoke commands for the UI thread? Or is this considered bad practice? And why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

宛菡 2024-08-31 12:18:14

由于 ObservableCollection 必须在其所属的线程上更新(假设是 GUI 应用程序),并且 ObservableCollections 应该是 ViewModel 的一部分,因此 ViewModel 具有 Dispatcher 的情况很明显。

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

Since an ObservableCollection must be updated on the thread it belongs to (assuming a GUI app), and ObservableCollections should be part of the ViewModel, then there's a clear case for the ViewModel having a Dispatcher.

I can't see it being part of the Model.

耀眼的星火 2024-08-31 12:18:14

理想情况下,ViewModel 应完全独立于所使用的 UI 技术。理论上,我们应该能够将其重用于Windows 窗体(如果我们稍微改进Windows 窗体控件以支持更好的绑定)、网页< /em> (我在这里设想了某种奇特的机制,可以将 ViewModel 也编译成 Javascript),以及任何未来的技术。并非所有这些技术都会使用 Dispatcher 模型。

也就是说,我认为现在将 Dispatcher 包含在 ViewModel 中是一种务实的妥协。在我的 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,但是好吧。 :->

Ideally, a ViewModel should be totally independent from the UI technology used. We should theoretically be able to reuse it for Windows Forms (if we pimp up the Windows Forms controls a little bit to support better binding), for Web pages (I envision some kind of fancy mechanism here that would compile the ViewModel also into Javascript), and for any future technologies. Not all of these technologies will use the Dispatcher model.

That said, i consider it as a pragmatic compromise to include the Dispatcher in the ViewModel nowadays. In my ViewModel base class, I check for the current 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));
        }
    }

I still have the dependency on System.Windows of course, but oh well. :->

任谁 2024-08-31 12:18:14

我同意 kyoryu 的观点,我想指出的是,它只创建对 ServiceModel lobrary(您已经拥有的)的依赖,而不是对 View 本身的依赖,因此没有什么可以反对这种构造。

昨天我用 WPF、一个简单的虚拟机和线程尝试了一些东西,并得出结论:我绝对需要将调度程序传递给虚拟机。

另请参阅使用 WPF UI 线程应始终确保 STA 公寓模式,对吧?

I agree with kyoryu and I would like to note that it only creates a dependency on the ServiceModel lobrary (which you already have) and not on the View itself, so there is very little to object against this construction.

I was trying out a few things with WPF, a simple VM and threads yesterday and came to the conclusion that I absolutely needed to pass the Dispatcher to the VM.

Also see Using WPF UI thread should always ensure STA apartment mode, right?

高跟鞋的旋律 2024-08-31 12:18:14

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

You should consider using AsyncOperation instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文