21

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?

Mafii
  • 7,227
  • 1
  • 35
  • 55
code-zoop
  • 7,312
  • 8
  • 47
  • 56

5 Answers5

25

You can use the IsDefault property of the button:

    <Button Command="SearchCommand" IsDefault="{Binding ElementName=SearchTextBox,
                                               Path=IsKeyboardFocused}">
         Search!
   </Button>
Dabblernl
  • 15,831
  • 18
  • 96
  • 148
  • Thanks, easy and clean. Works great! – code-zoop Oct 19 '09 at 09:47
  • What if you don't have a button? – ihake Feb 25 '14 at 17:38
  • This works the first time I press enter. I continue editing the search and press enter and it doesn't perform the search. I have to manually click back on the search control to get it to perform another search when I press enter. – Brandon Dec 08 '14 at 22:00
  • Nevermind--I'm an idiot. I forgot to add UpdateSourceTrigger=PropertyChanged on the TextBox :D – Brandon Dec 08 '14 at 22:04
24

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>
Greg Sansom
  • 20,442
  • 6
  • 58
  • 76
  • I additionally had to change the UpdateSourceTrigger on my TextBox.Text binding to get this to work. For more details, check out [Capturing the Enter key in a TextBox](http://stackoverflow.com/a/5556526/744014). – Scott Nov 17 '12 at 13:24
  • 1
    This should be the accepted answer. It works great is clean where as the accepted answer is a bit of a hack. – kenjara Feb 02 '18 at 15:47
3

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}" />
Richard Szalay
  • 83,269
  • 19
  • 178
  • 237
2
<TextBox Text="{Binding SerachString, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.InputBindings>
        <KeyBinding Command="{Binding SearchCommand}" Key="Enter" />
    </TextBox.InputBindings>
</TextBox>

this should work fine.100%

jithu
  • 1,867
  • 1
  • 7
  • 16
0

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

Gert Hermans
  • 769
  • 1
  • 9
  • 30