![](/img/trans.png)
[英]Update binding without implementation of INotifyPropertyChanged?
[英]Why does the binding update without implementing INotifyPropertyChanged?
我創建了一個 ViewModel 並將其屬性綁定到 UI 上的兩個文本框。 當我更改 first 的值並將焦點移出文本框但我沒有實現 INotifyPropertyChanged 時,另一個文本框的值會發生變化。 這是如何工作的?
以下是 XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Name}" />
</StackPanel>
</Window>
以下是我的 ViewModel
class ViewModel
{
public string Name { get; set; }
}
我測試過,你是對的。 現在我在網上搜索它,並找到了這個。
抱歉花了這么長時間才回復,實際上您遇到了WPF的另一個隱藏方面,那就是 WPF 的數據綁定引擎將數據綁定到 PropertyDescriptor 實例,如果源對象是一個普通的 CLR 對象並且沒有實現,則該實例包裝源屬性INotifyPropertyChanged接口。 並且數據綁定引擎將嘗試通過 PropertyDescriptor.AddValueChanged() 方法訂閱屬性更改事件。 並且當目標數據綁定元素改變屬性值時,數據綁定引擎會調用 PropertyDescriptor.SetValue() 方法將改變的值傳回源屬性,同時會引發 ValueChanged 事件通知其他訂閱者(在這種情況下,其他訂閱者將是 ListBox 中的 TextBlock。
如果您正在實現 INotifyPropertyChanged,則您完全有責任在需要數據綁定到 UI 的屬性的每個 setter 中實現更改通知。 否則,更改將不會如您預期的那樣同步。
希望這能讓事情變得更清楚一點。
所以基本上你可以做到這一點,只要它是一個普通的 CLR 對象。 非常整潔但完全出乎意料 - 過去幾年我做了一些 WPF 工作。 你永遠不會停止學習新事物,對吧?
正如 Hasan Khan 所建議的,這里有另一個鏈接, 指向關於這個主題的一篇非常有趣的文章。
請注意,這僅在使用 binding 時有效。 如果您從 code更新值,則不會通知更改。 [...]
WPF 在綁定時使用輕得多的 PropertyInfo 類。 如果您顯式實現 INotifyPropertyChanged,則 WPF 所需要做的就是調用 PropertyInfo.GetValue 方法以獲取最新值。 這比獲取所有描述符要少得多。 描述符最終的成本是屬性信息類內存的 4 倍。 [...]
實現 INotifyPropertyChanged 可能是一項相當乏味的開發工作。 但是,您需要根據 WPF 應用程序的運行時占用空間(內存和 CPU)權衡該工作。 自己實現 INPC 將節省運行時 CPU 和內存。
編輯:
更新這個,因為我仍然不時從這里得到評論和投票,所以它顯然仍然相關,即使我自己已經有一段時間沒有使用 WPF 了。 但是,如評論中所述,請注意這可能會導致內存泄漏。 據說它對反射的使用也很重要,這也被提到過。
我剛剛發現這也適用於 WinForms,有點:/
public class Test
{
public bool IsEnabled { get; set; }
}
var test = new Test();
var btn = new Button { Enabled = false, Text = "Button" };
var binding = new Binding("Enabled", test, "IsEnabled");
btn.DataBindings.Add(binding);
var frm = new Form();
frm.Controls.Add(btn);
test.IsEnabled = true;
Application.Run(frm);
奇怪的是,這並沒有禁用按鈕:
btn.Enabled = false;
這樣做:
test.IsEnabled = false;
我可以解釋為什么在焦點更改時更新屬性:所有Binding
都有一個UpdateSourceTrigger
屬性,它指示何時更新源屬性。 此默認值在每個DependencyProperty
上定義,並且TextBox.Text
屬性設置為LostFocus
,這意味着該屬性將在控件失去焦點時更新。
我相信 UrbanEsc 的回答解釋了為什么值會更新
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.