I have a OneWayToSource binding that is not behaving as I expected when I set the DataContext of the target control. The property of the source is being set to default instead of the value of the target control's property.
I've created a very simple program in a standard WPF window that illustrates my problem:
XAML
<StackPanel>
<TextBox x:Name="tb"
Text="{Binding Path=Text,Mode=OneWayToSource,UpdateSourceTrigger=PropertyChanged}"
TextChanged="TextBox_TextChanged"/>
<Button Content="Set DataContext" Click="Button1_Click"/>
</StackPanel>
MainWindow.cs
public partial class MainWindow : Window
{
private ViewModel _vm = new ViewModel();
private void Button1_Click(object sender, RoutedEventArgs e)
{
Debug.Print("'Set DataContext' button clicked");
tb.DataContext = _vm;
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
Debug.Print("TextBox changed to " + tb.Text);
}
}
ViewModel.cs
public class ViewModel
{
private string _Text;
public string Text
{
get { return _Text; }
set
{
Debug.Print(
"ViewModel.Text (old value=" + (_Text ?? "<null>") +
", new value=" + (value ?? "<null>") + ")");
_Text = value;
}
}
}
The TextBox tb
starts out with a null DataContext and therefore the binding is not expected to do anything. So if I type something in the text box, say "X", the ViewModel.Text property remains null.
If I then click the Set DataContext button I would have expected the ViewModel.Text
property to be set to the "X" of the TextBox.Text
property. Instead it is set to "". Certainly the binding is working because if I then type "Y" in the text box, after the "X", it sets the ViewModel.Text
property to "XY".
Here is an example of the output (the last two lines are counter-intuitive because of the order of evaluation, but they definitely both occur immediately after typing the "Y"):
TextBox changed to X
'Set DataContext' button clicked
ViewModel.Text (old value=<null>, new value=)
ViewModel.Text (old value=, new value=XY)
TextBox changed to XY
Why is the ViewModel.Text
property being set to "" instead of "X" when the DataContext is set?
What am I doing wrong? Am I missing something? Have I misunderstood something about binding?
Edit: I would have expected the output to be:
TextBox changed to X
'Set DataContext' button clicked
ViewModel.Text (old value=<null>, new value=X)
ViewModel.Text (old value=X, new value=XY)
TextBox changed to XY
Its a bug or perhabs not. Microsoft claims its by design. You first type x and then you kill DataContext by clicking on Button hence why the TextBox holds x and your viewModel.Text property gets newly initialized (its empty). When on datacontext changed getter will still be called. In the end you have no chance to fix this.
You can however use two way and let it be.
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