为了账号安全,请及时绑定邮箱和手机立即绑定

冒泡 NotifyPropertyChanged

冒泡 NotifyPropertyChanged

C#
不负相思意 2021-11-07 19:20:58
根据这个答案,我不需要担心 NotifyPropertyChanges 冒泡层次结构,但我仍然无法使用这样的(简化的测试-)结构:数据保持类public class TestNotifyChanged : INotifyPropertyChanged{    public event PropertyChangedEventHandler PropertyChanged;    private string _Test = "default";    public string Test    {        get        {            return _Test;        }        set        {            if(_Test!=value)            {                _Test = value;                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Test"));            }        }    }}使用该测试类和测试属性的 ViewModel:public class ViewModel : INotifyPropertyChanged{    public event PropertyChangedEventHandler PropertyChanged;    private TestNotifyChanged tnc = new TestNotifyChanged(); // only to init, otherwise VS screams at me    public ViewModel(TestNotifyChanged tnc)    {        tnc = tnc; // getting an instance of TestNotifyChanged from "Master" passed in, which hopefully will be replaces by a singleton class.    }    private string _Test;    public string Test    {        get        {            return tnc.Test;  // this might be the crucial part!?        }        set        {            if (_Test != value) // never hits that, as I would expect, but you never know..            {                _Test = value;                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Test"));  // of course also never hit, as expected            }        }    }}最后是我的 MainWindow cspublic partial class MainWindow : Window{    TestNotifyChanged tnc;    public MainWindow()    {        InitializeComponent();        tnc = new TestNotifyChanged();        DataContext = new ViewModel(tnc); // pass in my Test-Object that has the Values.    }现在发生了什么:默认值“default”显示在 TextBlock 中。当我单击按钮时,消息框显示“新值”TextBlock未更新为“新值”我想要达到的目标:看起来很简单:TextBlock 应该更新为“新值”当我直接在 ViewModel 上设置测试值时,我可以轻松地完成这项工作- 但这似乎不正确,并且与我认为我可以构建我的应用程序/代码的方式相去甚远。未来的目标是拥有一个单例(我发现静态不起作用)“RecordStore”,它包含大部分数据(并从 API、本地数据库或仅从内存中获取它,如果其中任何一个完成)所以问题是:为什么 NotifyPropertyChange 没有冒泡到 View/ViewModel?或者还有其他我没有看到的问题?
查看完整描述

1 回答

?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

“冒泡”是路由事件的概念。像 PropertyChanged 这样的常规事件不会“冒泡”。


除了tnc = tnc;ViewModel 中的明显错误(应该是this.tnc = tnc;)之外,这两个类的 Test 属性是不相关的。为了更新自己的 Test 属性,ViewModel 必须在 处注册一个 PropertyChanged 事件处理程序tnc。并且它必须tnc在其自身的 Test 属性更改时更新该属性。


public class ViewModel : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;


    private TestNotifyChanged tnc;


    public ViewModel(TestNotifyChanged t)

    {

        tnc = t;

        tnc.PropertyChanged += (s, e) =>

        {

            if (e.PropertyName == nameof(Test) || string.IsNullOrEmpty(e.PropertyName))

            {

                Test = tnc.Test; // update ViewModel.Test from TestNotifyChanged.Test

            }

        };

    }


    private string test;

    public string Test

    {

        get

        {

            return test; // always return own value

        }

        set

        {

            if (test != value)

            {

                test = value;

                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Test)));


                tnc.Test = Test; // update TestNotifyChanged.Test from ViewModel.Test

            }

        }

    }

}

或者,删除 Test 属性的支持字段并仅操作tnc.Test:


public class ViewModel : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;


    private TestNotifyChanged tnc;


    public ViewModel(TestNotifyChanged t)

    {

        tnc = t;

        tnc.PropertyChanged += (s, e) =>

        {

            if (e.PropertyName == nameof(Test) || string.IsNullOrEmpty(e.PropertyName))

            {

                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Test)));

            }

        };

    }


    public string Test

    {

        get { return tnc.Test; }

        set { tnc.Test = Test; }

    }

}

幸运的是,这完全没有必要。


相反,可能只是一个公共Tnc财产,如


public class ViewModel

{

    public TestNotifyChanged Tnc { get; }


    public ViewModel(TestNotifyChanged tnc)

    {

        Tnc = tnc;

    }

}

使用这样的绑定:


<TextBlock Text="{Binding Tnc.Test}"/>


查看完整回答
反对 回复 2021-11-07
  • 1 回答
  • 0 关注
  • 377 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信