在子项执行命令后调用方法

本文关键字:调用 方法 命令 执行 | 更新日期: 2023-09-27 18:34:16

我目前正在学习如何在C#/WPF项目中实现命令。假设我有一个带有简单命令MyCommand的类MyClass

public class MyClass
{
    private RelayCommand _myCommand;
    public ICommand MyCommand
    {
        get
        {
            if (_myCommand == null)
                _myCommand = new RelayCommand(_ => ExecuteMyCommand());
            return _myCommand;
        }
    }
    private void ExecuteMyCommand()
    {
        // Do work...
    }
}

现在,假设我在绑定到 ListView 的视图模型中创建了一个ObservableCollection<MyClass>。ListView 有一个 GridViewColumn,其中包含绑定到 MyCommand 的按钮。一切都很好。

public class MyViewModel
{
    private ObservableCollection<MyClass> _myCollection;
    public ObservableCollection<MyClass> MyCollection
    {
        get { return _myCollection; }
        set
        {
            _myCollection = value;
            RaisePropertyChanged("MyCollection");
        }
    }
    public void Refresh()
    {
        // Do work to refresh MyCollection to it's "live" state
    }
}

现在,在 MyCollection 中的一个对象执行 MyCommand 后,我需要在视图模型上调用 Refresh(( 方法,但我不确定如何处理这种情况。

我尝试过的事情:

  • 在 MyClass 的构造期间添加对视图模型的引用,允许命令在命令执行时通过视图模型的引用调用 Refresh((。这工作正常,但我真的不喜欢代码 - 让它引用特定的视图模型感觉很混乱,尤其是当它在程序的其他部分使用时。

我考虑过的事情:

  • 将 Refresh(( 更改为 ObservableCollection<MyClass> 的扩展方法,添加前面提到的引用属性,但引用 ObservableCollection 而不是视图模型,这不会感觉那么混乱,但在我眼中仍然不是很完美......

解决此问题的最佳/正确方法是什么?

在子项执行命令后调用方法

打开此功能的另一种方法是:

<MenuItem Content="Run MyCommand"
          Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.RefreshCommand}"
          CommandParameter="{Binding}"/>

然后,在你的MyViewModel

public class MyViewModel
{
    private ObservableCollection<MyClass> _myCollection;
    public ObservableCollection<MyClass> MyCollection
    {
        get { return _myCollection; }
        set
        {
            _myCollection = value;
            RaisePropertyChanged("MyCollection");
        }
    }
    //...
    private ICommand _refreshCommand;
    public ICommand RefreshCommand
    {
        get
        {
            if (_refreshCommand== null)
                _refreshCommand= new RelayCommand<MyClass>(p => Refresh(p));
            return _refreshCommand;
        }
    }
    public void Refresh(MyClass parameter)
    {
        if (null == parameter)
            return;
        parameter.ExecuteMyCommand();
        // Do work to refresh MyCollection to it's "live" state
    }
}

注意:目前您不需要在每个MyClass实例上都有MyCommand - 您可以将其作为参数传递给父视图模型。

我不能说有完成任务的正确方法。所以我不能说哪一个更好。

我设法以一种非常好的方式(我认为(让它工作。

首先,我将 Refresh(( 更改为命令。然后,我在 MyCommand 方法中添加了一个参数。该方法执行其工作,然后检查参数以查看它是否是命令,然后执行它。

private void ExecuteMyCommand(object param)
{
    // Do work...
    if (param != null && param is ICommand)
        ((ICommand)param).Execute(null);
}

然后在视图的 XAML 中,我将命令参数设置为我希望它之后运行的命令。

<MenuItem Content="Run MyCommand"
          Command="{Binding UploadCommand}"
          CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.RefreshCommand}"/>

如果在 XAML 中未提供命令参数,则传递 null。做。。。

您还可以在按钮上放置一个单击事件(它们冒泡到视图(,并从代码隐藏调用命令