PropertyChanged?.Invoke(...) 调用 在单步执行 Set 语句时再次调用 setter

发布于 2025-01-19 19:19:05 字数 2003 浏览 0 评论 0原文

我有一个实现 INotifyPropertyChanged 的​​简单基类。该代码有效。但是,当我单步执行 Set 语句时,当 Set 语句调用 SetProperty() 时,我注意到 PropertyChanged?.Invoke(...) 调用再次调用 setter。

因此,子类中的 setter 代码看起来像:

private string someProperty ;
public string SomeProperty { get => someProperty ;
set {
    // Do some tests on value to make sure it's valid
    SetProperty(ref someProperty, value);
    // Now do some other stuff once that is set
}

当我单步执行它时,调用堆栈显示:

  • SomeProperty.Set( valuetype value); ????怎么又来了???? --- 5
  • 外部代码 --- 4
  • OnPropertyChanged(string propertyName ) --- 3
  • SetProperty(field, value) --- 2
  • SomeProperty.Set( valuetype value) ---- 初始设置执行

代码片段:

public abstract class ViewModelBase : INotifyPropertyChanged
{        
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        Dev.Tools.Assert(propertyName != null, "propertyName can't be null.... ");
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // This is used to support change tracking.  But 
    //   the problem happens even when TrackChangedFields is false.
    // The EqualityComparer prevents this from being recursive.
    public virtual bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
    {
        if (!EqualityComparer<T>.Default.Equals(field, newValue))
        {
            field = newValue;
            OnPropertyChanged(propertyName);

            if (TrackChangedFields && !IgnoreFieldList.Contains(propertyName))
            {
                ChangedFieldList.Add(new ChangedRecordDetail(propertyName, field, newValue, ViewModelName));
            }
            return true;
        }
        return false;
    }

知道为什么PropertyChanged?.Invoke() 调用导致集合再次触发?

同样,这段代码运行良好。我只是不明白为什么会发生第二次对 setter 的调用,也不明白该怎么做才能只调用一次 setter。

I have a simple base class that implements INotifyPropertyChanged. The code works. But when I was stepping through a Set statement, when the Set statement called SetProperty(), I noticed that the PropertyChanged?.Invoke(...) call was calling the setter again.

So the setter code in the subclass looks something like:

private string someProperty ;
public string SomeProperty { get => someProperty ;
set {
    // Do some tests on value to make sure it's valid
    SetProperty(ref someProperty, value);
    // Now do some other stuff once that is set
}

When I step through it the call stack shows:

  • SomeProperty.Set( valuetype value); ????? Why again???? --- 5
  • External Code --- 4
  • OnPropertyChanged(string propertyName ) --- 3
  • SetProperty(field, value) --- 2
  • SomeProperty.Set( valuetype value) ---- Initial set execution

Code snippet:

public abstract class ViewModelBase : INotifyPropertyChanged
{        
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        Dev.Tools.Assert(propertyName != null, "propertyName can't be null.... ");
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // This is used to support change tracking.  But 
    //   the problem happens even when TrackChangedFields is false.
    // The EqualityComparer prevents this from being recursive.
    public virtual bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
    {
        if (!EqualityComparer<T>.Default.Equals(field, newValue))
        {
            field = newValue;
            OnPropertyChanged(propertyName);

            if (TrackChangedFields && !IgnoreFieldList.Contains(propertyName))
            {
                ChangedFieldList.Add(new ChangedRecordDetail(propertyName, field, newValue, ViewModelName));
            }
            return true;
        }
        return false;
    }

Any idea why the PropertyChanged?.Invoke() call is causing the set to fire again?

Again, this code works fine. I just don't understand why the 2nd call to the setter is happening nor what to do to only have the setter called once.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文