子进程命令后的调用方法

时间:2014-12-16 04:03:30

标签: c# wpf mvvm

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

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

    private void ExecuteMyCommand()
    {
        // Do work...
    }
}

现在,假设我在视图模型中创建了一个ObservableCollection<MyClass>,它绑定到ListView。 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而不是视图模型,这不会让人感到麻烦,但仍然不是很完美我的眼睛......

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

3 个答案:

答案 0 :(得分:1)

启用此功能的另一种方法如下:

<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
    }
}

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

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

答案 1 :(得分:0)

我设法让这个工作(我认为)非常好。

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

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

然后在XAML中查看View,我将CommandParameter设置为我希望它之后运行的命令。

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

如果XAML中没有提供CommandParameter,则传递null。做...

答案 2 :(得分:0)

您还可以在按钮上放置一个click事件(它们向上冒泡到视图),然后从代码隐藏中调用命令