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

Implementing RaiseCanExecuteChanged method inside setter of a class object

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

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

然后我在 ViewModel:

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

并且在 View 的 XAML 代码中,我通过 TestVM 属性 绑定 Test class 的所有属性.虽然这工作正常,但我 运行 在尝试实现 DelegateCommad.

时遇到了问题
    public DelegateCommand StartTestCommand { get; private set; }

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

    ...
    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,但会直接更新模型。

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

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

正在声明

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

你基本上是在告诉编译器:当对 TestVM 对象的引用发生变化时(即使是相同的值),更新 StartTestCommand 的状态。

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

如果您想在某些子视图模型 (Test) 的属性更改时更新父视图模型 (ViewModel) 中的命令,您可以使用 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();
    }
}