简体   繁体   English

WPF MVVM从代码后面调用ViewModel方法

[英]WPF MVVM calling ViewModel methods from code behind

First off I am very new to WPF MVVM and a bit confused. 首先,我对WPF MVVM很新,有点困惑。 People say that generally in MVVM the best practice is not to have any code behind. 人们说通常在MVVM中最好的做法是不要有任何代码。 I have found that some methods are way easier to achieve in code behind than in viewmodel (eg MouseMove ) and that led me thinking between the differences of these 2 following examples: 我发现有些方法在代码后面比在viewmodel(例如MouseMove )中更容易实现,这让我想到了以下两个例子的不同之处:

1) Using RelayCommand : 1)使用RelayCommand

View 视图

<Button Command="{Binding AlertCommand}"></Button>

ViewModel 视图模型

public RelayCommand AlertCommand { get; set; }

public void Alert()
{
   MessageBox.Show("message");
}

2) calling ViewModel methods from code behind: 2)从后面的代码调用ViewModel方法:

View 视图

<Button PreviewMouseLeftButtonUp="OnMouseLeftButtonUp"></Button>

View code behind 查看背后的代码

private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
     var ctx = (MainViewModel) this.DataContext;
     ctx.Alert();
}

Is using code behind here wrong? 在这里使用代码错了吗? What are my benefits of not using code behind? 不使用代码背后的好处是什么?

The MVVM pattern is a best practice when building UWP, WPF, and Xamarin.Forms apps. 构建UWP,WPF和Xamarin.Forms应用程序时,MVVM模式是最佳实践。 The main advantage is that you are able to decouple the logic from the presentation and potentially could present a single view model by multiple different views and could switch views without having to modify the view model significantly. 主要优点是您能够将逻辑与表示分离,并且可能通过多个不同的视图呈现单个视图模型,并且可以切换视图而无需显着修改视图模型。 This is a great advantage when building cross-platform apps with native UI, which MvvmCross framework uses to a great extent for example. 在使用本机UI构建跨平台应用程序时,这是一个很大的优势,例如MvvmCross框架在很大程度上使用它。

Having an empty code-behind is however definitely just an ideal , which is usually not easy and not always necessary to achieve . 然而,拥有一个空的代码隐藏绝对是一个理想的选择 ,这通常并不容易,并不总是需要实现 Sometimes you need to use code-behind for purely view-related manipulation like changing layout for different window sizes, controlling animations, etc. For such actions, code-behind is a much better fit than trying to force this somehow into the VM. 有时您需要使用代码隐藏来进行纯粹的视图相关操作,例如更改不同窗口大小的布局,控制动画等。对于此类操作,代码隐藏比尝试以某种方式强制进入VM更合适。

Comparing your two approaches, using the RelayCommand -based one over the direct method call is preferable, because it has less direct tie to the method itself. 比较两种方法,使用基于RelayCommand的方法比直接方法调用更可取,因为它与方法本身的直接联系较少。 If you wanted, you could switch the RelayCommand instance in the VM for a different implementation (calling different method) at runtime, and thanks to binding the button could now perform a different action. 如果需要,可以在运行时将VM中的RelayCommand实例切换为不同的实现(调用不同的方法),并且由于绑定,按钮现在可以执行不同的操作。 This can be used in editor-like apps where some tools may have different functionality based on current context the app is in. 这可以在类似编辑器的应用程序中使用,其中某些工具可能具有基于应用程序所处的当前上下文的不同功能。

Also, for controls which do not offer a Command you can use EventTrigger hand in hand with InvokeCommandAction (both defined withing Expression Blend SDK) which will allow you to "convert" an event to a command call, even with your defined transformation of EventArgs . 此外,对于不提供Command控件,您可以将EventTriggerInvokeCommandAction一起InvokeCommandAction (两者都使用Expression Blend SDK定义),这将允许您将事件“转换”为命令调用,即使使用您定义的EventArgs转换也是如此。

Both are valid methods. 两者都是有效的方法。 The first is preferable if possible. 如果可能,第一个是优选的。 I generally use the second method on events where no command binding is available. 我通常在没有命令绑定可用的事件上使用第二种方法。 The notion of "absolutely no code-behind in MVVM" is debatable. “在MVVM中绝对没有代码隐藏”的概念值得商榷。 Any code that belongs directly to the view (and is not business logic) and is not reusable in a VM can be put in the code-behind, such as wiring up events in the second example. 任何直接属于视图(并且不是业务逻辑)且在VM中不可重用的代码都可以放在代码隐藏中,例如在第二个示例中连接事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM