【发布时间】:2019-06-18 05:49:40
【问题描述】:
我已经实现了我的第一个 WPF MVVM 窗口。在加载窗口时,会调用一个从 Access 数据库中获取数据的方法,并且所有适当的文本框都绑定到 EmployeeModel 的属性。
我还有一个名为 Refresh 的按钮,它运行相同的方法从数据库中获取员工数据,出于测试目的,我让 Refresh 按钮获取不同的员工 ID。
但是,新的 EmployeeModel 并没有更新窗口的字段。我使用断点发现将新数据保存到 EmployeeModel 没有问题,但似乎没有使用这些新数据更新文本框。
按照在线指南,我使用了 INotifyProperyChanged 并在我的视图中使用了 UpdateSourceTrigger。
员工模型
class EmployeeModel : MyDbConnector, INotifyPropertyChanged
{
private int _employeeId;
private string _firstname;
public int EmployeeId
{
get => _employeeId;
set
{
if (_employeeId != value)
{
_employeeId = value;
OnPropertyChanged();
}
}
}
public string Firstname
{
get => _firstname;
set
{
if (_firstname != value)
{
_firstname = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]string caller = null)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
public static EmployeeModel FindById(int id)
{
//code omitted
}
EmployeeViewModel
class EmployeeViewModel
{
public EmployeeModel Employee { get; set; }
public EmployeeViewModel()
{
LoadEmployee(100);
}
public bool LoadEmployee(int employeeId)
{
if (!DbConnector.OpenDB())
return false;
Employee = EmployeeModel.FindById(employeeId);
DbConnector.CloseDB();
if (Employee == null)
return false;
return true;
}
public void Refresh()
{
// Load a different employee
if (!LoadEmployee(102))
MessageBox.Show("An error has occurred");
}
}
查看
<Label Width="100" Content="Employee ID"/>
<TextBox Width="100" IsEnabled="False" Text="{Binding Employee.EmployeeId, UpdateSourceTrigger=PropertyChanged}"/>
<Label Width="100" Content="First name"/>
<TextBox Text="{Binding Employee.Firstname, TargetNullValue='', UpdateSourceTrigger=PropertyChanged}"/>
【问题讨论】:
-
一个好的经验法则是,除非它完全实现 INotifyPropertyChanged,否则不要将其称为 ViewModel。
-
我一直在使用 INotifyPropertyChanged 实现我的模型。我是不是弄错了,它应该在 ViewModels 上实现。模型上根本不需要 INotifyPropertyChanged 吗?
-
几乎是的。模型通常是 POCO 类,用于将内容来回发送到数据层。但是,如果您的“模型”类的行为类似于视图模型(绑定在 XAML 中的属性等),那么它们需要 INPC。
-
在 mvvm 模型中不应实现 INotifyPropertyChanged,因为模型只是数据实体(它们不属于 UI 层)。如果您想以您的方式使用“模型”,您应该在模型周围创建一个包装器,该包装器基本上是同一个类,但具有 INotifyPropertyChanged 实现,并且包装器中的所有属性都应该指向模型中的属性。