这是不好的MVVM练习吗?

时间:2014-11-24 15:16:24

标签: c# wpf mvvm viewmodel code-behind

假设我想使用事件在视图模型中调用命令。这是不好的做法吗?如果是这样的话?

示例:

代码隐藏

void button1_Click(object sender, MouseEventArgs e)
{
    this.ViewModel.OnButton1Click();
}

视图模型

void OnButton1Click()
{
    // Do something
}

提前致谢。

2 个答案:

答案 0 :(得分:1)

WPF中的MVVM负责处理应用程序的表示逻辑和状态。这意味着视图的代码隐藏文件不应包含任何代码来处理从任何UI引发的事件。 所以你要做的就是打破MVVM

您应该使用以下内容重写代码

    <Button Command="{Binding ClickCommand}" Width="100" Height="100" Content="test"/>

窗口背后的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModelBase();
    }
}

ViewModel:

public class ViewModelBase
{
    public ViewModelBase()
    {
        _canExecute = true;
    }
    private ICommand _clickCommand;
    public ICommand ClickCommand
    {
        get
        {
            return _clickCommand ?? (_clickCommand = new CommandHandler(() => MyAction(), _canExecute));
        }
    }
    private bool _canExecute;
    public void MyAction()
    {

    }
}
public class CommandHandler : ICommand
{
    private Action _action;
    private bool _canExecute;
    public CommandHandler(Action action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action();
    }
}

答案 1 :(得分:1)

是的,这是不好的做法,因为您直接引用ViewModel中的View,这意味着View和{{1}之间存在依赖关系因而紧密耦合。

该模式明确要求ViewModel NOT 依赖于特定的View实例或类型。这里的想法是为多态ViewModel解耦ViewsViewModels(您可以通过多种方式显示相同的数据)。为了使Views可以重复使用,它不需要具体依赖于特定的View类型。

更好的方法是使用ViewModel,如Kamel所说。但是,并非所有事件/交互/控件都必须允许调用Commands。但是,您可以使用Commands附带的Commands程序集将System.Windows.Interactivity.dll附加到特定事件。

这允许您创建如下所示的XAML:

Blend SDK

..它允许与事件处理程序相同的功能来调用 <i:Interaction.Triggers> <i:EventTrigger EventName="LostFocus"> <i:InvokeCommandAction Command="{Binding UpdateTextBoxBindingOnEnterCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"/> </i:EventTrigger> </i:Interaction.Triggers> ,但是以一种解耦的MVVM友好方式。