【问题标题】:Textboxes are not updated when the ViewModel's data changesViewModel 的数据更改时,文本框不会更新
【发布时间】: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 实现,并且包装器中的所有属性都应该指向模型中的属性。

标签: c# wpf xaml mvvm


【解决方案1】:

您正在为一个新的 Model 对象更改整个 Model,但您并没有通知 UI 是您所做的。您的 EmployeeViewModel 类应该实现 INotifyPropertyChanged 就像您对员工模型所做的那样,然后属性 Employee 应该调用 OnPropertyChanged 方法

    private EmployeeModel _employee;
    public EmployeeModel Employee {
        get { return _employee; }
        set {
            if(_employee!=value) {
                _employee=value;
                OnPropertyChanged();
            }
         }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-14
    • 1970-01-01
    • 2015-11-11
    • 2011-08-09
    • 1970-01-01
    • 2017-03-23
    • 2014-12-13
    • 2011-09-19
    相关资源
    最近更新 更多