簡體   English   中英

為什么綁定更新而不實現 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM