更改其他TextBox时WPF绑定TextBox值未更新

时间:2019-06-19 11:31:24

标签: c# wpf xaml mvvm

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

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

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

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

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

我应该如何设置以便在更改DoB时不修改模型就更新Age?


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

查看

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

2 个答案:

答案 0 :(得分:0)

如果您不想在INotifyPropertyChanged中实现EmployeeModel,则不应绑定到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}" />

答案 1 :(得分:0)

我也正在使用您的方法来计算年龄,并且可以正常工作。

我有一个在单独的类中定义的Patient模型

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

这是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}"/>