首页 > 解决方案 > 多个视图的相同命令

问题描述

我有两个相同的视图View1.xamlView2.xaml它们都有一个 buttonbutton1和一个 textfield textfield1。这个想法是,当您按下按钮时,相应的文本字段会填充一些信息。两个视图都使用相同的方法来填充文本字段(从这个意义上说,视图实际上是相同的)。

我的问题是:如何使用 OOP 原则编写通用代码而不破坏 MVVM 模式?我目前使用 RelayCommand 执行此操作的方式:

ViewModel1和的相同代码ViewModel2

public RelayCommand ButtonCommand { get; private set; }

#Constructor
ButtonCommand = new RelayCommand(ExecuteButtonCommand, CanExecuteButtonCommand);
#EndConstructor

private void ExecuteButtonCommand(object message)
{
    //Some method to fill the corresponding textfield
}

private bool CanExecuteButtonCommand(object message)
{
    return true;
}

View1.xaml和中的按钮绑定View2.xaml

<Button Command="{Binding Path=ButtonCommand, Mode=OneWay}" />

这很糟糕,因为我必须为两个 ViewModel 编写相同的代码。我试图创建一个ButtonCommand继承自 RelayCommand 的类,但由于并非每个视图都具有此功能,因此我无法使用此方法实现它。

标签: c#wpfmvvm

解决方案


这是一个 XY 问题。您正在寻求一种解决 Y 的方法(ButtonCommand实际上不是重复的),您的问题是 X(您的代码中已经存在重复)

我有两个相同的视图 View1.xaml 和 View2.xaml

我想补充一下,您还说过您不仅有两个相同的视图,还有更多。

解决这个问题的最好方法是有一个ParentViewModel可以构造子 ViewModel的父级

所以首先,我们需要一个子视图模型的接口

IMyViewModel

public interface IMyViewModel
{
    void Load(); 
}

接下来,实现

我的视图模型

public class MyViewModel : ViewModelBase, IMyViewModel
{
    public MainViewModel() 
    {
        ButtonCommand = new RelayCommand(ExecuteButtonCommand, CanExecuteButtonCommand);
    }
    
    public RelayCommand ButtonCommand { get; private set; }
    
    public void Load()
    {
        //Example load logic
        InvalidateCommands();
    }
    
    private void InvalidateCommands()
    {
        ButtonCommand.RaiseCanExecuteChanged();
    }
        
    private void ExecuteButtonCommand(object message)
    {
        //Some method to fill the corresponding textfield
    }

    private bool CanExecuteButtonCommand(object message)
    {
        return true;
    }
}

最后,ParentViewModel它负责创建视图模型。请注意,我没有告诉它何时创建 ViewModel,我将由您决定。

父视图模型

public class ParentViewModel : ViewModelBase 
{
    private Func<IMyViewModel> _myVmCreator;
    
    public ParentViewModel(Func<IMyViewModel> myVmCreator) 
    {
        _friendEditVmCreator = friendEditVmCreator;
    }
    
    public ObservableCollection<IMyViewModel> MyViewModels { get; private set; }
    
    private IMyViewModel CreateAndLoadMyViewModel()
    {
        var myVm = _myVmCreator();
        MyViewModels.Add(myVm);
        myVm.Load();
        return myVm;
    }
}

这将允许您创建任意数量MyViewModels或任何其他类型的 ViewModel,只要它实现IMyViewModel

上面的例子来源于本课程:https ://www.pluralsight.com/courses/wpf-mvvm-test-driven-development-viewmodels

我强烈推荐它。


推荐阅读