wpf 使用 Caliburn.Micro 从 ViewModel 调用 UserControl 的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19717475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:59:35  来源:igfitidea点击:

Calling method of UserControl from ViewModel with Caliburn.Micro

c#wpfmvvmcaliburn.micro

提问by PeterE

I'm writing a ViewModel-first MVVM application using Caliburn.Micro My View contains a 3rd party UserControl that implements a Method I want/need to call from the associated ViewModel. How do I do that while still upholding the MVVM principles?

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

There exists an old threadhere on SO where a similar question is asked in a more specific context. I would appreciate it if someone could flesh-out the approaches suggested there a bit.

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

Approach one suggests that the View could subscribe to an IEventAggregator message. But wouldn't I have to use the code behind file to do that? (I thought that was a big no no in MVVM)

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

Regarding approach two, I have no idea how to do that. And regarding approach three, thats what I tried first but somehow I didn't quite get it to work.

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

回答by Charleh

Let me clarify your understanding:

让我澄清你的理解:

Yes code in the code-behind is generally avoided, but only because MVVM makes it so easy to bind to viewmodel properties and commands in order to wire up your visual element with the functionality behind the scenes

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

Code that is view-specific in the code-behind of the view is perfectly acceptable assuming it doesn't cross the boundary of concern. For instance, I have a view in my application that does some visual processing of the page, and to do so I require that there is code in the view. This code may also interact with the viewmodel layer, but it will not directly reference the viewmodel, therefore keeping my components loosely coupled

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

If you have controls that need particular methods calling, then creating an event aggregator message to propagate the notification to the view is perfectly fine since you are still maintaining the separation of concern between the viewmodel and view (and the application components remain encapsulated and testable)

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

Example View (I've left all event aggregator wire up code and potential dependency injection stuff out for clarity):

示例视图(为了清楚起见,我已将所有事件聚合器的接线代码和潜在的依赖注入内容都保留了下来):

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

Obviously, what you wouldn't do is something like this in the ViewModel:

显然,你不会在 ViewModel 中做这样的事情:

public class MyViewModel : IViewAware
{
    public void DoSomethingThatAffectsView()
    {
        var view = this.GetView() as MyView;

        view.SomePageControl.SomeMethod();
    }
}

Which violates the MVVM principles since you are tightly coupling MyViewModel and MyView.

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

What if you wanted to use the Contextproperty in caliburn micro which allows multiple views over the same view model? The code above would break - even if you checked the View type, you would still end up with spaghetti code e.g.

如果您想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...
    }
}

Of course this is subjective: it may be that your usercontrol affects the viewmodel and the view in a complex way, in which case you might want to consider looking at the architecture and working out how that usercontrol can better fit

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

Have you got any background on what the UC is and what the method on it does?

您对 UC 是什么以及它的方法有什么了解吗?