Реализация метода RaiseCanExecuteChanged внутри установщика объекта класса - PullRequest
0 голосов
/ 26 апреля 2018

Я до сих пор не уверен, что мой подход правильный, но, пытаясь реализовать шаблон 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); }
    }
    ...

И в коде XAML View я связываю все свойства класса Test через свойство TestVM.Хотя это работает нормально, я столкнулся с проблемой при попытке реализовать DelegateCommad.

    public DelegateCommand StartTestCommand { get; private set; }

До сих пор, при реализации DelegateCommand s, если я хочу вызвать метод CanExecute, когдасвойство изменилось, я включаю 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 изменяется, вызывается установщик, но вместо этого модель обновляется напрямую.

Что я делаю не так?Какой правильный подход при использовании объекта Model в ViewModel?

1 Ответ

0 голосов
/ 26 апреля 2018

Изменение значения свойства объекта не меняет ссылку на объект.

Объявляя это

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();
    }
}
...