Executing viewmodels command on enter in TextBox

WpfTextboxCommand

Wpf Problem Overview


I want to execute a command in my viewmodel when the user presses enter in a TextBox. The command works when bound to a button.

<Button Content="Add" Command="{Binding Path=AddCommand}" />

But I can't bring it to work from the TextBox. I tried an Inputbinding, but it didn't work.

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

I also tried to set the working button as default, but it doesn't get executed when enter is pressed.

Thanks for your help.

Wpf Solutions


Solution 1 - Wpf

I know I am late to the party, but I got this to work for me. Try using Key="Return" instead of Key="Enter"

Here is the full example

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

Make sure to use UpdateSourceTrigger=PropertyChanged in your binding, otherwise the property will not be updated until focus is lost, and pressing enter will not lose focus...

Hope this was helpful!

Solution 2 - Wpf

You have probably not made the command a property, but a field. It only works to bind to properties. Change your AddCommand to a property and it will work. (Your XAML works fine for me with a property instead of a field for the command -> no need for any code behind!)

Solution 3 - Wpf

Here's an attached dependency property I created for this. It has the advantage of ensuring that your text binding is updated back to the ViewModel before the command fires (useful for silverlight which doesn't support the property changed update source trigger).

public static class EnterKeyHelpers
{
    public static ICommand GetEnterKeyCommand(DependencyObject target)
    {
        return (ICommand)target.GetValue(EnterKeyCommandProperty);
    }

    public static void SetEnterKeyCommand(DependencyObject target, ICommand value)
    {
        target.SetValue(EnterKeyCommandProperty, value);
    }

    public static readonly DependencyProperty EnterKeyCommandProperty =
        DependencyProperty.RegisterAttached(
            "EnterKeyCommand",
            typeof(ICommand),
            typeof(EnterKeyHelpers),
            new PropertyMetadata(null, OnEnterKeyCommandChanged));

    static void OnEnterKeyCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        ICommand command = (ICommand)e.NewValue;
        FrameworkElement fe = (FrameworkElement)target;
        Control control = (Control)target;
        control.KeyDown += (s, args) =>
        {
            if (args.Key == Key.Enter)
            {
                // make sure the textbox binding updates its source first
                BindingExpression b = control.GetBindingExpression(TextBox.TextProperty);
                if (b != null)
                {
                    b.UpdateSource();
                }
                command.Execute(null);
            }
        };
    }
}

You use it like this:

<TextBox 
    Text="{Binding Answer, Mode=TwoWay}" 
    my:EnterKeyHelpers.EnterKeyCommand="{Binding SubmitAnswerCommand}"/>

Solution 4 - Wpf

You need to define Gesture instead of Key property of the KeyBinding:

<TextBox.InputBindings>
    <KeyBinding Gesture="Enter" Command="{Binding AddCommand}"/>
</TextBox.InputBindings>

Solution 5 - Wpf

In addition to Mark Heath's answer, I took the class one step further by implementing Command Parameter attached property in this way;

public static class EnterKeyHelpers
{
        public static ICommand GetEnterKeyCommand(DependencyObject target)
        {
            return (ICommand)target.GetValue(EnterKeyCommandProperty);
        }

        public static void SetEnterKeyCommand(DependencyObject target, ICommand value)
        {
            target.SetValue(EnterKeyCommandProperty, value);
        }

        public static readonly DependencyProperty EnterKeyCommandProperty =
            DependencyProperty.RegisterAttached(
                "EnterKeyCommand",
                typeof(ICommand),
                typeof(EnterKeyHelpers),
                new PropertyMetadata(null, OnEnterKeyCommandChanged));


        public static object GetEnterKeyCommandParam(DependencyObject target)
        {
            return (object)target.GetValue(EnterKeyCommandParamProperty);
        }

        public static void SetEnterKeyCommandParam(DependencyObject target, object value)
        {
            target.SetValue(EnterKeyCommandParamProperty, value);
        }

        public static readonly DependencyProperty EnterKeyCommandParamProperty =
            DependencyProperty.RegisterAttached(
                "EnterKeyCommandParam",
                typeof(object),
                typeof(EnterKeyHelpers),
                new PropertyMetadata(null));

        static void OnEnterKeyCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            ICommand command = (ICommand)e.NewValue;
            Control control = (Control)target;
            control.KeyDown += (s, args) =>
            {
                if (args.Key == Key.Enter)
                {
                    // make sure the textbox binding updates its source first
                    BindingExpression b = control.GetBindingExpression(TextBox.TextProperty);
                    if (b != null)
                    {
                        b.UpdateSource();
                    }
                    object commandParameter = GetEnterKeyCommandParam(target);
                    command.Execute(commandParameter);
                }
            };
        }
    } 

Usage:

<TextBox Text="{Binding Answer, Mode=TwoWay}" 
    my:EnterKeyHelpers.EnterKeyCommand="{Binding SubmitAnswerCommand}"
    my:EnterKeyHelpers.EnterKeyCommandParam="your parameter"/>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarksView Question on Stackoverflow
Solution 1 - WpfmkamionerView Answer on Stackoverflow
Solution 2 - WpfAndreas ZitaView Answer on Stackoverflow
Solution 3 - WpfMark HeathView Answer on Stackoverflow
Solution 4 - Wpfuser1826289View Answer on Stackoverflow
Solution 5 - WpfT.Y. KucukView Answer on Stackoverflow