21
votes

I have a search field in my WPF app with a search button that contains a command binding. This works great, but how can i use the same command binding for the text field when pressing enter on the keyboard? The examples I have seen are all using the Code behind with a KeyDown Event Handler. Is there a smart way to make this work only with xaml and command binding?

5

5 Answers

25
votes

You can use the IsDefault property of the button:

    <Button Command="SearchCommand" IsDefault="{Binding ElementName=SearchTextBox,
                                               Path=IsKeyboardFocused}">
         Search!
   </Button>
24
votes

The accepted answer only works if you already have a button bound to the command.

To avoid this limitation, use TextBox.InputBindings:

<TextBox.InputBindings>
    <KeyBinding Key="Enter" Command="{Binding Path=MyCommand}"></KeyBinding>
</TextBox.InputBindings>
3
votes

The Prism Reference Implementation contains an implementation of exactly what you are after.

The basics steps are:

  • Create a static class EnterKey
  • Registered attached property "Command" of type ICommand on EnterKey
  • Registered attached property "EnterKeyCommandBehavior" of type EnterKeyCommandBehavior on EnterKey
  • When the value of "Command" changes, attach "EnterKeyCommandBehavior" to the control as a new instance of EnterKeyCommandBehavior, and assign the ICommand to the behavior's Command property.
    • If the behavior is already attached, use the existing instance
  • EnterKeyCommandBehavior accepts a UIElement in the constructor and attaches to the PreviewKeyDown (or KeyDown if you want to stay Silverlight compatible).
  • In the event handler, if the key is Enter, execute the ICommand (if CanExecute is true).

This enables you to use the behavior like so:

<TextBox prefix:EnterKey.Command="{Binding Path=SearchCommand}" />
1
votes
<TextBox Text="{Binding SerachString, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.InputBindings>
        <KeyBinding Command="{Binding SearchCommand}" Key="Enter" />
    </TextBox.InputBindings>
</TextBox>

this should work fine.100%

0
votes

I've tried the TextBox.Inputs solution of Greg Samson , but got an error saying that I could only bind to textinputs through a dependency property. In the end I've found the next solution for this.

Create a class called CommandReference which looks like this:

public class CommandReference : Freezable, ICommand
{
    public CommandReference()
    {
        //
    }

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandReference), new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        if (Command != null)
            return Command.CanExecute(parameter);
        return false;
    }

    public void Execute(object parameter)
    {
        Command.Execute(parameter);
    }

    public event EventHandler CanExecuteChanged;

    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CommandReference commandReference = d as CommandReference;
        ICommand oldCommand = e.OldValue as ICommand;
        ICommand newCommand = e.NewValue as ICommand;

        if (oldCommand != null)
        {
            oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;
        }
        if (newCommand != null)
        {
            newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;
        }
    }

    #endregion

    #region Freezable

    protected override Freezable CreateInstanceCore()
    {
        throw new NotImplementedException();
    }

    #endregion
}

In Xaml add this to the UserControl Resources:

<UserControl.Resources>
    <Base:CommandReference x:Key="SearchCommandRef" Command="{Binding Path = SomeCommand}"/>

The actual TextBox looks like this:

 <TextBox Text="{Binding Path=SomeText}">
                    <TextBox.InputBindings>
                        <KeyBinding Command="{StaticResource SearchCommandRef}" Key="Enter"/>
                    </TextBox.InputBindings>
                </TextBox>

I don't remember where I got this code from, but this site explains it as well;

http://www.netframeworkdev.com/windows-presentation-foundation-wpf/invoke-a-command-with-enter-key-after-typing-in-a-textbox-21909.shtml