3

我正在使用 Caliburn.Micro 编写一个 ViewModel-first MVVM 应用程序我的视图包含一个第 3 方 UserControl,它实现了我想要/需要从关联的 ViewModel 调用的方法。我该如何在坚持 MVVM 原则的同时做到这一点?

SO上有一个旧线程,在更具体的上下文中提出了类似的问题。如果有人可以充实那里建议的方法,我将不胜感激。

方法一表明视图可以订阅 IEventAggregator 消息。但是我不必使用文件后面的代码来做到这一点吗?(我认为这在 MVVM 中是一个很大的禁忌)

关于方法二,我不知道该怎么做。关于方法三,这就是我首先尝试的方法,但不知何故我并没有让它发挥作用。

4

1 回答 1

9

让我澄清你的理解:

是的,通常会避免代码隐藏中的代码,但这仅仅是因为 MVVM 可以很容易地绑定到视图模型属性和命令,以便将您的视觉元素与幕后的功能联系起来

在视图的代码隐藏中特定于视图的代码是完全可以接受的,假设它不跨越关注的边界。例如,我的应用程序中有一个视图,它对页面进行一些可视化处理,为此我需要视图中有代码。此代码也可能与视图模型层交互,但它不会直接引用视图模型,因此保持我的组件松散耦合

如果您有需要调用特定方法的控件,那么创建一个事件聚合器消息以将通知传播到视图是非常好的,因为您仍然保持视图模型和视图之间的关注点分离(并且应用程序组件保持封装和可测试)

示例视图(为清楚起见,我已将所有事件聚合器连线代码和潜在的依赖注入内容排除在外):

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();
    }
}

这违反了 MVVM 原则,因为您将 MyViewModel 和 MyView 紧密耦合。

如果您想Context在 caliburn micro 中使用允许多个视图在同一个视图模型上的属性怎么办?上面的代码会中断——即使你检查了 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...
    }
}

当然这是主观的:可能是您的用户控件以复杂的方式影响视图模型和视图,在这种情况下,您可能需要考虑查看架构并确定用户控件如何更好地适应

您对 UC 是什么以及它的方法有什么背景吗?

于 2013-10-31T22:48:24.167 回答