2014-01-22 50 views
3

案件是:我有一个控件的事件,我希望我的ViewModel作出反应。目前我通过执行隐藏按钮的命令来执行此操作,如下例所示。将事件传递给ViewModel的最佳方式是什么?

在View.xaml:

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

在View.xaml.cs:

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

这工作不错,但它看起来像一个黑客给我。我想知道是否有更好的(标准)方法来做到这一点?我找不到任何例子,这就是我自己“发明”的。

+0

Google用于交互触发器。 –

+0

或者只是将视图的DataContext转换为ViewModel并做任何您想要做的事情.ViewModel vm = this.DataContext as ViewModel;那么你可以做vm。SomeAction – Krishna

+0

@RohitVats谢谢,我看到在一些例子中使用它们,但它看起来并不像我所需要的。现在我发现我错了。 – Kurtevich

回答

7

使用MVVM,处理事件的一般方法是简单地将它们包装在Attached Properties中,或使用Attached Events。这里是附加属性使用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); 
} 

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

<TextBox TextBoxProperties.PreviewKeyDown="SomeKeyEventHandler" /> 

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

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

这看起来很有趣...我需要检查它是如何工作的。 – Kurtevich

+0

这工作,我也很喜欢这个解决方案如何清洁,简单,简单就是。我也被告知过交互性触发器,但我认为这样更好。谢谢! – Kurtevich

+0

你可以显示附加事件的方式吗?我无法找到如何在虚拟机上使用附加事件注册事件处理程序,因为所有路由事件都不支持绑定,或者不是吗? –

0

您应该向您的控件添加依赖项属性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财产中您的视图模型中定义

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

看一看例如SearchResultRefreshed在下面的教程了解更多dependecyproperty and attachedproperty

2

我个人从来没有需要使用附加属性来处理wi控制的事件。在你的例子中,一个控件想知道什么时候'SearchResultRefreshed',然后通过隐藏的控件通知ViewModel ...为什么ViewModel不知道结果已经刷新?

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

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

+0

是,该数据被从视图模型来,但是当滤波是在其内部进行的事件是由3dparty的WinForms控制上升。 – Kurtevich

+0

噢,好的。然后,我使用交互命名空间,因为它需要较少的大量的代码不是写新的连接的属性:' ' – Mashton

相关问题