Search code examples
wpfdata-bindingsetterupdatesourcetrigger

LostFocus Binding missing setter call


I have a problem with a two-way Binding on a TextBox.

<TextBox Text="{Binding Path=MyText, Mode="TwoWay", UpdateSourceTrigger=LostFocus}" />

On leaving the Focus of this element I would like to have a setter call of MyText, even if the Text property didn't change.

public string MyText {
    get { return _myText; }
    set {
        if (value == _myText) {
            RefreshOnValueNotChanged();
            return;
        }
        _myText = value;
        NotifyOfPropertyChange(() => MyText);
    }
}

The test function RefreshOnValueNotChanged() is never called. Does anyone know a trick? I need the UpdateSourceTrigger=LostFocus, because of the attached behaviour for Enter (and I need a completed user input...).

<TextBox Text="{Binding Path=MyText, Mode="TwoWay", UpdateSourceTrigger=LostFocus}" >
    <i:Interaction.Behaviors>
        <services2:TextBoxEnterBehaviour />
    </i:Interaction.Behaviors>
</TextBox>

with class:

public class TextBoxEnterBehaviour : Behavior<TextBox>
{
    #region Private Methods

    protected override void OnAttached()
    {
        if (AssociatedObject != null) {
            base.OnAttached();
            AssociatedObject.PreviewKeyUp += AssociatedObject_PKeyUp;
        }
    }

    protected override void OnDetaching()
    {
        if (AssociatedObject != null) {
            AssociatedObject.PreviewKeyUp -= AssociatedObject_PKeyUp;
            base.OnDetaching();
        }
    }

    private void AssociatedObject_PKeyUp(object sender, KeyEventArgs e)
    {
        if (!(sender is TextBox) || e.Key != Key.Return) return;
        e.Handled = true;
        ((TextBox) sender).MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }

    #endregion
}

Solution

  • I found a workaround on myself. But maybe someone has a better solution than this. Now I manipulate the value at GotFocus. Then the setter is called always on leaving the Controls Focus...

    <TextBox Text="{Binding Path=MyText, Mode="TwoWay", UpdateSourceTrigger=LostFocus}" GotFocus="OnGotFocus" >
        <i:Interaction.Behaviors>
            <services2:TextBoxEnterBehaviour />
        </i:Interaction.Behaviors>
    </TextBox>
    

    with:

    private void OnGotFocus(object sender, RoutedEventArgs e)
    {
        var tb = sender as TextBox;
        if(tb == null) return;
        var origText = tb.Text;
        tb.Text += " ";
        tb.Text = origText;
    }