C# 属性更改多次发射

C# 属性更改多次发射,c#,wpf,events,event-handling,C#,Wpf,Events,Event Handling,我有一个具有几个属性的类。当这些更改时,将引发一个PropertyChangedEvent。某些属性依赖于其他属性,因此当其中一个依赖项发生更改时,它会为自身以及依赖它的属性引发PropertyChangedEvent 我的问题是,我已将属性changedeventhandler附加到此类的实例。当一个属性依赖于另一个属性时,会多次调用此事件处理程序。有没有办法绕过这个问题 更新 一个小代码,只是为了说明我所说的: private bool _foo; private bool

我有一个具有几个属性的类。当这些更改时,将引发一个
PropertyChangedEvent
。某些属性依赖于其他属性,因此当其中一个依赖项发生更改时,它会为自身以及依赖它的属性引发
PropertyChangedEvent

我的问题是,我已将
属性changedeventhandler
附加到此类的实例。当一个属性依赖于另一个属性时,会多次调用此事件处理程序。有没有办法绕过这个问题

更新

一个小代码,只是为了说明我所说的:

    private bool _foo;
    private bool _bar;

    public bool Foo
    {
        get { return _foo; }
        set
        {
            _foo = value;
            OnPropertyChanged("Foo");
            OnPropertyChanged("Baz");
        }
    }

    public bool Bar
    {
        get { return _bar; }
        set
        {
            _bar = value;
            OnPropertyChanged("Bar");
            OnPropertyChanged("Baz");
        }
    }

    public bool Baz
    {
        get
        {
            return Foo && Bar;
        }
    }

当设置了
Foo
时,
Baz
也会改变。如果我附加了一个
属性changedeventhandler
,当我设置
Foo
时,它将被调用两次。我只想叫它一次。有什么好办法吗?

在setter中插入一个值更改检查,如:

set
{
   if(value != [yourfield])
   {
      yourfield = value;
      OnPropertyChanged(Yourfield);
   }
}

在setter中插入值更改检查,如:

set
{
   if(value != [yourfield])
   {
      yourfield = value;
      OnPropertyChanged(Yourfield);
   }
}

你所需要做的就是对这个问题进行逻辑思考,然后得到答案。您有以下情况:

public bool Foo
{
    get { return _foo; }
    set
    {
        _foo = value;
        OnPropertyChanged("Foo");
        OnPropertyChanged("Baz");
    }
}

public bool Bar
{
    get { return _bar; }
    set
    {
        _bar = value;
        OnPropertyChanged("Bar");
        OnPropertyChanged("Baz");
    }
}

public bool Baz
{
    get
    {
        return Foo && Bar;
    }
}
我的第一点意见是,如果要一次多次引发
INotifyPropertyChanged.PropertyChanged
事件,那么最好使用这样的实现,这样可以一次引发任意多个属性的事件:

protected virtual void NotifyPropertyChanged(params string[] propertyNames)
{
    if (PropertyChanged != null)
    {
        foreach (string propertyName in propertyNames) 
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

回到你的问题上来。。。让我们考虑一下您的要求:

  • Baz
    的值发生变化时,需要通知接口
  • Foo
    Bar
    属性值更改时,其值可以更改。。。因此,您需要在其中任何一个发生更改时通知接口,正如您所做的那样

    现在,@frank评论说,您应该从属性1的setter触发一个更新属性2的方法,通过更改该方法将触发他自己的属性更改。让我们考虑一下。。。大概,您需要从
    Foo
    Bar
    属性设置器调用相同的方法才能使其工作

    但是,实际发生的情况是,当
    Foo
    Bar
    值更改时,该方法将被调用两次,因此
    INotifyPropertyChanged
    通知仍将被调用两次,尽管它现在来自
    Baz
    setter。。。所以很明显,这并没有改善

    然而,还有一个选择可能对你有用。为此,您需要添加一个助手方法,该方法将更新
    Foo
    Bar
    属性值,并代表
    Baz
    属性通知
    INotifyPropertyChanged
    接口:

    public void UpdateBaz(bool? foo, bool? bar)
    {
        if (foo != null) Foo = foo;
        if (bar != null) Bar = bar;
        OnPropertyChanged("Baz");
    }
    
    当然,要使其工作,您需要从两个属性处理程序中删除对
    OnPropertyChanged(“Baz”)
    的调用:

    public bool Foo
    {
        get { return _foo; }
        set { _foo = value; OnPropertyChanged("Foo"); }
    }
    
    public bool Bar
    {
        get { return _bar; }
        set { _bar = value; OnPropertyChanged("Bar"); }
    }
    

    但是,如果您希望通过
    绑定更新
    Foo
    Bar
    属性,那么您将返回@frank的建议,即调用此方法两次,并分别更新这两个属性。在这种情况下,您似乎只需要忍受两次通知
    Baz
    属性。

    您所需要做的就是对这个问题进行逻辑思考片刻,以获得您的答案。您有以下情况:

    public bool Foo
    {
        get { return _foo; }
        set
        {
            _foo = value;
            OnPropertyChanged("Foo");
            OnPropertyChanged("Baz");
        }
    }
    
    public bool Bar
    {
        get { return _bar; }
        set
        {
            _bar = value;
            OnPropertyChanged("Bar");
            OnPropertyChanged("Baz");
        }
    }
    
    public bool Baz
    {
        get
        {
            return Foo && Bar;
        }
    }
    
    我的第一点意见是,如果要一次多次引发
    INotifyPropertyChanged.PropertyChanged
    事件,那么最好使用这样的实现,这样可以一次引发任意多个属性的事件:

    protected virtual void NotifyPropertyChanged(params string[] propertyNames)
    {
        if (PropertyChanged != null)
        {
            foreach (string propertyName in propertyNames) 
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    回到你的问题上来。。。让我们考虑一下您的要求:

  • Baz
    的值发生变化时,需要通知接口
  • Foo
    Bar
    属性值更改时,其值可以更改。。。因此,您需要在其中任何一个发生更改时通知接口,正如您所做的那样

    现在,@frank评论说,您应该从属性1的setter触发一个更新属性2的方法,通过更改该方法将触发他自己的属性更改。让我们考虑一下。。。大概,您需要从
    Foo
    Bar
    属性设置器调用相同的方法才能使其工作

    但是,实际发生的情况是,当
    Foo
    Bar
    值更改时,该方法将被调用两次,因此
    INotifyPropertyChanged
    通知仍将被调用两次,尽管它现在来自
    Baz
    setter。。。所以很明显,这并没有改善

    然而,还有一个选择可能对你有用。为此,您需要添加一个助手方法,该方法将更新
    Foo
    Bar
    属性值,并代表
    Baz
    属性通知
    INotifyPropertyChanged
    接口:

    public void UpdateBaz(bool? foo, bool? bar)
    {
        if (foo != null) Foo = foo;
        if (bar != null) Bar = bar;
        OnPropertyChanged("Baz");
    }
    
    当然,要使其工作,您需要从两个属性处理程序中删除对
    OnPropertyChanged(“Baz”)
    的调用:

    public bool Foo
    {
        get { return _foo; }
        set { _foo = value; OnPropertyChanged("Foo"); }
    }
    
    public bool Bar
    {
        get { return _bar; }
        set { _bar = value; OnPropertyChanged("Bar"); }
    }
    

    但是,如果您希望通过
    绑定更新
    Foo
    Bar
    属性,那么您将返回@frank的建议,即调用此方法两次,并分别更新这两个属性。在这种情况下,您似乎只能忍受
    Baz
    属性被通知两次。

    我觉得这完全合乎逻辑。您不应该禁用所有这些事件:当属性发生更改时,它应该触发更改事件。你需要如何处理它?EventHandler中发生了什么?为什么要忽略其他处理程序?不应引发从另一个处理程序更改的另一个属性。您应该从属性1的setter触发一个方法来更新属性2 w