OneWayToSource
Binding seems broken in .NET 4.0
I have this simple piece of Xaml
<StackPanel>
<TextBox Text="{Binding TextProperty, Mode=OneWayToSource}"/>
<Button/>
</StackPanel>
And my code behind looks like this
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private string m_textProperty;
public string TextProperty
{
get
{
return "Should not be used in OneWayToSource Binding";
}
set
{
m_textProperty = value;
}
}
In .NET 3.5 this works as you might except. Put some text in the TextBox
, press Tab to make it lose Focus, and the TextProperty
updates with whatever text that was entered in the TextBox
In .NET 4.0, if I type some text in the TextBox
and then press Tab to make it lose Focus, the TextBox
reverts to the value for TextProperty
(meaning "Should not be used in OneWayToSource Binding"). Is this re-reading intended for a OneWayToSource
Binding in .NET 4.0? I just want the TextBox
to push its value into the TextProperty
and not the other way around.
Update
Adding a Bounty to this question as this has become a mayor inconvenience in my project and I would like to know the reason that this has changed. It seems that get
is called after the Binding has updated the source. Is this the desired behavior for a OneWayToSource
Binding in .NET 4.0?
If Yes
Or is this in fact a bug that we can hope to get fixed in a future release?
Karl Shifflett's blog and @Simpzon's answer already cover why they added this feature and why it is not a problem for properties that always get what was set. In your own code you always use an intermediate property that has the proper semantics for binding and use an internal property that has the semantics you want. I would call the intermediate property a "blocking" property because it blocks the getter from reaching your internal property.
But in the case where you don't have access to the source code for the entity that you are setting the property on and you want the old behavior, you can use a converter.
Here is a blocking converter with state:
public class BlockingConverter : IValueConverter
{
public object lastValue;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return lastValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
lastValue = value;
return value;
}
}
and you can use it for your example like this:
<Grid>
<Grid.Resources>
<local:BlockingConverter x:Key="blockingConverter" x:Shared="False"/>
</Grid.Resources>
<StackPanel>
<TextBox Text="{Binding TextProperty, Mode=OneWayToSource, Converter={StaticResource blockingConverter}}"/>
<Button Content="Click"/>
</StackPanel>
</Grid>
Note that because the converter has a state you need a separate instance each time the resource is used and for this we can use the x:Shared="False"
attribute on the resource.
This is indeed by design. Usually it should not make trouble, but your property implementation is at least unconventional, I would say. Getters and setters (accessors) should really do not much more than get and set, and each get should be consistent with the last corresponding set. (sorry, no source for this, it's just what we have called good citizenship in all development teams I've been in).
More details about the feature here: http://karlshifflett.wordpress.com/2009/05/27/wpf-4-0-data-binding-change-great-feature/
Bug, definitely.
if it's a "feature", it's a very bad one...
it seems they have added a call to the get() function after the set() is done, even in the OneWayToSource mode... can anybody explain why ?
also, thanks for pointing this out, it explains an issue I have had since I upgraded my project to .net 4.0 and that I could not explain until now...
just a side note: I have solved this by using dependency properties in the end.
This is quite clearly a bug. It seems to have been reported at least once by someone. https://connect.microsoft.com/VisualStudio/feedback/details/612444/onewaytosource-broken-in-net-4-0
I agree with many of the others that one way should be one way period.
My scenario is complicated and having functionality changed between framework versions has caused me a real headache.
I have a textbox bound to a property. I have a converter which changes the format on the fly. EG: I enter EU5 in the textbox, the property gets EU005. I have got the binding set to trigger on property changed as I need to do lookups within the ViewModel as the user types. The new implementation changes the value of the textbox as I type. So if I wish to type EU512 I couldn't easily as the textbox text would keep changing.
I have tried many thing - Explicit binding (where you decide when to update and which way.) This has the same problem. If I say, UpdateSource, it does, but also then rereads the property and changes the target too.
I tried OneWayToSource and had the same problem. I have found no way to work around this without making annoying changes to my VM. The only other way would be to remove binding on this field and start firing events which would be awful.
If MS made the binding behave as it is logically named then my problem would disappear. Even a property on the binding to opt out of the .net4 implementation and behave as 3.5 would work for me.
Anyone have any suggestions for me on how I can get around this?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With