首先,可以簡化RaisePropertyChanged
這樣:
public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
所以你不需要寫RaisePropertyChanged("Description")
,但只有:RaisePropertyChanged()
和propertyName
被自動注入。如果你經常重構的真棒:你不必處理的整體解決方案:)
其次記住所有的「標題」和「描述」字符串的噩夢,如果BaseClass
有PropertyChangedEvent
,你可以在MyClassViewModel
聽它。
myClassBase.PropertyChanged += (s, e) => { RaisePropertyChanged(e.PropertyName); };
但是,如果你沒有在MyClassViewModel
構造立即注入myClassBase
,或者如果可以myClassBase
改變某個時候,事情變得有點複雜。
你必須要MyClassViewModel
也實現INotifyPropertyChanging
:
public event PropertyChangingEventHandler PropertyChanging;
public void RaisePropertyChanging([CallerMemberName] string propertyName = null)
{
PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
}
你也必須提高爲myClassBase
通知:
public BaseClass myClassBase
{
get { return _myClassBase; }
set
{
RaisePropertyChanging();
_myClassBase = value;
RaisePropertyChanged();
}
}
private BaseClass _myClassBase;
然後,所有你需要的是這樣的代碼:
public MyClassViewModel()
{
PropertyChanging += OnPropertyChanging;
PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanging(object sender, PropertyChangingEventArgs e)
{
if (e.PropertyName != nameof(MyClassViewModel.myClassBase))
return; //or do something with the other properties
if (myClassBase == null)
return;
myClassBase.PropertyChanged -= OnMyBaseClassPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != nameof(MyClassViewModel.myClassBase))
return; //or do something with the other properties
if (myClassBase == null)
return;
myClassBase.PropertyChanged += OnMyBaseClassPropertyChanged;
}
private void OnMyBaseClassPropertyChanged(object sender, PropertyChangedEventArgs e)
{
RaisePropertyChanged(e.PropertyName);
}
注意:我使用C#-6.0 nameof()
運營商,我希望你能使用它,它簡直太棒了!
編輯:
這裏有一個演示功能正常,一個簡單的測試方法:
[TestMethod]
public void ChildClassPropertyChanged()
{
var bc = new BaseClass();
var c = new MyClassViewModel();
bc.Title = "t1";
c.myClassBase = bc;
Assert.AreEqual("t1", c.Title);
c.Title = "t2";
Assert.AreEqual("t2", c.Title);
c.myClassBase.Title = "t3";
Assert.AreEqual("t3", c.Title);
c.myClassBase = new BaseClass();
bc.Title = "t4";
Assert.AreEqual(null, c.Title);
c.myClassBase.Title = "t5";
Assert.AreEqual("t5", c.Title);
}
請記住,如果你設置一個null
myClassBase
,你的屬性getter和setter內該代碼將拋出一個NullReferenceException
。也許你應該這樣修改它:
public string Title
{
get
{
return myClassBase?.Title;
}
set
{
if (myClassBase != null)
myClassBase.Title = value;
RaisePropertyChanged();
}
}