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

Kur*_*ich 4 c# wpf xaml mvvm

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

在View.xaml中:

<Control x:Name="SearchResultGrid" ... DataRefreshed="SearchResultRefreshed" />
<Button x:Name="SearchResultRefreshedButton" Visibility="Collapsed" Command="{Binding SearchResultRefreshedCommand}" />
Run Code Online (Sandbox Code Playgroud)

在View.xaml.cs中:

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

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

She*_*dan 8

使用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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,使用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);
}
Run Code Online (Sandbox Code Playgroud)

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

<TextBox TextBoxProperties.PreviewKeyDown="SomeKeyEventHandler" />
Run Code Online (Sandbox Code Playgroud)

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

<TextBox TextBoxProperties.PreviewKeyDownCommand="{Binding SomeCommand}" />
Run Code Online (Sandbox Code Playgroud)