Search code examples
c#data-bindingbindingwindows-phonelostfocus

LostFocus before ApplicationBar Command


I'm binding a TextBox to a property of my ViewModel. When the user clicks on an ApplicationBar Button, a command is being called (I'm using BindableApplicationBar, which can be found on NuGet). Problem is that when the user types in the TextBox and clicks right away the Application Button, the setter of the TextBox is not being called, which means that the ButtonCommand is using the old text.

I've seen a lot of solutions, but I can't use them in my situation. The only "solution" would be to get rid of the ApplicationBar and use instead a button, which is behind the Keyboard (which pops up when the user clicks on the TextBox. I'm using Windows Phone, so that's why there's a KeyBoard...). So the user has to click somewhere else to use the button -> lostfocus.

Some solutions:

WPF Databind Before Saving

Binding with UpdateSourceTrigger==LostFocus do not fire for Menu or Toolbar interaction

I cant use UpdateSourceTrigger=PropertyChanged and I'm using MVVM, so I also don't really want to use CodeBehind. If there's no other way to do it without CodeBehind, then it's ok.


Solution

  • One solution I've used in the past is to update the binding whenever the contents of the text box changes, rather than when focus is lost.

    A simple, reusable way to do this is with a behaviour.

    Something like this:

    public class RebindOnTextChanged : Behavior<TextBox>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.TextChanged += this.TextChanged;
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.TextChanged -= this.TextChanged;
        }
    
        private void TextChanged(object sender, TextChangedEventArgs e)
        {
            var bindingExpression = this.AssociatedObject.GetBindingExpression(TextBox.TextProperty);
            if (bindingExpression != null)
            {
                bindingExpression.UpdateSource();
            }
        } 
    }      
    

    and used like:

    <TextBox Text="{Binding SomeProperty}">
        <i:Interaction.Behaviors>
            <behaviours:RebindOnTextChanged />
        </i:Interaction.Behaviors>
    </TextBox>