我在论坛上搜索了一个解决方案,但没有一个列出的解决方案有所帮助。我假设我的实施已经关闭,但我不明白为什么或为什么。
使用Xamarin表单我试图在对象的数据发生更改时获取标签。
相关守则:
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;}
}
基本上,"之前"打印到控制台,但是" Fired"不打印。这意味着PropertyChanged为null,因此PropertyChanged没有被触发。
我错过了什么?
答案 0 :(得分:2)
我不知道这是否会影响它(可能不会),但我会将属性更改的方法重写为以下内容。
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上的this answer。
对局部变量的赋值可确保如果事件在if和实际调用之间取消注册,则调用列表将不为null(因为该变量将具有原始调用列表的副本)。
这在多线程代码中很容易发生,在检查null和触发事件之间,它可能会被另一个线程取消注册。
接下来,我会将属性从String
重命名为其他内容。我相信Xamarin的.NET框架实现包括BCL类型的String。你可能会混淆绑定引擎,虽然它应该足够聪明以识别差异。
另外,请确保Binding
成员的方向设置为Two-Way
,并且将更新更改通知设置为PropertyChanged
。这将确保在更改属性值时始终触发OnPropertyChanged
方法。
new Binding("String")
{
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
}