[英]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
控件,您可以将EventTrigger
与InvokeCommandAction
一起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.