【问题标题】:How to share multiple ObservableCollections with multiple ViewModels?如何与多个 ViewModel 共享多个 ObservableCollections?
【发布时间】:2018-02-22 07:17:37
【问题描述】:

我正在编写一个有 4 个视图的程序:CompanyViewMembersViewWeeksViewReportsView。每个都有对应的 ViewModel 和 Model。我使用 PRISM BindableBase 来创建 ViewModel。数据绑定正确。

  • CompanyViewModel 包含 Company 类型的 Object。
  • MembersViewModel 包含 Member 对象的 ObservableCollection。
  • WeeksViewModel 包含 Week 对象的 ObservableCollection。

通过主窗口中的顶部按钮执行导航,可以随时选择任何视图

Container.RegisterTypeForNavigation<CompanyView>("CompanyView");
Container.RegisterTypeForNavigation<MembersView>("MembersView");
Container.RegisterTypeForNavigation<WeeksView>("WeeksView");
Container.RegisterTypeForNavigation<ReportsView>("ReportsView");

问题是 WeeksViewModel 必须有权访问 Members ObservableCollectionReportsViewModel 必须可以访问 Company ObjectMembers ObservableCollectionWeeks ObservableCollection

我不确定如何实现这一点。如何在 ViewModel 之间轻松共享数据?

我曾尝试使用 PRISM IEventAggregator 在更新时发布 ObservableCollections,这很有效,但是必须先访问视图才能收听事件。如果用户之前没有点击过“Weeks”视图,更新后的 MembersCollection 将不会到达 WeeksView。我可以预先初始化视图吗?我该怎么做?

我关注了 MVVM Made Simple with Prism - 网络研讨会 (https://www.youtube.com/watch?v=ZfBy2nfykqY) 并发现了在 cmets 中编写的相同问题。 Brian Lagunas 建议解决此问题的唯一方法是通过导航参数:

我在将消息从 ViewAViewModel 传递到 ViewBViewModel 时遇到了一个小问题。如果我没有访问 ViewB,它似乎不起作用,我认为这是因为 ViewBViewModel 尚未被实例化,直到它的视图至少被加载一次。

任何人对此有任何想法,我认为在需要之前实例化所有视图模型是一个坏主意,那么如何在实例化之前将默认信息从其他视图模型中获取到视图模型中?

Brian Lagunas:唯一的方法是在导航到 ViewBViewModel 时将该信息作为参数传递。

我考虑过使用导航参数,但您似乎必须知道从 WHERE 到 WHERE 的导航。例如。从 MembersView > WeeksView,将 Members Collection 作为参数传递。但用户可以按任何顺序导航,包括在程序加载时直接导航到 WeeksView。例如如果 WeeksView 来自 Company View,他们如何获得 Members Collection?公司不知道会员收藏。

我对其他想法持开放态度,我进行了广泛的研究并完全陷入困境:-(

非常感谢您的想法和帮助! 亲切的问候, 达米安

【问题讨论】:

  • 出于好奇,用户是否可以同时打开不同的视图? IE。有没有办法让 WeeksView 和 MembersView 同时打开和可见?
  • 您也可以使用 Prism 的region context
  • 你应该有一个主视图模型,它创建它的子视图模型并设置它们之间共享的任何东西。这种方法也简化了导航。您正面临由 PRISM 创建的人为问题。最简单的解决方案是不制造问题。
  • 无需同时打开单独的视图。我喜欢主视图模型和子视图模型的想法。简单总是最好的。谢谢!
  • 不客气,但请记住接受答案:meta.stackexchange.com/questions/23138/…

标签: c# .net wpf mvvm prism


【解决方案1】:

问题是 WeeksViewModel 还必须有权访问 Members ObservableCollection。而且 ReportsViewModel 还必须能够访问 Company 对象、Members ObservableCollection 和 Weeks ObservableCollection。

我不确定如何实现这一点。如何在 ViewModel 之间轻松共享数据?

您可以使用单个视图模型,其中包含每个特定视图模型的属性以及在两个或多个视图模型之间共享的公共属性,例如:

class MainViewModel
{
    public CompanyViewModel CompanyViewModel { get; set; }
    public MembersViewModel MembersViewModel { get; set; }
    public WeeksViewModel WeeksViewModel { get; set; }

    public ObservableCollection<Members> Members { get; set; }
}

然后每个子视图可以继承父窗口的DataContext 并绑定到他们想要跨所有视图模型类型的任何属性。

另一种选择是在视图模型之间来回传递信息,使用直接引用、事件聚合器或共享服务。

但是,如果视图模型仍然必须访问彼此的属性,那么拼命尝试分离视图模型之间的逻辑似乎毫无意义。所以我可能会采用第一种方法。

【讨论】:

  • 创建一个MainViewModel,它公开一个MembersViewModel和一个Members集合,并将MainViewModel作为数据上下文传递给MembersView,使其绑定到MembersViewModel.SomePropertyMembers 有点奇怪……
  • 不,但是从服务中获取 ObservableCollection (!) 肯定是。
  • ObservableCollection 来自 ObjectModel 命名空间,绝不是仅 WPF 或 UI。在视图模型之外使用INotifyPropertyChangedINotifyCollectionChanged 没有任何问题。
  • 我正在努力让它工作,但有很多问题......我是否必须重做我当前的 Prism 导航方法?是否有您知道我可以查看的示例或示例代码?谢谢!
  • 只需创建一个新类并将共享属性移至该类并绑定特定属性,例如 {Binding CompanyViewModel.CompanyName}。您需要提供您当前代码的示例,以便我能够为您提供任何进一步的建议。
【解决方案2】:

我建议让CompanyObservableCollection&lt;Week&gt;ObservableCollection&lt;Member&gt; 来自一项或多项服务。

WeeksViewModel 然后从服务接收ObservableCollection&lt;Week&gt;ObservableCollection&lt;Member&gt; 并处理数据以供WeeksView 使用。 ReportsViewModel 处理CompanyObservableCollection&lt;Week&gt;ObservableCollection&lt;Member&gt;ReportsView 使用...如果有人添加Member,他通过拥有ObservableCollection&lt;Member&gt; 的服务和所有视图模型来实现从该服务收到ObservableCollection&lt;Member&gt; 的用户将收到通知并进行相应更新。

没有必要在视图模型之间传递数据,因为视图模型不拥有数据。他们所做的只是将来自某个数据源的数据转换为要显示的视图,反之则将用户操作转换为对修改数据的服务的调用。

当您拥有拥有数据的视图模型时,您会在视图模型上获得 UpdateData 之类的方法,最终您会得到难以理解的意大利面条代码 UpdateThisUpdateThat 或一个 mm8 样式的巨型视图模型所有视图都使用它。你不想这样。

【讨论】:

  • “超级风格”?你错过了子属性吗?
  • 同意!通过服务管理数据。
  • 当然数据应该通过注入视图模型的服务来管理。但是您仍然必须将视图模型中的数据暴露给视图,这就是我所看到的问题所在。
  • 问题是关于在多个视图中使用相同的数据,即视图模型。为了实现这一点,我建议使用一种服务,将数据提供给不同的视图模型,而您建议使用主视图模型来拥有数据并将其提供给子视图模型。对我来说,这种数据分布不是视图模型的工作。视图模型的工作是为自己的视图提供数据。
  • 看看这里,例如:stackoverflow.com/questions/38915353/… 本质上,您注册了一个单例(服务)并将其注入所有感兴趣的视图模型中。您可以对其进行改进,以便服务类实现多个(精简)接口,并且每个视图模型只获得它所需的功能(一个可能想要创建约会,而另一个可能只想显示所有约会的列表)...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 2021-06-22
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多