在 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; }
到目前为止,在实现 DelegateCommand
s 时,如果我想在 属性 发生变化时触发 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();
}
}
我仍然不确定我的方法是否正确,但为了尝试实现 MVVM 模式,我按以下方式创建了一个模型 class '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 代码中,我通过 TestVM
属性 绑定 Test
class 的所有属性.虽然这工作正常,但我 运行 在尝试实现 DelegateCommad
.
public DelegateCommand StartTestCommand { get; private set; }
到目前为止,在实现 DelegateCommand
s 时,如果我想在 属性 发生变化时触发 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();
}
}