我正在使用Caliburn.Micro编写ViewModel-first MVVM应用程序 My View包含第三方UserControl,它实现了我想要/需要从关联的ViewModel调用的方法。如何在坚持MVVM原则的同时做到这一点?
SO上有一个旧的thread,在更具体的背景下提出类似的问题。如果有人能够充实了那里提出的方法,我将不胜感激。
方法一表明View可以订阅IEventAggregator消息。但我不是必须使用代码隐藏文件来做到这一点吗? (我认为这在MVVM中是一个很大的禁忌)
关于方法二,我不知道如何做到这一点。关于方法三,这就是我首先尝试的但不知何故我没有完全开始工作。
答案 0 :(得分:7)
让我澄清你的理解:
通常可以避免代码隐藏中的代码,但这只是因为MVVM可以很容易地绑定到viewmodel属性和命令,以便将可视元素与幕后功能连接起来
在视图的代码隐藏中视图特定的代码是完全可以接受的,假设它没有跨越关注的边界。例如,我在我的应用程序中有一个视图,它对页面进行了一些可视化处理,为此,我要求视图中有代码。此代码也可能与viewmodel层交互,但它不会直接引用viewmodel,因此保持我的组件松散耦合
如果您有需要特定方法调用的控件,那么创建事件聚合器消息以将通知传播到视图是完全正常的,因为您仍然保持视图模型和视图之间的关注分离(并且应用程序组件保持封装状态)和可测试的)
示例视图(为了清晰起见,我已将所有事件聚合器连线代码和潜在的依赖注入内容留下):
public class MyView : IHandle<SomeNotificationMessageType>
{
// Handler for event aggregator messages of type SomeNotificationMessageType
public void Handle(SomeNotificationMessageType message)
{
// Call a method on one of the page controls
SomePageControl.SomeMethod();
}
}
显然,在ViewModel中你不会做的是这样的事情:
public class MyViewModel : IViewAware
{
public void DoSomethingThatAffectsView()
{
var view = this.GetView() as MyView;
view.SomePageControl.SomeMethod();
}
}
由于您正在紧密耦合MyViewModel和MyView,因此违反了MVVM原则。
如果您想在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();
// ad infinitum...
}
}
当然这是主观的:可能是您的usercontrol以复杂的方式影响了视图模型和视图,在这种情况下,您可能需要考虑查看体系结构并确定该用户控件如何更好地适应
你对UC是什么以及它的方法有什么背景知识吗?