Why does the binding update without implementing I

2019-01-02 20:54发布

I created a ViewModel and bound its property to two textboxes on UI. The value of the other textbox changes when I change the value of first and focus out of the textbox but I'm not implementing INotifyPropertyChanged. How is this working?

Following is 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>

And following is my ViewModel

class ViewModel
{
    public string Name { get; set; }
}

3条回答
听够珍惜
2楼-- · 2019-01-02 21:09

I tested it, you are right. Now i searched for it on the web, and found this.

Sorry to take so long to reply, actually you are encountering a another hidden aspect of WPF, that's it WPF's data binding engine will data bind to PropertyDescriptor instance which wraps the source property if the source object is a plain CLR object and doesn't implement INotifyPropertyChanged interface. And the data binding engine will try to subscribe to the property changed event through PropertyDescriptor.AddValueChanged() method. And when the target data bound element change the property values, data binding engine will call PropertyDescriptor.SetValue() method to transfer the changed value back to the source property, and it will simultaneously raise ValueChanged event to notify other subscribers (in this instance, the other subscribers will be the TextBlocks within the ListBox.

And if you are implementing INotifyPropertyChanged, you are fully responsible to implement the change notification in every setter of the properties which needs to be data bound to the UI. Otherwise, the change will be not synchronized as you'd expect.

Hope this clears things up a little bit.

So basically you can do this, as long as its a plain CLR object. Pretty neat but totally unexpected - and i have done a bit of WPF work the past years. You never stop learning new things, right?

As suggested by Hasan Khan, here is another link to a pretty interesting article on this subject.

Note this only works when using binding. If you update the values from code, the change won't be notified. [...]

WPF uses the much lighter weight PropertyInfo class when binding. If you explicitly implement INotifyPropertyChanged, all WPF needs to do is call the PropertyInfo.GetValue method to get the latest value. That's quite a bit less work than getting all the descriptors. Descriptors end up costing in the order of 4x the memory of the property info classes. [...]

Implementing INotifyPropertyChanged can be a fair bit of tedious development work. However, you'll need to weigh that work against the runtime footprint (memory and CPU) of your WPF application. Implementing INPC yourself will save runtime CPU and memory.

查看更多
回忆,回不去的记忆
3楼-- · 2019-01-02 21:13

I just found out that this also works in WinForms, kinda :/

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);

Strangely though, this doesn't disable the button:

btn.Enabled = false;

This does:

test.IsEnabled = false;
查看更多
姐姐魅力值爆表
4楼-- · 2019-01-02 21:23

I can explain why the property is updated when focus changes: all Bindings have an UpdateSourceTrigger property which indicates when the source property will be updated. The default value for this is defined on each DependencyProperty and for the TextBox.Text property is set to LostFocus, meaning that the property will be updated when the control loses focus.

I believe UrbanEsc's answer explains why the value is updated at all

查看更多
登录 后发表回答