所以我目前正在开发一个用WPF编写的UI。我真正喜欢WPF的一个方面是它引导你编写更多分离的,独立的UI组件的方式。对于我来说,WPF的一个难点在于它会引导您编写更多分离的,孤立的UI组件,这些组件有时需要彼此通信:)。这可能是由于我相对缺乏UI体验,特别是在WPF中(我不是新手,但我的大多数工作都比UI设计低得多)。
无论如何,情况如下:
在任何时候,UI的中心区域显示实现为UserControl
s的三个视图之一,我们称之为视图A,B和C.
用户将在不同时间在这些视图之间切换,并且有多种方法可以切换视图(这对客户很有效,导致代码设计当前有些痛苦。)
现在每个视图切换机制都可以自己转换到另一个视图。某个单例类负责存储数据并在视图之间进行通信。我不喜欢这个,它很混乱,容易出错,并且单例类对UI的细节知之甚少。我想尽可能地消除它。
我今天碰到了一个与视图之间切换时间有关的错误。为简化起见,一个视图在卸载时需要执行一些清理,但清理会清除另一个视图所需的一些数据。如果清理在之后运行,则加载另一个视图,确保问题。明白了吗?凌乱。
我试图退后一步,想象一种不同的方式来让这些视图加载他们完成工作所需的数据。你们中的一些人更有经验的UI / WPF人员一定遇到过类似的问题。我有几个想法,但我希望有人会在这里向我提出一个更清洁的方法。我不喜欢依赖于操作的顺序(在高级别)我的代码才能正常工作。提前感谢您提供的任何帮助。
答案 0 :(得分:5)
我建议使用某种处理CurrentView的父ViewModel。如果你有兴趣的话,我前一段时间写了一个例子here。
基本上,父视图会有List<ViewModelBase> AvailablePages
,ViewModelBase CurrentPage
和ICommand ChangePageCommand
您如何选择展示这些取决于您自己。我首选的方法是ContentControl
,其中Content
绑定到CurrentPage
,并使用DataTemplates
根据{{1}确定应显示哪个View
存储在ViewModel
答案 1 :(得分:2)
Rachel's post总结了我的基本方法,很好。但是,我想根据您的意见添加一些内容,您可以在此处考虑这些内容。
请注意,这是假设采用ViewModel优先方法,如评论中所述。
用户将在不同时间在这些视图之间切换,并且有多种方法可以切换视图(这对客户很有效,导致代码设计当前有些痛苦。)
这不应该导致设计上的痛苦。这里的关键是要有一个单一,一致的方式来请求“当前ViewModel”更改,View将自动跟进。 View中使用的实际机制可以是任何东西 - 更改VM应该是一致的。
正确完成后,设计应该没有什么痛苦,并且在视图实际操作方面具有很大的灵活性。
现在每个视图切换机制都可以自己转换到另一个视图。某个单例类负责存储数据并在视图之间进行通信。我不喜欢这个,它很混乱,容易出错,并且单例类对UI的细节知之甚少。我想尽可能地消除它。
这是一个协调的ViewModel可以真正放松的地方。它不需要单例,因为它有效地“拥有”视图的各个ViewModel。这里的一个选项,相当简单,就是在ViewModel上实现一个包含事件的接口 - ViewModel可以引发事件(我会更多地根据意图来命名,而不是基于“视图更改”)。协调VM将订阅每个子VM,并基于该事件,基于发出请求的适当内容来改变它的“CurrentItem”属性(对于活动VM)。根本没有UI细节。
我今天碰到了一个与视图之间切换时间有关的错误。为简化起见,一个视图在卸载时需要执行一些清理,但清理会清除另一个视图所需的一些数据。如果在加载其他视图后运行清理,则会出现问题。明白了吗?凌乱。
这是对重构的尖叫。 ViewModel永远不应该清理它不拥有的数据。如果发生这种情况,则意味着VM正在清理真正应该单独管理的数据。同样,协调VM可能是处理此问题的一种方法,但如果没有更多信息则非常困难。
我不喜欢依赖于操作顺序(在高级别)我的代码才能正常工作。
这是在这里思考的正确方法。如果可以避免,则代码中不应该依赖于顺序,因为随着时间的推移它会使生活变得更加简单。
我试图退后一步,想象一种不同的方式来让这些视图加载他们完成工作所需的数据。
Rachel和我在这里所支持的方法实际上与我在series on MVVM中用来实现master-detail View的方法相同。这里的好处是View的“detail”部分并不总是必须是相同类型的ViewModel或View - 如果你使用ContentPresenter
绑定到只有Object
的属性(或者虚拟机共享的接口),只需在运行时更改属性值,就可以轻松地使用完全不同的视图切换视图。
答案 2 :(得分:1)
我的建议是让一个主视图模型协调所有(不是静态/单例),然后使用子视图模型来传输数据。这样可以保持您正在寻找的分离,提供可测试性,并允许您控制何时更改每个对象的数据。