INotifyPropertyChanged event fires, but UI not updated if business class changes property value after UI update
Microsoft,
This same issue was brought up in the following blog entry : http://www.lhotka.net/weblog/DataBindingIssueInWPFWithSolution.aspx
Sam Bent and Kevin Moore from the WPF team were given credit for a workaround.
The issue is very simple. I'm just wondering if a hot fix will be release by Microsoft so that we don't have to write our code like the workaround suggests.
Issue : A textbox is bound to a CLR class. That class implements INotifyPropertyChanged.
If the CLR class changes the value in the property setter and then the PropertyChanged event is fired, the source textbox is not re-updated. Any other controls bound to that textbox are updated, but not the textbox. In my example below, the first textbox is bound to the same property to show that after the second textbox is updated, the first textbox will show the entered input in UPPER CASE, but the source textbox will show the text as entered.
This would occur when the CLR class was simply applying a business rule and altered the value sent from the textbox to the CLR class.
The workaround involves using an IValueConverter that does nothing except return the value pass into it.
Code Snippet<
StackPanel x:Name="spMain"><
StackPanel.Resources><
TestDataBindingTextBoxIssue:DummyConverter x:Key="dummyConverter" /></< FONT></StackPanel.Resources>
<
TextBox Text="{Binding Path=LastName}" /><
TextBox x:Name="txtLastName" Text="{Binding Path=LastName, Converter={StaticResource dummyConverter}}" /></< FONT>
</StackPanel>
Code SnippetPublic Property LastName() As String
Get Return _strLastName End Get Set(ByVal Value As String)'this next line, simulates a CLR object performing a business rule on entered data.
_strLastName = Value.ToUpper
NotifyPropertyChanged("LastName")
End Set
End PropertyI really do not want to have to place a converter on every textbox that has business rules attached to it.
I was thinking of just putting the validation code in the textbox itself and this problem goes away, but then I have rules in the UI and CLR object.
Are there any plans to address this? Can it be addresses without the above workaround? I spent two hours reading and comparing call stacks, but all the code that does the work in burried in the PresentationFramework.dll and I couldn't find a workaround even if I extended the textbox class.
We are starting a MONSTER application next week and I just learned about this today so any direction or best practice guidance for handling CLR object business rules and the updating of inputted data would really be appreciated.
Thank you for any help and have a great day.
Karl
Todas las respuestas
- I'm having a similar issue where my data bound fields are changing as expected, but the PropertyChanged event is not always being raised to my calling code. Sometimes it does, sometimes it doesn't.
I'm afraid we cannot change this behavior - it would be a breaking change (meaning it could break existing apps). We are tracking this issue, so that it gets addressed in a future "major" release where breaking changes are allowed. For now, the only option I'm aware of is the one Rocky mentions that uses a dummy converter.
When the dummy converter is present, WPF will re-read the property's value after calling the setter, and propagate the new value back to the UI, calling the converter on the way. This roughly doubles the cost of an update, so it's not something we'd want to do uniformly to all two-way bindings. It's something the app author should "opt-in", so that we only spend the cycles if the author asks us to. Today, the only way to opt-in is to add the dummy converter.
Tim's problem with the PropertyChanged event sounds like a different issue altogether. I'd need more information before I can say anything useful. Can you describe situations where the event is not being raised? Usually it's not WPF that raises this event, but rather the source object itself. So your problem may be arising from a faulty source object. Or one that optimizes by comparing the new value to the old value before deciding to raise the event at all.
Sam, thanks for your response.
I have an extensive architecture of entity objects (.NET 2.0) that implement INotifyPropertyChanged. My objects that contain sub-objects "bubble" the propertychanged event up to original calling object like so:
Code Snippetprivate PersonName _name;
public PersonName Name{
get { return _name; } set{
_name =
value;OnPropertyChanged(
"Name");}
public Person()
{
this.Name.PropertyChanged += delegate(object s, PropertyChangedEventArgs e)
{
OnPropertyChanged("Name." + e.PropertyName);
};
}
I have unit tests that explicity test this functionality and it works as expected. In my WinForm 2.0 code, I use Control.DataBindings.Add("Text", _object, "Property.SubProperty",true). I also listen to the PropertyChanged event in my forms because it triggers my validation code. This also works as expected.
I've recently began the port of our UI code to WPF. I use simple databinding in xaml - <TextBox Text="{Binding Path=Name.FullName, UpdateSourceTrigger=PropertyChanged}" />
In my code, I set this.DataContext to my entity object.
When I listen to the PropertyChanged event of the entity object that drives this.DataContext, it doesn't always get fired as expected.
For example I have a control that has it's datacontext set to a Client object. When the control that is bound to Client.Name.FullName has it's text changed, I expect a PropertyChanged event to be raised, but it is never fired. However, changing the text in the Client.Comment textbox, raises the event properly. To eleminate the sub objects as a suspect, Client.ClientProgramSet.DefaultProgram.ProgramName raises the PropertyChanged event as expected.
I've yet to test porting my enitity object to .NET 3.0, but I just don't see how that could be a problem. I added many more specific units tests in hope of finding the issue, and I've implemented INotifyPropertyChanged properly. It seems to be specific to how WPF handles object databinding.
Any thoughts?
Tim, this is a different issue from the original post. You might consider starting a new thread, and adding a pointer to it in this thread. I'd do it myself, but it's better if you do it so that you are the owner of the new thread.
Your code snippet has two problems. First, you listen for the PropertyChanged event from the initial PersonName (the initial value of the Name property), but if someone changes the Name you don't listen for PropertyChanged from the new PersonName. The setter for the Name property should add a listener from the new PersonName, and presumably also remove the listener from the old PersonName.
Second, raising PropertyChanged with a compound property name like "Name.FullName" is meaningless in WPF. When you declare a binding with path = Name.FullName, WPF will listen for PropertyChanged with name=Name on the top-level object, and will also listen for PropertyChanged with name=FullName on the second-level object. But an event with name=Name.FullName will be ignored because "Name.FullName" doesn't match "Name".
The first problem is the one that's blocking you, I suspect.
Hi,
I have used Notifypropertychanged and in that i m firing propertychanged event, the contol comes to this line but the subscribed event is not executed, This scenario is seen for the checkboxes which are binded, but the same works well for the radio buttons which are not binded. Is this a bug with binding, ie. The NotifyPropertychange, does not comes into action when we use Binding. Please suggest something. This seems to be a major bug.
Is there any Fix up for this, Has anyone comes across it, if so please do tell me, its an urgent need.
regards
Dikshit- hi
i have impl. this converter still my propertychanged evnet doesn't filre at all.
i also posted the thread in forum. - hurrrrrrrrrrrrray
the problem is solved.
actually i was tried to change the content on UpdateSourceTrigger=PropertyChanged, but the it work on UpdateSourceTrigger=LostFocus (the default) . ..
can sm1 suggest me for UpdateSourceTrigger=PropertyChanged :( - I am seeing this problem on a LostFocus event. I have a textbox control. The Text property has a multivalue converter on it. The converter will change the 'Name' field that the textbox.content displays. The property changed event fires, other controls that display this name value receive the event and display the new value. The textbox control clearly ignores the event.
This is a huge issue for us. How can I handle this? I can't put two converters on the text box control -- such as the multivalue converter and then an identity converter.
In researching this, I do know that the lost focus event fires before the converter executes...Iteresting that the lost focus will fire -- and yet the cursor is still sitting in the text box. Would that be why the control is still ignoring the notification.
This seems pretty easy to replicate. Just attach a multivalue converter -- and in the debugger change the value in the converter that is to be displayed by the textbox control.
I am bummed...I love WPF/XAML. This is a real showstopper!
Any help that you could give me would be greatly appeciated!

