首页 > 解决方案 > 更改其他文本框时 WPF 绑定文本框值未更新

问题描述

我有一个 WPF 窗口,允许用户编辑员工的出生日期,在这个窗口中也是一个文本框,用于显示输入的 DoB 的年龄。

DoB 文本框绑定到我的 EmployeeModel Dob 属性

Age 文本框绑定到我的 EmployeeModel Age 属性并且无法设置,并且使用 Dob 值获取。

我面临的问题是当用户更改 DoB 时,年龄文本框没有得到更新。

我发现如果我INotifyPropertyChanged在 EmployeeModel 中实现并添加OnPropertyChanged("Age")Dob 属性,那么 Age 值就会更新。但这违背了我的建议,即我的模型应该只是业务逻辑,不应该实现 INotifyPropertyChanged。

我应该如何设置它,以便在不修改模型的情况下更改 DoB 时更新年龄?


员工模型

class EmployeeModel
{
    public DateTime? Dob { get => _dob; set => _dob = value; }
    public int Age
    {
        get
        {
            if (_dob == null)
                return 0;

            DateTime now = DateTime.Today;
            int age = now.Year - _dob.Value.Year;
            if (now < _dob.Value.AddYears(age))
                age--;

            return age;
        }
    }
}

员工视图模型

class EmployeeViewModel : INotifyPropertyChanged
{
    private EmployeeModel _employee;

    public EmployeeModel Employee
    {
        get => _employee;
        set
        {
            if (_employee != value)
            {
                _employee = value;
                OnPropertyChanged();
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]string caller = null)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(caller));
    }

看法

<Label Content="DOB" />
<DatePicker SelectedDate="{Binding Employee.Dob, TargetNullValue=''}" />
<Label Content="Age" />
<TextBox Text="{Binding Employee.Age, Mode=OneWay}" />

标签: c#wpfxamlmvvm

解决方案


如果您不想实现INotifyPropertyChangedin EmployeeModel,则不应绑定到 an 的属性,EmployeeModel而是绑定到将属性包装在 中的视图模型的属性EmployeeModel,例如:

class EmployeeViewModel : INotifyPropertyChanged
{
    private EmployeeModel _employee;

    public DateTime? Dob
    {
        get { return _employee.Dob; }
        set { _employee.Dob = value; OnPropertyChanged(); OnPropertyChanged(nameof(Age)); }
    }

    public int Age
    {
        get { return _employee.Age; }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]string caller = null)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(caller));
    }
}

XAML:

<Label Content="DOB" />
<DatePicker SelectedDate="{Binding Dob, TargetNullValue=''}" />
<Label Content="Age" />
<TextBox Text="{Binding Age, Mode=OneWay}" />

推荐阅读