将事件传递给 ViewModel 的最佳方式是什么? [英] What's the best way to pass event to ViewModel?

查看:30
本文介绍了将事件传递给 ViewModel 的最佳方式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

案例是:我有一个控件的事件,我希望我的 ViewModel 对其做出反应.目前我正在通过执行一个隐形按钮的命令来做到这一点,如下例所示.

The case is: I have a control's event that I want my ViewModel to react on. Currently I'm doing this by executing a command of invisible button like in the example below.

在 View.xaml 中:

In View.xaml:

<Control x:Name="SearchResultGrid" ... DataRefreshed="SearchResultRefreshed" />
<Button x:Name="SearchResultRefreshedButton" Visibility="Collapsed" Command="{Binding SearchResultRefreshedCommand}" />

在 View.xaml.cs 中:

In View.xaml.cs:

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

这很好用,但对我来说它看起来像是一个黑客.我想知道是否有更好的(标准)方法来做到这一点?我找不到任何例子,这是我自己发明"的.

This works good, but it looks like a hack to me. I'm wondering if there is better (standard) way of doing this? I could not find any examples and this is what I "invented" myself.

推荐答案

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

Using MVVM, the general way to handle events is to simply wrap them in Attached Properties, or use Attached Events. Here is an example using the PreviewKeyDown event in an Attached Property:

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 处理程序调用它:

Note that it is just as easy (and better too) to use an ICommand instead of the actual KeyEventArgs object which shouldn't really be in the view model. Just create an Attached Property of type ICommand and call that from this TextBox_PreviewKeyDown handler instead:

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);
}

无论哪种方式,它都会像这样使用:

Either way, it would be used something like this:

<TextBox TextBoxProperties.PreviewKeyDown="SomeKeyEventHandler" />

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

Or if you used the preferred ICommand method:

<TextBox TextBoxProperties.PreviewKeyDownCommand="{Binding SomeCommand}" />

这篇关于将事件传递给 ViewModel 的最佳方式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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