Andrew Nix
Andrew Nix

Reputation: 116

Bind Return key press to text box only while focused

I want to add a key binding to a TextBox so that when I press the ENTER key, the appropriate command will fire, but I only want this to happen when the TextBox has focus on it.

The following code adds the binding, but it will fire whenever the Return key is pressed, no matter where the focus is in the window. Is it possible to restrict the key binding to only when the TextBox has focus?

<TextBox Text="{Binding SearchBoxNumber, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.InputBindings>
        <KeyBinding Key="Return" Command="{Binding SearchCommand}" />
    </TextBox.InputBindings>
</TextBox>

Upvotes: 0

Views: 72

Answers (2)

Roger Leblanc
Roger Leblanc

Reputation: 1583

You can add a condition to your SearchCommand.CanExecute so that it returns false when focus is not in TextBox. Unfortunately, IsFocused, IsKeyboardFocused and IsKeyboardFocusWithin are all read-only DP, you won't be able to bind to them from markup (XAML), even if you set the Mode to OneWayToSource. You can create your own control that derives from TextBox for this.

public class FocusAwareTextBox : TextBox
{
    protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e)
    {
        if (e.OldValue != e.NewValue && e.NewValue != null)
        {
            HasFocus = (bool)e.NewValue;
        }

        base.OnIsKeyboardFocusWithinChanged(e);
    }

    public bool HasFocus
    {
        get { return (bool)GetValue(HasFocusProperty); }
        set { SetValue(HasFocusProperty, value); }
    }

    public static readonly DependencyProperty HasFocusProperty =
        DependencyProperty.Register(
            nameof(HasFocus),
            typeof(bool),
            typeof(FocusAwareTextBox),
            new PropertyMetadata(false));
}

You then bind the HasFocus DP to a new bool property in your ViewModel and add the check for this bool property in your SearchCommand.CanExecute.

Another solution would be to handle the KeyDown event instead and call the command from there. Note that you'll have to use a Behavior to keep the MVVM pattern.

Upvotes: 0

mm8
mm8

Reputation: 169190

This is the default behaviour. If I put the following two TextBoxes in a StackPanel, give the keyboard focus to the second one and press ENTER, the command is not fired.

<StackPanel>
    <TextBox Text="{Binding SearchBoxNumber, UpdateSourceTrigger=PropertyChanged}">
        <TextBox.InputBindings>
            <KeyBinding Key="Return" Command="{Binding SearchCommand}" />
        </TextBox.InputBindings>
    </TextBox>

    <TextBox />
</StackPanel>

Upvotes: 1

Related Questions