WPF/MVVM/模型不更新视图模型
WPF / MVVM / Model does not update viewmodel
上下文:
- 我在 MVVM 应用程序中绑定 属性 时遇到问题。现在我做了一个小项目来测试这个案例。它仅包括 window、视图模型、模型、BindableObject(带有 INotifyProperyChanged 的抽象 class)和命令 classes。所有 classes 都在同一个命名空间中,datacontext 在视图中设置,模型和 vm 有 INotifyProperyChanged,视图中的文本绑定到绑定到模型 属性 的 vm 属性。构造函数设置模型 属性 并影响视图模型和视图中的 属性。
问题:
- 当我在模型中更改 属性 时,它不会在视图模型和视图中更改 属性。
这是 BaseModel 和命令 classes:
abstract class BindableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertieChanged ([CallerMemberName]string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
class Command : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public Command(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}
型号:
public class Model : BindableObject
{
private int modelValue;
public int ModelValue { get => modelValue; set { modelValue = value; OnPropertieChanged(); } }
public Model ()
{
ModelValue = 111;
}
public void ChangeValue ()
{
ModelValue = 777;
}
}
视图模型:
class MainVM : BindableObject
{
private int myValue;
public int MyValue { get => myValue; set { myValue = value; OnPropertieChanged(); } }
public ICommand Command1 { get; set; }
public MainVM()
{
var model = new Model();
MyValue = model.ModelValue;
Command1 = new Command( (obj) => model.ChangeValue() );
}
}
查看:
<Window>
...
<Window.DataContext>
<local:MainVM/>
</Window.DataContext>
<StackPanel>
<TextBlock Text="{Binding MyValue}"/>
<Button Command="{Binding Command1}"/>
</StackPanel>
</Window>
问题是您的视图模型中的命令正在调用模型实例上的方法,但是您的 xaml 绑定到视图模型中单独的 属性 类型 int (我的价值)。这就是为什么 MyValue 在 vm 构造函数中设置一次但从未使用命令更新的原因。
在视图模型中将模型 class 的实例设为 属性:
private Model _myModel;
public Model MyModel
{
get
{
return _myModel;
}
set
{
_myModel = value;
OnPropertieChanged();
}
}
public ICommand Command1 { get; set; }
public MainVM()
{
MyModel = new Model();
Command1 = new Command((obj) => MyModel.ChangeValue());
}
并绑定到 xaml 中的模型值 属性。
<StackPanel>
<TextBlock Text="{Binding MyModel.ModelValue}"/>
<Button Height="50" Width="100" Command="{Binding Command1}"/>
</StackPanel>
不过,一般来说,模型 class 通常不执行逻辑;相反,逻辑要么在服务 class 中的模型实例上执行,要么在视图模型中的客户端执行。但那是一个单独的讨论。
上下文:
- 我在 MVVM 应用程序中绑定 属性 时遇到问题。现在我做了一个小项目来测试这个案例。它仅包括 window、视图模型、模型、BindableObject(带有 INotifyProperyChanged 的抽象 class)和命令 classes。所有 classes 都在同一个命名空间中,datacontext 在视图中设置,模型和 vm 有 INotifyProperyChanged,视图中的文本绑定到绑定到模型 属性 的 vm 属性。构造函数设置模型 属性 并影响视图模型和视图中的 属性。
问题:
- 当我在模型中更改 属性 时,它不会在视图模型和视图中更改 属性。
这是 BaseModel 和命令 classes:
abstract class BindableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertieChanged ([CallerMemberName]string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
class Command : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public Command(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}
型号:
public class Model : BindableObject
{
private int modelValue;
public int ModelValue { get => modelValue; set { modelValue = value; OnPropertieChanged(); } }
public Model ()
{
ModelValue = 111;
}
public void ChangeValue ()
{
ModelValue = 777;
}
}
视图模型:
class MainVM : BindableObject
{
private int myValue;
public int MyValue { get => myValue; set { myValue = value; OnPropertieChanged(); } }
public ICommand Command1 { get; set; }
public MainVM()
{
var model = new Model();
MyValue = model.ModelValue;
Command1 = new Command( (obj) => model.ChangeValue() );
}
}
查看:
<Window>
...
<Window.DataContext>
<local:MainVM/>
</Window.DataContext>
<StackPanel>
<TextBlock Text="{Binding MyValue}"/>
<Button Command="{Binding Command1}"/>
</StackPanel>
</Window>
问题是您的视图模型中的命令正在调用模型实例上的方法,但是您的 xaml 绑定到视图模型中单独的 属性 类型 int (我的价值)。这就是为什么 MyValue 在 vm 构造函数中设置一次但从未使用命令更新的原因。
在视图模型中将模型 class 的实例设为 属性:
private Model _myModel;
public Model MyModel
{
get
{
return _myModel;
}
set
{
_myModel = value;
OnPropertieChanged();
}
}
public ICommand Command1 { get; set; }
public MainVM()
{
MyModel = new Model();
Command1 = new Command((obj) => MyModel.ChangeValue());
}
并绑定到 xaml 中的模型值 属性。
<StackPanel>
<TextBlock Text="{Binding MyModel.ModelValue}"/>
<Button Height="50" Width="100" Command="{Binding Command1}"/>
</StackPanel>
不过,一般来说,模型 class 通常不执行逻辑;相反,逻辑要么在服务 class 中的模型实例上执行,要么在视图模型中的客户端执行。但那是一个单独的讨论。