在类对象的setter中实现RaiseCanExecuteChanged方法

时间:2018-04-26 08:07:12

标签: c# wpf mvvm prism delegatecommand

我仍然不确定我的方法是否正确,但在尝试实现MVVM模式时,我已按以下方式创建了一个模型类'Test':

public class Test : BindableBase
{
    private int testNumber;
    public int TestNumber
    {
        get { return testNumber; }
        set { SetProperty(ref testNumber, value) }
    }
    ...
}

然后我在ViewModel

中创建了这个类的实例
class ViewModel : BindableBase
{
    private Test testVM;
    public Test TestVM
    {
        get { return testVM; }
        set { SetProperty(ref testVM, value); }
    }
    ...

View的XAML代码中,我通过Test属性绑定了TestVM类的所有属性。虽然这很好用,但在尝试实现DelegateCommad时遇到了问题。

    public DelegateCommand StartTestCommand { get; private set; }

到目前为止,在实现DelegateCommand时,如果我想在属性发生变化时触发CanExecute方法,我会在属性的setter中包含DelegateCommand.RaiseCanExecuteChanged()。像这样:

    ...
    private bool duringTest;
    public bool DuringTest
    {
        get { return duringTest; }
        set
        {
            SetProperty(ref duringTest, value);
            StartTestCommand.RaiseCanExecuteChanged();
        }
    }
    ...

这适用于ViewModel中声明的属性,但是当对Test属性使用相同的方法时,这不再有效。

    ...
    private Test testVM;
    public Test TestVM
    {
        get { return testVM; }
        set
        {
            SetProperty(ref testVM, value);
            StartTestCommand.RaiseCanExecuteChanged();
        }
    }
}

我希望每次更改TestVM的属性时,都会调用setter,而是直接更新模型。

我做错了什么?在Model中使用ViewModel对象时的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

更改对象的属性值不会更改对象的引用。

声明此

public Test TestVM
{
    get { return testVM; }
    set
    {
        SetProperty(ref testVM, value);
        StartTestCommand.RaiseCanExecuteChanged();
    }
}

你基本上是在告诉编译器:当TestVM对象的引用被改变时(甚至改为相同的值),更新StartTestCommand的状态。

但很明显,一旦分配了该对象,就不会更改对该对象的引用。

如果要在某些子视图模型(ViewModel)属性发生更改时更新父视图模型(Test)中的命令,则可以使用PropertyChanged事件:

public Test TestVM
{
    get { return testVM; }
    set
    {
        Test oldValue = testVM;
        if (SetProperty(ref testVM, value))
        {
            if (oldValue != null)
            {
                oldValue.PropertyChanged -= TestPropertyChanged;
            }

            if (testVM!= null)
            {
                testVM.PropertyChanged += TestPropertyChanged;
            }
        }
    }
}

void TestPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    // filter if necessary
    if (e.PropertyName == "...")
    {
        StartTestCommand.RaiseCanExecuteChanged();
    }
}