【问题标题】:Problems related to View Models created from XAML与从 XAML 创建的视图模型相关的问题
【发布时间】:2015-06-07 22:14:06
【问题描述】:

正如标题所暗示的,这个问题专门寻找解决方案(或避免的方法)我在直接从 XAML 创建视图模型的应用程序中遇到的问题(没有对对象的代码引用)。

这是一个成熟、功能齐全且完全 MVVM 应用程序 - 在各个领域,视觉对象通常被添加到 XAML 主窗口或弹出窗口的部分中,如下所示:

<viewModels:MyViewModel MyDependencyProperty="{Binding}" />

在这些情况下,ViewModel 的实例是通过无参数构造创建的,我们有时会如上所示初始化依赖属性。

主 XAML 窗口具有主视图模型的 DataContext - ApplicationViewModel。大多数情况下,我们所有的视图都是资源字典,其样式定义了视图模型目标类型的各种模板。这些被拉入我们皮肤 XAML 文件中的合并字典中。

问题1

有时,应用程序周围的其他对象需要与 ApplicationViewModel 交互。但是,在实例化时,XAML 或其他方式中没有可用的引用 - 导致过度使用静态 ApplicationViewModel 实例(不好)。

问题 2

我们的 XAML 实例化对象通常会有事件挂钩和可视元素,需要显式取消挂钩/处置。我们的可视化树非常大而且非常复杂,因为我们在代码中没有对视图模型的任何引用,所以管理处置和避免内存增长的开销不断增加 - 并且将主窗口与任何视图模型或可视化一起丢弃可能导致它留在记忆中的元素 - 是一个持续的挑战。

我不是在这里要求任何代码,更多的是对您解决这些问题的方法/经验的描述。

由于各种原因,我无法提供代码 - 主要原因是需要演示的内容太多!

更新

仅供参考,关于该应用程序的另一件重要的事情是不断创建新的 ViewModel 项目,这些项目代表丰富的项目,这些项目出现在许多不断滚动的列表中,这些列表在选项卡中可用。从这些列表中的每一个中,都有许多命令操作、弹出对话框和其他需要下游 ViewModel 创建的功能(目前是按需创建的)。这些列表支持各种触摸手势,包括轻弹/动量滚动、滑出菜单、触摸扩展和拖放,更不用说包含矢量图像和动画的丰富显示了!

【问题讨论】:

  • 你使用依赖注入来创建 ViewModels 吗?
  • 您使用的是用户控件还是数据模板?
  • @Contango DataTemplates(和 ControlTemplates)。如前所述,样式位于资源字典中并合并到 XAML 外观中。组合中还有几个自定义用户控件。

标签: c# wpf xaml mvvm


【解决方案1】:

在完成了一些听起来具有相似复杂性的工作后,我可以提供一些建议,以使您的应用程序快速、响应迅速且内存高效:

  • 如果您想要快速的应用程序性能,以及在 3rd 方组件中出现的不那么隐蔽的错误,请使用隐藏/显示而不是创建/销毁可视化树。这将大大加快速度。创建可视化树是一个占用大量 CPU 资源的过程,因此请尽量隐藏它并按需显示它,而不是按需创建它然后销毁它。如果某些东西崩溃了,WPF 运行时非常非常擅长忽略与之相关的任何更新,因此它使用的 CPU 时间可以忽略不计。这可能会导致您创建大量 XAML 来控制许多可见 XAML 子块的可见性,并且还会导致闪电般快速的应用程序性能。我们倾向于使用 DataTemplate 来保持一切模块化,以便管理复杂性。
  • 使用依赖注入 (DI) 在应用程序启动时创建尽可能多的 ViewModel。这意味着 ViewModel 之间的所有依赖关系都会自动为您解决。这意味着视图的可视化树被创建一次,然后被隐藏,匹配的 ViewModel 被创建一次,然后不再创建。所有的 Model 类都被创建一次,然后再也不会被释放或创建。我推荐 Unity,但任何形式的 DI 都可以。避免使用 MEF 作为主要 DI 机制,因为 Unity 更适合此任务。有时自动创建类是不可避免的(例如,当用户将某些内容添加到列表时,第 3 方组件会自动创建新的 ViewModel 类),但通常这些类很小,因此不会影响性能。
  • 我不建议使用事件挂钩。这会导致 ViewModel 之间的耦合过多。相反,使用 Reactive Extensions (RX) 在 ViewModel 之间传递事件。有一个具有 Subject 的公共类。一个 ViewModel 可以使用 OnNext 发送事件,而另一个 ViewModel 可以使用 Subscribe 接收事件。但是,仅将此作为最后的手段:尝试构建对象层次结构,以便 ViewModel 可以相互引用,而无需求助于事件传递。
  • 最后,尽可能使用 async/await 将处理移出主 GUI 线程(我确定您已经这样做了)。

【讨论】:

  • 是的 - UI 线程的使用是经过深思熟虑的,只有 UI 活动发生在那里。尽管另一个线程的另一个主题是调度程序调用结束与实际呈现视觉完成之间的差距!
  • 我已经更新了原始问题,提供了一些关于应用程序的更多信息,这些信息可能与引入 DI 以创建视图模型有关..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-21
  • 2011-12-20
  • 2017-11-07
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
相关资源
最近更新 更多