让我澄清一下您的理解:是的,通常应避免在代码后台中编写代码,但这只是因为MVVM使得将视图模型属性和命令绑定到视觉元素以便将其与幕后功能连接起来变得非常容易。
在视图的代码后台中编写特定于视图的代码是完全可以接受的,前提是它不越过关注点的边界。例如,我的应用程序中有一个视图对页面进行一些视觉处理,为此我需要在视图中编写代码。这段代码也可能与视图模型层交互,但它不会直接引用视图模型,因此保持了组件的松耦合。
如果您有需要调用特定方法的控件,则创建事件聚合器消息以将通知传播到视图是完全可以的,因为您仍然在视图模型和视图之间保持了关注点分离(并且应用程序组件保持封装和可测试性)。
示例视图(为了清晰起见,我省略了所有事件聚合器的连接代码和潜在的依赖项注入):
public class MyView : IHandle<SomeNotificationMessageType>
{
public void Handle(SomeNotificationMessageType message)
{
SomePageControl.SomeMethod();
}
}
显然,在ViewModel中不会这样做:
很明显,你不会在ViewModel中这样做:
public class MyViewModel : IViewAware
{
public void DoSomethingThatAffectsView()
{
var view = this.GetView() as MyView;
view.SomePageControl.SomeMethod();
}
}
这样做违反了MVVM原则,因为你将MyViewModel和MyView紧密耦合。
如果你想在caliburn micro中使用Context
属性,允许同一个视图模型有多个视图呢?上面的代码就会失效 - 即使你检查了View类型,你仍然会得到一堆混乱的代码。
public class MyViewModel : IViewAware
{
public void DoSomethingThatAffectsView()
{
var myview = this.GetView() as MyView;
if(myview != null)
myview.SomePageControl.SomeMethod();
var myotherview = this.GetView() as MyOtherView;
if(myotherview != null)
myotherview.SomePageControl.SomeMethod();
}
}
当然,这是主观的:可能你的用户控件以一种复杂的方式影响视图模型和视图,这种情况下,您可能需要考虑查看架构并找出如何使该用户控件更好地适应。
你了解 UC 是什么以及其方法的背景吗?
IoC.Get<IEventAggregator>()
。有没有更好的依赖注入方式,而不仅仅是直接从容器中获取对象? - Anton KedrovOnViewAttached()
方法内调用了eventAggregator.Subscribe(view)
,我认为这比在View构造函数中使用IoC.Get<IEventAggregator>()
更好。 - Anton Kedrov