2

When using databinding in WPF, if you set Mode property to TwoWay, you can control the moment when the source property will be updated by setting UpdateSourceTrigger property. That scenario is possible for target -> source update stream. But how you can control same thing for source -> target update stream? I cannot find equivalent property.

For example, lets say I have two textboxes on my window, and I want to bind Text properties of both textboxes. XAML may look like this:

        <TextBox
            Name="txt1"
            Text="{Binding ElementName=txt2, Path=Text, Mode=TwoWay,
            UpdateSourceTrigger=LostFocus}"
            />
        <TextBox
            Name="txt2"
            />

When user enters text in txt1 TextBox, Text property of txt2 Textbox will be updated as Text property changes, just if I had implemented TextChanged event on txt1.

However, when user enters text in txt2 TextBox, Text property of txt1 Textbox will be updated after txt2 TextBox looses focus because UpdateSourceTrigger property is set to LostFocus, just if I had implemented LostFocus event.

Is there possibility in WPF databinding to update target property after source property control looses focus? In our example: what should be done to XAML code above, so Text property of txt2 TextBox would be updated only after txt1 TextBox loose focus, and not after its Text property changes?

Thanks!

Bogdan
  • 33
  • 1
  • 5

2 Answers2

1

Why not define two bindings? This works for me:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox Name="txt1" Margin="4" 
                 Text="{Binding ElementName=txt2, Path=Text, Mode=OneWay}" />
        <TextBox Name="txt2" Margin="4" 
                 Text="{Binding ElementName=txt1, Path=Text, Mode=OneWay}" />
    </StackPanel>
</Window>
Rico Suter
  • 11,548
  • 6
  • 67
  • 93
1

The UpdateSourceTrigger mechanism is linked to the implicit nature of a WPF control. In this way you can decide when update the source. On the other side the source can be a UIElement, but it can be another object too. Indeed an object which is the source of a binding, can notify its changes to the binding, by implementing INotifyPropertyChanged. With this interface the object notities its changes everytime a property changes.

So if you want a kind of "UpdateTargetTrigger" you should implement it in a control. For example you can extend the TextBox control in this way:

public class ExtTextBox : TextBox, INotifyPropertyChanged
{
    private event PropertyChangedEventHandler propertyChanged;
    private string textOnLostFocus;

    public event PropertyChangedEventHandler PropertyChanged
    {
        add
        {
            propertyChanged += value;
        }
        remove
        {
            propertyChanged -= value;
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);
        SetTextOnLostFocus(Text, false);
    }

    private void SetTextOnLostFocus(string text, bool updateText)
    {
        if (StringComparer.Ordinal.Compare(textOnLostFocus, text) != 0)
        {
            textOnLostFocus = text;
            if (updateText)
            {
                Text = text;
            }

            OnPropertyChanged("TextOnLostFocus");
        }
    }

    public string TextOnLostFocus
    {
        get
        {
            return textOnLostFocus;
        }
        set
        {
            SetTextOnLostFocus(Text, true);
        }
    }
}

I am using the TextOnLostFocus as a support to notify its changes just on LostFocus event. Therefore your XAML will be:

<TextBox Name="txt1" Text="{Binding ElementName=txt2, Path=TextOnLostFocus, Mode=TwoWay,
                                    UpdateSourceTrigger=LostFocus}" Margin="3" />
<local:ExtTextBox x:Name="txt2" Margin="3" />

I hope it can help you.

Il Vic
  • 5,576
  • 4
  • 26
  • 37