将事件传递给ViewModel的最佳方法是什么?

案例是:我有一个控件的事件,我希望我的ViewModel作出反应。 目前我正在通过执行隐藏按钮的命令来执行此操作,如下例所示。

在View.xaml中:

 

在View.xaml.cs中:

 private void SearchResultRefreshed(object sender, EventArgs e) { if (SearchResultRefreshedButton.Command != null) { SearchResultRefreshedButton.Command.Execute(SearchResultGrid.ResultRowCount); } } 

这很好用,但对我来说看起来像是一个黑客。 我想知道是否有更好的(标准)方式这样做? 我找不到任何例子,这就是我自己“发明”的东西。

使用MVVM,处理事件的一般方法是简单地将它们包装在附加属性中 ,或使用附加事件 。 以下是使用附加属性中的PreviewKeyDown事件的示例:

 public static DependencyProperty PreviewKeyDownProperty = DependencyProperty.RegisterAttached("PreviewKeyDown", typeof(KeyEventHandler), typeof(TextBoxProperties), new UIPropertyMetadata(null, OnPreviewKeyDownChanged)); public static KeyEventHandler GetPreviewKeyDown(DependencyObject dependencyObject) { return (KeyEventHandler)dependencyObject.GetValue(PreviewKeyDownProperty); } public static void SetPreviewKeyDown(DependencyObject dependencyObject, KeyEventHandler value) { dependencyObject.SetValue(PreviewKeyDownProperty, value); } public static void OnPreviewKeyDownChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { TextBox textBox = dependencyObject as TextBox; if (e.OldValue == null && e.NewValue != null) textBox.PreviewKeyDown += TextBox_PreviewKeyDown; else if (e.OldValue != null && e.NewValue == null) textBox.PreviewKeyDown -= TextBox_PreviewKeyDown; } private static void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) { TextBox textBox = sender as TextBox; KeyEventHandler eventHandler = GetPreviewKeyDown(textBox); if (eventHandler != null) eventHandler(sender, e); } 

请注意,使用ICommand而不是实际的KeyEventArgs对象同样容易(也更好),该对象实际上不应该在视图模型中。 只需创建一个ICommand类型的附加属性,然后从这个TextBox_PreviewKeyDown处理程序调用它:

 private static void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) { TextBox textBox = sender as TextBox; ICommand command = PreviewKeyDownCommand(textBox); if (command != null && command.CanExecute(textBox)) command.Execute(textBox); } 

无论哪种方式,它将使用这样的东西:

  

或者,如果您使用首选的ICommand方法:

  

就个人而言,我从来没有必要使用附属物来处理控件的事件。 在你的例子中,一个控件想要知道何时“SearchResultRefreshed”,然后通过隐藏控件通知ViewModel …为什么ViewModel不知道结果已被刷新?

如果结果首先来自ViewModel,并且绑定用于在控件中显示它们,那么搜索结果已刷新的知识应该由ViewModel驱动 – 而不是您的视图。

在少数情况下,我发现需要摆脱ICommands和数据绑定。

您应该将依赖项属性DataRefreshed添加到控件中以便绑定它

这里是一个如何做到这一点的例子

 public static readonly DependencyProperty DataRefreshedProperty = DependencyProperty.Register( "DataRefreshed", typeof(bool), typeof("typeof yourcontrol here "), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnDataRefreshedChanged) ) ); public bool DataRefreshed { get { return (bool)GetValue(DataRefreshedProperty); } set { SetValue(DataRefreshedProperty, value); } } 

然后你可以像任何其他WPF属性一样操纵你的属性,例如在ViewModel中定义的SearchResultRefreshed

   

看一下以下教程,了解更多dependecyproperty and attachedproperty