C# 使用MVVM模式时,可以将x:Bind绑定到ViewModel中的事件处理程序吗?

C# 使用MVVM模式时,可以将x:Bind绑定到ViewModel中的事件处理程序吗?,c#,wpf,xaml,uwp,C#,Wpf,Xaml,Uwp,例如,我有一个ListView,其中包含一个ItemClick事件和一个SelectionChanged事件。我应该完全跳过代码隐藏文件并将事件处理程序放在ViewModel中,还是应该将处理程序放在代码隐藏中 在我看来,跳过后面的代码似乎不符合逻辑,因为事件处理程序似乎是直接为UI元素生成的。例如,sender参数和相关的EventArgs参数通常需要了解特定类型的UI元素,因此必须将sender对象强制转换为UI元素类型,以便处理数据。事实上,在某些情况下,sender参数的类型已经给定:

例如,我有一个
ListView
,其中包含一个
ItemClick
事件和一个
SelectionChanged
事件。我应该完全跳过代码隐藏文件并将事件处理程序放在ViewModel中,还是应该将处理程序放在代码隐藏中

在我看来,跳过后面的代码似乎不符合逻辑,因为事件处理程序似乎是直接为UI元素生成的。例如,
sender
参数和相关的
EventArgs
参数通常需要了解特定类型的UI元素,因此必须将
sender
对象强制转换为UI元素类型,以便处理数据。事实上,在某些情况下,
sender
参数的类型已经给定:

private void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
    // In this particular case there is no need to cast the sender parameter to the AutoSuggestBox (UI element!) type because it is already given.
}

使用这些UI元素是安全的还是应该只在视图中处理UI问题。请救我脱离我自己。谢谢

事件处理程序属于该视图。您不会在视图模型中定义事件处理程序,尤其是不接受控件(如
AutoSuggestBox
作为参数)的事件处理程序。这首先违背了使用MVVM模式的目的。视图模型不应该有任何引用或任何关于任何UI控件的知识

为了能够使用
x:Bind
,您可以在视图的代码隐藏中定义实际的事件处理程序,然后从该事件处理程序调用视图模型的方法或命令。只要不将任何与视图相关的内容传递给视图模型,也不在视图中实现任何类型的应用程序逻辑,就可以了,例如:

private void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
    var parameter = ...; //extract the parameter from the args
    ViewModel.Command.Execute(parameter);
}
x:Bind
不可用(WPF)的XAML框架中,通常避免在代码隐藏中定义任何事件处理程序,而是直接从XAML调用视图模型的命令。你可以阅读更多关于这方面的内容


这里的要点是,只要在视图模型中实现可测试和分离的应用程序逻辑,向视图的代码隐藏类添加事件处理程序并不会真正打破MVVM模式。代码隐藏和XAML标记属于同一个类,从该类的代码隐藏调用命令与从XAML或可重用的附加行为调用命令一样,就MVVM模式而言。

你没有错。很多人最终都会使用与其视图紧密绑定的虚拟机,因为他们避免过多地使用代码。如果它是特定于视图的,那么它应该保留在视图imo中。很多时候,您可以通过巧妙的xaml来避免这种情况,例如奇妙的绑定,或者将用户输入转换为命令(尽管这可能会以类型安全为代价)。最好的方法实际上取决于你的应用程序和你正在使用的MVVM框架。如果你还不熟悉它,我建议用谷歌搜索“命令模式MVVM”。这些方法不会消除代码落后,但往往会消除大部分代码落后。(如果您的具体例子是这些例外,请道歉)谢谢您的回复。因此,对于ListView的ItemClick事件或SelectionChanged事件,我是否应该将处理程序直接放在代码中,然后调用ViewModel中的方法,并将适当的项数据传递给该ViewModel方法?我越学lol.PS就越困惑——UI框架和模式很难学习,MVVM肯定也不例外。MVVM是我使用过的更好的模式之一,但不是因为它简单。即使在一个特定的MVVM框架内,在最佳实践方面也很少达成一致意见,这也无济于事。在实际、详细的层面上,您甚至不会在VM是什么(或应该是什么)上找到太多一致意见。我的观点是,如果它看起来令人困惑,请不要感觉很糟糕。不要在viewmodel中使用任何ui。虽然理想情况下,如果您没有绑定到命令,请不要在viewmodel中使用它从codebehind调用-在viewmodel上直接调用方法之前,这是额外的垃圾和成本。当然;如果这是与此视图模型交互的唯一方式,则可以调用它的公共方法,而不是调用命令。但这不是我的重点。@mm8那么你是在暗示,如果事件处理程序在代码隐藏中,x:Bind没有任何作用,因为在这种情况下,我可以简单地创建一个普通事件,自动在代码隐藏中为我生成处理程序?还是在所有情况下都使用x:Bind更好?另外,对于所有这些,您最喜欢的方法是什么?您可以使用x:Bind直接绑定视图模型的方法。如果不在WPF和UWP客户机之间共享视图模型类,这是一种可行的方法,因为它提供了编译时安全性。使用{Binding}绑定到命令时不会发生错误。但是,如果出于某种原因从视图模型中公开命令,则视图中不需要任何事件处理程序。