简体   繁体   English

当其他 TextBox 更改时,WPF 绑定的 TextBox 值不会更新

[英]WPF Bound TextBox value not updating when other TextBox is changed

I have a WPF window that allows the user to edit the Date of Birth of an employee, in this window is also a TextBox to display the age from the DoB entered.我有一个 WPF 窗口,允许用户编辑员工的出生日期,在此窗口中还有一个文本框,用于显示输入的 DoB 的年龄。

The DoB textbox is bound to my EmployeeModel Dob property DoB 文本框绑定到我的 EmployeeModel Dob 属性

The Age textbox is bound to my EmployeeModel Age property and cannot be set, and the get using the Dob value. Age 文本框绑定到我的 EmployeeModel Age 属性并且无法设置,并且使用 Dob 值获取。

The problem I'm facing is when the user changes the DoB, the Age textbox does not get updated.我面临的问题是当用户更改 DoB 时,年龄文本框不会更新。

I have found that if I implement INotifyPropertyChanged in my EmployeeModel, and add OnPropertyChanged("Age") in the Dob property, then the Age value gets updated.我发现如果我在我的 EmployeeModel 中实现INotifyPropertyChanged ,并在 Dob 属性中添加OnPropertyChanged("Age") ,那么 Age 值就会更新。 But this goes against what I have been advised that my Models should be business logic only and should not implement INotifyPropertyChanged.但这违背了我的建议,我的模型应该只是业务逻辑,而不应该实现 INotifyPropertyChanged。

How should I set this up so Age updates when DoB is changed without modifying the Model?我应该如何设置它以便在不修改模型的情况下更改 DoB 时更新年龄?


EmployeeModel员工模型

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;
        }
    }
}

EmployeeViewModel员工视图模型

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));
    }

View看法

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

If you don't want to implement INotifyPropertyChanged in EmployeeModel you shouldn't bind to a property of an EmployeeModel but to a property of the view model that wraps the property in EmployeeModel , eg:如果您不想在EmployeeModel实现INotifyPropertyChanged ,则不应绑定到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: XAML:

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

I am also using your approach to calculate the age and it works properly.我也在用你的方法来计算年龄,它工作正常。

I have a Patient model which is defined in a separate class我有一个在单独的类中定义的患者模型

Here is the ViewModel:这是视图模型:

class PatientRecordDetailsViewModel : INotifyPropertyChanged
{
    public DateTime PatientDateOfBirth
    {
        get => m_patientDateofbirth;
        set
        {
            m_patientDateofbirth = value;
            OnPropertyChange("PatientDateOfBirth");
            OnPropertyChange(nameof(PatientAge));
        }
    }

    public int PatientAge => CalculateAge();

    private int CalculateAge()
    {
        if (m_patientDateofbirth == null)
        {
            return 0;
        }
        else
        {
            int CurrentYear = DateTime.Now.Year;
            int BirthYear = m_patientDateofbirth.Year;
            m_patientAge = CurrentYear - BirthYear;
            return m_patientAge;
        }           
    }

    public event PropertyChangedEventHandler PropertyChanged;
     private void OnPropertyChange(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Here is the Xaml这是 Xaml

<DatePicker Name="Date" Grid.Column="0" SelectedDate ="{Binding Path = PatientDateOfBirth, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource DatePickerStyle}" VerticalAlignment="Center" Height="30" Padding="3,0,5,0"/>
<TextBox  Name="Age" Grid.Column="1" Text="{Binding Path = PatientAge, Mode=OneWay}" Style="{StaticResource TextBoxStyle}"/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM