触发OnPropertyChanged时更新其他属性

时间:2017-10-16 07:31:16

标签: c# .net model

我在这里检查了其他链接,但我无法得到正确答案。我有xaml,它包含两个文本框。第一个是几小时,而下一个是几分钟。每当我更改文本框中的小时值时,分钟应重置为0.如何使用OnPropertyChange执行此操作?

public class Variable : INotifyPropertyChanged
{
    public Variable()
    {
        this.hours = "1";
        this.minutes = "2";
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private string hours;
    private string minutes;

    public string Hours
    {
        get { return this.hours.ToString(); }
        set
        {
            if (this.hours != value)
            { 
                this.hours = value;
                this.minutes = "0";
                this.OnPropertyChanged("Hours");
            }
        }
    }

    public string Minutes { get { return this.minutes; } }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName ));
    }
}

2 个答案:

答案 0 :(得分:3)

除非Minutes文本框是只读的,否则您应该拥有该属性的setter:

public string Minutes
{
    get => this.minutes; 
    set
    {
        if (this.minutes != value)
        {
            this.minutes = value;
            OnPropertyChanged();
        }
    }
}

现在您可以在Hours setter中使用此setter来通知UI更改:

if (this.hours != value)
{ 
    this.hours = value;
    this.OnPropertyChanged();
    this.Minutes = "0";
}

相反,如果Minutes是正确的只读属性,那么您有两个选项:创建其setter private(并按上面使用它)或手动调用OnPropertyChanged()以通知UI改变:

if (this.hours != value)
{ 
    this.hours = value;
    this.OnPropertyChanged();

    this.minutes = "0";
    this.OnPropertyChanged(nameof(Minutes));
}

我强烈反对第二个选项,因为它增加了不必要的复杂性,除非绝对需要,否则我不想手动通知更改。

所有这些都表示您可以在代码中改进更多内容。

OnPropertyChanged()有一个带[CallerMemberName]属性的参数,那么您不需要指定属性名称(如果它是从该属性中调用的)。如果必须(请参阅第二个示例),请使用nameof(PropertyName)代替"PropertyName",因为重命名您的媒体资源时会自动更改。

我没有代码的大图片,但如果HoursMinutes是整数属性,那么您应该int代替string。如果输入错误,您最好尽快通知用户。您还应该验证值:

if (value < 0 || value >= 60)
    throw new ArgumentOutOfRangeException(...);

不是在这种情况下,但通常当你有一个属性,其中支持字段只是因为你没有setter,那么你可以使用:

public string Minutes { get; private set; }

答案 1 :(得分:2)

只需再次使用名称OnPropertyChanged

调用Minutes调用者
OnPropertyChanged(nameof(Minutes));

或者您可以将一个私有的setter添加到在那里调用它的minutes属性。 所以你会有这样的事情:

public class Variable : INotifyPropertyChanged
{
    public Variable()
    {
        this.hours = "1";
        this.minutes = "2";
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private string hours;
    private string minutes;

    public string Hours
    {
        get { return this.hours.ToString(); }
        set
        {
            if (this.hours != value)
            { 
                this.hours = value;
                this.OnPropertyChanged();

                this.Minutes = "0";                    
            }
        }
    }

    public string Minutes 
    { 
        get { return this.minutes; }
        private set
        {
            if(this.minutes == value)
                return;

            this.minutes = value;
            OnPropertyChanged()
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName ));
    }
}

顺便说一下,调用者中的[CallerMemberName]属性意味着如果你没有传递参数的任何值,它就会取名叫谁的名字。如果属性,它将是该属性的名称,因此您不必编写它。