INotifyPropertyChanged未触发属性更改事件

4

我已经在论坛上搜索了解决方案,但列出的解决方案都没有帮助。我认为我的实现有问题,但我不明白是什么或为什么。

使用Xamarin Forms,我正在尝试在对象数据更改时更新标签。

相关代码:

public new event PropertyChangedEventHandler PropertyChanged;

protected new virtual void OnPropertyChanged(string propertyName)
{
    System.Diagnostics.Debug.WriteLine ("Before");
    if (PropertyChanged != null)
    {
        System.Diagnostics.Debug.WriteLine ("Fired");
        PropertyChanged(this,
            new PropertyChangedEventArgs(propertyName));
    }
}

public string String {
    set { 
        if (_data == value)
            return;
        _data = value;
    OnPropertyChanged ( "String" ); }

    get { return _data; }
}

public new View Content {
        get { 
            label = new Label { Text = String };
            label.SetBinding( Label.TextProperty, new Binding( "String" ) );
            return label;}
    }

基本上,“Before”被打印到控制台,但“Fired”没有被打印。这意味着 PropertyChanged 是空的,因此 PropertyChanged 没有被触发。
我错过了什么?

String是一个关键字,可能会引起一些问题,你能把它改成"Data"吗?另外,你是否在页面上设置了绑定上下文? - JamesMontemagno
你正在创建一个绑定,但没有设置BindingContext(至少在你发布的代码示例中没有)。 - Jason
设置绑定在Content属性中是否与设置绑定上下文相同? - Carson
@Carson 我也遇到了同样的问题,你是如何解决的? - TheHunter Shergill
1个回答

3

我不知道这是否会对它产生影响(可能不会),但我建议将您的属性更改方法重写为以下内容。

protected new virtual void OnPropertyChanged(string propertyName)
{
    System.Diagnostics.Debug.WriteLine ("Before");
    var handler = this.PropertyChanged;
    if (handler == null)
    {
        return;
    }

    System.Diagnostics.Debug.WriteLine ("Fired");
    handler(this,
        new PropertyChangedEventArgs(propertyName));
}

获取事件的本地引用可在多线程环境中保护您。即使您不编写多线程代码,这也是最佳实践。处理事件时采用这种更安全的方法。
关于此问题,请参见Stackoverflow上的此答案
引用本地变量确保了如果事件在if和实际调用之间取消注册,调用列表将不会为null(因为该变量将具有原始调用列表的副本)。在多线程代码中,这很容易发生,在检查null并触发事件之间,它可能会被另一个线程取消注册。
接下来,我建议将属性从String重命名为其他名称。我相信Xamarin的.NET框架实现包括BCL类型String。您可能会让绑定引擎感到困惑,尽管它应该足够智能以识别差异。
还要确保Binding成员的方向设置为Two-Way,并且更新更改通知设置为PropertyChanged。这将确保在更改属性值时始终触发OnPropertyChanged方法。
new Binding("String")
{
    Mode = BindingMode.TwoWay,
    UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
}

感谢您的评论。我已经转换到了那些最佳实践。遗憾的是,就功能而言,它并没有帮助。PropertyChange仍然没有触发。 - Carson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接