MVVM + ViewModel 调用的 View 特定功能的实现 [英] MVVM + Implementation of View specific functionalities called by the ViewModel

查看:92
本文介绍了MVVM + ViewModel 调用的 View 特定功能的实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我想要解决的问题":

here is my "problem" I want to resolve:

我有许多仅查看"特定功能,例如:

I have got many "View only" specific functionalities for example:

  • 在运行时更改视图的 ResourcesDictionary(用于将皮肤从黑色更改为蓝色或其他)
  • 保存和恢复视图特定设置,例如视图大小或用户设置的网格属性
  • ...

所有这些功能都与 ViewModel 无关,因为它们实际上是特定于视图的,并且可能只适合 ViewModel 的一个客户端(View)(如果一个 ViewModel 有多个客户端).上面的例子只是我想要实现的大量功能中的两个,所以我需要一个更通用的解决方案,而不是只适合这两个例子的解决方案.

All those functionalities have nothing to do with the ViewModel, since they are really view specific and might only fit to one client (View) of a ViewModel (in the case a ViewModel has got more than one client). The examples above are only two of a large amount of functionalities I want to implement, so I need a more generic solution instead of solutions that only fit those two examples.

在考虑解决方案时,我想到了以下两种方法

When thinking of a solution I came two the following approaches

  • 创建一个从 DependancyObject 继承的 ViewBase.我不喜欢这个解决方案,因为它以某种方式打破了视图没有代码的 MVVM 模式的想法.为了调用这个方法,我需要在我的 ViewModel 中引用视图,这也否定了关注点分离的想法.
  • 创建一个 IView 接口.和第一种方法一样脏.每个 View 都需要实现 IView,因此背后有代码.此外,ViewModel 需要以某种方式"知道 IView 实现以调用其方法
  • 将 ViewModel 的属性绑定到视图的触发器、行为和命令.这种方法似乎是最好的,但我认为我会非常快地运行在使用限制中,因为某些功能可能无法使用这种方法.例如,仅将 resourceDictionary 绑定到视图可能不起作用,因为需要合并才能正确显示新资源.再说一遍……我只能查看 ViewModel 中的特定功能/信息(如资源字典),但只有 ViewModel 的特定客户端使用此属性.

如果你们中的任何人已经遇到了同样的问题,并且为我的问题找到了一个智能/流畅(并且大部分是通用的;))解决方案,那就太好了.

If anyone of you already had the same problem and got a smart/smooth (and mostly generic ;) ) solution for my problem, this would be great.

谢谢

推荐答案

我一直认为模式是为人而生,而不是人为模式而生.很多时候你会看到 MVVM 不适合的情况并解决它,非常聪明的人想出了解决它的方法,同时保持纯粹的 MVVM 外观.

I've long since adopted the way of thinking that Patterns were made for Man, not Man for patterns. Quite often you'll see a situation where MVVM doesn't fit and to resolve it, very smart people have come up with ways to get around it, while maintaining the pure MVVM look.

然而,如果你认同我的学派,或者你只是想保持简单,另一种方法是让 ViewModel 引用视图;当然是通过接口,否则这将是糟糕的编程实践.现在问题变成了,如何将视图放入视图模型中?

However, if you subscribe to my school of thought, or if you just like to keep it simple, another way is to allow the ViewModel to reference the view; via an interface of course, or that would just be terrible programming practice. Now the question becomes, how to get the view into the viewmodel?

最简单的方法是在视图的 dataContextChanged 事件中执行此操作.但是,如果您想尝试不同的东西,如何使用附加属性或依赖属性将视图注入视图模型?

the simplest way would be to do this in the view's dataContextChanged event. However if you want to try something different, how about using an attached property or dependency property to inject the view into the viewmodel?

我已经在许多 WPF 项目中成功地使用了这种技术,并且不觉得脏或以某种方式受到损害.我称之为 MiVVM或模型接口到视图视图模型.

I've successfully used this techniques on a number of WPF projects and don't feel dirty or somehow compromised. I call it MiVVM or Model Interface-to-View ViewModel.

模式很简单.您的用户控件应该有一个接口,称为 IMyView.然后在 ViewModel 中,您有一个带有 IMyView 类型设置器的属性,例如

The pattern is simple. Your Usercontrol should have an interface, call it IMyView. Then in the ViewModel you have a property with a setter of type IMyView, say

public IMyView InjectedView { set { _injectedView = value; } }

然后在视图中创建一个名为 This

Then in the view you create a dependency property called This

public MyUserControl : IMyView
{
    public static readonly DependencyProperty ThisProperty = 
         DependencyProperty.Register("This", typeof(IMyView), typeof(MyUserControl)); 

    public MyUserControl() 
    {
       SetValue(ThisProperty, this);
    } 
    public IMyView This { get { return GetValue(ThisProperty); } set { /* do nothing */ } } 
}

最后在 Xaml 中,您可以使用绑定将视图直接注入到 ViewModel 中

finally in Xaml you can inject the view directly into the ViewModel using binding

<MyUserControl This="{Binding InjectedView, Mode=OneWayToSource}"/>

试试吧!我已经多次使用这种模式,并且您会在启动时获得一次注入视图的接口.这意味着您保持分离(Viewmodel 可以被测试,因为 IView 可以被模拟),但您可以解决许多第三方控件缺乏绑定支持的问题.另外,它的速度很快.你知道绑定使用反射吗?

Try it out! I've used this pattern many times and you get an interface to the view injected once on startup. This means you maintain separation (Viewmodel can be tested as IView can be mocked), yet you get around the lack of binding support in many third party controls. Plus, its fast. Did you know binding uses reflection?

此博客链接.如果您使用的是无法修改的第三方控件,我主张尝试 MiVVM 的附加属性实现.

There's a demo project showcasing this pattern on this blog link. I'd advocate trying out the Attached Property implementation of MiVVM if you are using a third party control that you cannot modify.

最后,我建议找到最适合这项工作的工具几乎总是最好的编程方法.如果您开始使用正确的干净"或正确"代码,您通常会遇到需要改变方法的墙.

Finally may I suggest to find the best tool for the job is almost always the best programming approach. If you set out to right "clean" or "correct" code you are often going to hit a wall where you need to change your approach throughout.

这篇关于MVVM + ViewModel 调用的 View 特定功能的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆