1
votes

I have two text boxes on a WPF form. The second TextBox gets its text from the first TextBox using ElementName binding, and it also updates the first text box via TwoWay binding mode:

<StackPanel Orientation="Vertical">
    <TextBox Name="TextBox1"/>
    <TextBox Text="{Binding ElementName=TextBox1, Path=Text, Mode=TwoWay}"/>
</StackPanel>

When I edit the second text box, the first text box updates only when the second text box loses focus, not instantly as I type. (This is as expected, UpdateSourceTrigger=PropertyChanged can be added to the binding to get instant update.)

However when I edit the first text box, the second text box updates instantly as I type. This was not what I expected. Why is this?

2

2 Answers

1
votes

DependencyProperty Text of any TextBox updates when a new symbol is typed (can be tested by attaching a handler to TextChanged event)

But there is a connector between two DPs: a Binding (image from MSDN article)

Binding

Binding intercept changes of Target DP and update Source Property according to UpdateSourceTrigger parameter. Changes from Source are visible immediately.

Bindings that are TwoWay or OneWayToSource listen for changes in the target property and propagate them back to the source. This is known as updating the source. Usually, these updates happen whenever the target property changes. This is fine for check boxes and other simple controls, but it is usually not appropriate for text fields. Updating after every keystroke can diminish performance and it denies the user the usual opportunity to backspace and fix typing errors before committing to the new value. Therefore, the default UpdateSourceTrigger value of the Text property is LostFocus and not PropertyChanged.

to have a simmetric behavior, use binding for both TextBoxes

<StackPanel Orientation="Vertical">
    <TextBox Name="TextBox1" Text="{Binding Path=Text, ElementName=Txt, Mode=TwoWay}"/>
    <TextBlock Name="Txt" Visibility="Collapsed"/>
    <TextBox Name="TextBox2" Text="{Binding Path=Text, ElementName=Txt, Mode=TwoWay}"/>
</StackPanel>
1
votes

Well, this is expected behavior.

Imagine, you bind a Label or (TextBlock) to a property of data class, e.g. Person.Name:

<Label Content="{Binding Person.Name}" />

You expect the label to be updated, whenever Person.Name changes.

In this case, the Person is your binding source and Label binding target.

Now back to your case. You have two textboxes, where second is databound to first. The first is binding source and the second is binding target. Whenever source changes, target is updated, just like if it was databound to Person.Name. UpdateSourceTrigger argument affects only when the source should be updated, as the argument name suggests.

WORKAROUND: Databind both TextBoxes to 3rd object (usually it is ViewModel).

<StackPanel Orientation="Vertical">
    <TextBox Text="{Binding SomeProperty}"/>
    <TextBox Text="{Binding SomeProperty}"/>
</StackPanel>