问题描述
案例是:我有一个控件的事件,我希望我的 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 的最佳方式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!