我有Car.xaml:
<CheckBox Name="carA" IsChecked="{Binding CarACheck, Mode=TwoWay, FallbackValue=true}" />
然后在Car.xaml.cs:
public Car()
{
//...
DataContext = this;
}
public bool CarACheck
{
get => carA.IsChecked;
set => carA.IsChecked = value;
}
當我運行它并單擊時CheckBox,應用程式崩潰并出現以下錯誤:
set => carA.IsChecked = value;
System.StackOverflowException
mscorlib.dll 中出現“System.StackOverflowException”型別的未處理例外
uj5u.com熱心網友回復:
錯誤原因
原因是您的二傳手被一遍又一遍地呼叫。
- 被
CheckBox點擊。 - 的
IsChecked屬性CheckBox已設定。 - 系結設定系結屬性的值
CarACheck。 - 的 setter
CarACheck設定 的IsChecked屬性CheckBox。 - 轉到 3。
從長遠來看,這會導致堆疊溢位并導致應用程式崩潰。
MVVM 解決方案
您似乎正在嘗試構建一個顯示汽車資料的視圖。我從您的示例中看到的是,您將資料和最可能的業務邏輯與用戶界面代碼混合在一起。你不應該這樣做,因為從長遠來看它會損害代碼質量和可維護性。一種更好且可持續的方法是將您的視圖與資料和業務邏輯分開。這就是MVVM 模式的意義所在。
在您的示例代碼中,我們有一個視圖,我們稱之為CarView. 這是CheckBox與用戶界面的其余部分一起定義以表示汽車的地方。資料通過一個名為 的單獨視圖模型型別暴露給視圖CarViewModel。此視圖模型包含從視圖系結的屬性。
使用簡單屬性時,無論是否有支持欄位,系結都無法從視圖模型端確定對屬性的更改。這就是您必須實作INotifyPropertyChanged介面的原因,該介面為此目的提供了一個事件。每當更改屬性時都會引發該事件。通常這是在 setter 中完成的。
public class CarViewModel : INotifyPropertyChanged
{
private bool _carACheck;
public bool CarACheck
{
get => _carACheck;
set
{
if (_carACheck == value)
return;
_carACheck = value;
OnPropertyChanged(nameof(_carACheck));
}
}
// ...other code, maybe even setting CarACheck.
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
在視圖中,只需將此視圖模型的實體分配給DataContextXAML 或代碼隱藏,例如:
public Car()
{
// ...other code.
DataContext = new CarViewModel();
}
在您看來,您不需要為 命名CheckBox,因為沒有明確參考它。該Mode=TwoWay宣告也可以洗掉,因為該IsChecked屬性默認系結雙向。
<CheckBox IsChecked="{Binding CarACheck, FallbackValue=true}"/>
關于你的原始代碼的備注:我希望你能看到 MVVM 模式的好處。當然,在查看此解決方案之后,您可以簡單地添加一個支持欄位并INotifyPropertyChanged到您當前的代碼中以使其作業,但這里要學習的教訓是,這種分離是有價值的并且值得投資,盡管它可能看起來更冗長。也可以看看:
- 資料系結概述 (WPF .NET)
- 如何:實施屬性更改通知
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/520477.html
