![](/img/trans.png)
[英]WPF two way mode binding using INotifyPropertyChanged not working
[英]WPF INotifyPropertyChanged two way binding strange action
我按照許多線程的建議實現了INotifyPropertyChanged
。
實施1
public class Notifier : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string pName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pName));
}
}
public class Model : Notifier, IDataErrorInfo
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("name_changed"); }
}
}
視圖模型由模型和用於更改模型屬性的命令組成。
public class ViewModel : Notifier
{
private Model _model;
public Model Model
{
get { return _model; }
set { _model = value; OnPropertyChanged("model_changed"); }
}
private ICommand _cmd;
public ICommand Command
{
get { return _cmd; }
set { _cmd = value; }
}
public void ExecuteCommand(object para)
{
Console.WriteLine("Command executed");
Model.Name = "new name";
}
}
然后將VM綁定到視圖。
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Width="100">
<TextBox.Text>
<Binding Path="Model.Name" Mode="TwoWay" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<ExceptionValidationRule></ExceptionValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
執行該命令時, TextBox
不會更新為新值。
但是,如果我像該指令那樣實現INotifyPropertyChanged
,則綁定有效。
實施2
public class Notifier : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName]string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
}
public class Model : Notifier, IDataErrorInfo
{
private string name;
public string Name
{
get { return name; }
set { SetProperty(ref name, value); }
}
}
第一種方法遺漏了什么?
實現1的主要問題是OnPropertyChanged
方法的字符串參數必須是要更改的確切屬性名稱。 對於您的兩個示例,應該將"model_changed"
更改為"Model"
並且"name_changed"
應該讀為"Name"
。 這是兩種通過鍵入文字字符串名稱來減輕潛在人為錯誤的出色技術:
1.使用CallerMemberName
屬性
如果允許並有權訪問System.Runtime.CompilerServices
命名空間,則可以這樣編寫基類,以使屬性名稱作為OnPropertyChanged
方法的字符串參數自動傳遞:
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class Notifier : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string pName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pName));
}
}
然后,您只需在屬性的getter中調用OnPropertyChanged()
。
2.使用nameof
關鍵字
另外,您可以簡單地將文本類型化的屬性名稱替換為nameof(<InsertPropertyNameHere>)
,這將返回名稱而不會造成任何nameof(<InsertPropertyNameHere>)
風險,例如以下示例:
public class Model : Notifier, IDataErrorInfo
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged(nameof(Name)); }
}
}
請添加這樣的屬性名稱。
public class Model : Notifier, IDataErrorInfo
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.