[c#] Bind TextBox on Enter-key press

The default databinding on TextBox is TwoWay and it commits the text to the property only when TextBox lost its focus.

Is there any easy XAML way to make the databinding happen when I press the Enter key on the TextBox?. I know it is pretty easy to do in the code behind, but imagine if this TextBox is inside some complex DataTemplate.

This question is related to c# wpf xaml .net-3.5 textbox

The answer is


A different solution (not using xaml but still quite clean I think).

class ReturnKeyTextBox : TextBox
{
    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);
        if (e.Key == Key.Return)
            GetBindingExpression(TextProperty).UpdateSource();
    }
}

This works for me:

        <TextBox                 
            Text="{Binding Path=UserInput, UpdateSourceTrigger=PropertyChanged}">
            <TextBox.InputBindings>
                <KeyBinding Key="Return" 
                            Command="{Binding Ok}"/>
            </TextBox.InputBindings>
        </TextBox>

Answered here quite elegantly using attached behaviors, my preferred method for almost anything.

WPF how to make textbox lose focus after hitting enter


Here is an approach that to me seems quite straightforward, and easier that adding an AttachedBehaviour (which is also a valid solution). We use the default UpdateSourceTrigger (LostFocus for TextBox), and then add an InputBinding to the Enter Key, bound to a command.

The xaml is as follows

       <TextBox Grid.Row="0" Text="{Binding Txt1}" Height="30" Width="150">
        <TextBox.InputBindings>
            <KeyBinding Gesture="Enter" 
                        Command="{Binding UpdateText1Command}"
                        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}},Path=Text}" />
        </TextBox.InputBindings>
    </TextBox>

Then the Command methods are

Private Function CanExecuteUpdateText1(ByVal param As Object) As Boolean
    Return True
End Function
Private Sub ExecuteUpdateText1(ByVal param As Object)

    If TypeOf param Is String Then
        Txt1 = CType(param, String)
    End If
End Sub

And the TextBox is bound to the Property

 Public Property Txt1 As String
    Get
        Return _txt1
    End Get
    Set(value As String)
        _txt1 = value
        OnPropertyChanged("Txt1")
    End Set
End Property

So far this seems to work well and catches the Enter Key event in the TextBox.


This is how I solved this problem. I created a special event handler that went into the code behind:

private void TextBox_KeyEnterUpdate(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        TextBox tBox = (TextBox)sender;
        DependencyProperty prop = TextBox.TextProperty;

        BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop);
        if (binding != null) { binding.UpdateSource(); }
    }
}

Then I just added this as a KeyUp event handler in the XAML:

<TextBox Text="{Binding TextValue1}" KeyUp="TextBox_KeyEnterUpdate" />
<TextBox Text="{Binding TextValue2}" KeyUp="TextBox_KeyEnterUpdate" />

The event handler uses its sender reference to cause it's own binding to get updated. Since the event handler is self-contained then it should work in a complex DataTemplate. This one event handler can now be added to all the textboxes that need this feature.


I personally think having a Markup Extension is a cleaner approach.

public class UpdatePropertySourceWhenEnterPressedExtension : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return new DelegateCommand<TextBox>(textbox => textbox.GetBindingExpression(TextBox.TextProperty).UpdateSource());
    }
}


<TextBox x:Name="TextBox"
             Text="{Binding Text}">
        <TextBox.InputBindings>
            <KeyBinding Key="Enter"
                        Command="{markupExtensions:UpdatePropertySourceWhenEnterPressed}" 
                        CommandParameter="{Binding ElementName=TextBox}"/>
        </TextBox.InputBindings>
</TextBox>

In case you are using MultiBinding with your TextBox you need to use BindingOperations.GetMultiBindingExpression method instead of BindingOperations.GetBindingExpression.

// Get the correct binding expression based on type of binding
//(simple binding or multi binding.
BindingExpressionBase binding = 
  BindingOperations.GetBindingExpression(element, prop);
if (binding == null)
{
    binding = BindingOperations.GetMultiBindingExpression(element, prop);
}

if (binding != null)
{
     object value = element.GetValue(prop);
     if (string.IsNullOrEmpty(value.ToString()) == true)
     {
         binding.UpdateTarget();
     }
     else
     {
          binding.UpdateSource();
     }
}

This is not an answer to the original question, but rather an extension of the accepted answer by @Samuel Jack. I did the following in my own application, and was in awe of the elegance of Samuel's solution. It is very clean, and very reusable, as it can be used on any control, not just the TextBox. I thought this should be shared with the community.

If you have a Window with a thousand TextBoxes that all require to update the Binding Source on Enter, you can attach this behaviour to all of them by including the XAML below into your Window Resources rather than attaching it to each TextBox. First you must implement the attached behaviour as per Samuel's post, of course.

<Window.Resources>
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
        <Style.Setters>
            <Setter Property="b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed" Value="TextBox.Text"/>
        </Style.Setters>
    </Style>
</Window.Resources>

You can always limit the scope, if needed, by putting the Style into the Resources of one of the Window's child elements (i.e. a Grid) that contains the target TextBoxes.


I don't believe that there's any "pure XAML" way to do what you're describing. You can set up a binding so that it updates whenever the text in a TextBox changes (rather than when the TextBox loses focus) by setting the UpdateSourceTrigger property, like this:

<TextBox Name="itemNameTextBox"
    Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}" />

If you set UpdateSourceTrigger to "Explicit" and then handled the TextBox's PreviewKeyDown event (looking for the Enter key) then you could achieve what you want, but it would require code-behind. Perhaps some sort of attached property (similar to my EnterKeyTraversal property) woudld work for you.


You could easily create your own control inheriting from TextBox and reuse it throughout your project.

Something similar to this should work:

public class SubmitTextBox : TextBox
{
    public SubmitTextBox()
        : base()
    {
        PreviewKeyDown += new KeyEventHandler(SubmitTextBox_PreviewKeyDown);
    }

    void SubmitTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            BindingExpression be = GetBindingExpression(TextBox.TextProperty);
            if (be != null)
            {
                be.UpdateSource();
            }
        }
    }
}

There may be a way to get around this step, but otherwise you should bind like this (using Explicit):

<custom:SubmitTextBox
    Text="{Binding Path=BoundProperty, UpdateSourceTrigger=Explicit}" />

If you combine both Ben and ausadmin's solutions, you end up with a very MVVM friendly solution:

<TextBox Text="{Binding Txt1, Mode=TwoWay, UpdateSourceTrigger=Explicit}">
    <TextBox.InputBindings>
        <KeyBinding Gesture="Enter" 
                    Command="{Binding UpdateTextBoxBindingOnEnterCommand}"
                    CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}" />
    </TextBox.InputBindings>
</TextBox>

...which means you are passing the TextBox itself as the parameter to the Command.

This leads to your Command looking like this (if you're using a DelegateCommand-style implementation in your VM):

    public bool CanExecuteUpdateTextBoxBindingOnEnterCommand(object parameter)
    {
        return true;
    }

    public void ExecuteUpdateTextBoxBindingOnEnterCommand(object parameter)
    {
        TextBox tBox = parameter as TextBox;
        if (tBox != null)
        {
            DependencyProperty prop = TextBox.TextProperty;
            BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop);
            if (binding != null) 
                binding.UpdateSource();
        }
    }

This Command implementation can be used for any TextBox and best of all no code in the code-behind though you may want to put this in it's own class so there are no dependencies on System.Windows.Controls in your VM. It depends on how strict your code guidelines are.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to wpf

Error: the entity type requires a primary key Reportviewer tool missing in visual studio 2017 RC Pass command parameter to method in ViewModel in WPF? Calling async method on button click Setting DataContext in XAML in WPF How to resolve this System.IO.FileNotFoundException System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll? Binding an Image in WPF MVVM How to bind DataTable to Datagrid Setting cursor at the end of any text of a textbox

Examples related to xaml

Setting DataContext in XAML in WPF Change color of Button when Mouse is over Implement Validation for WPF TextBoxes Use StringFormat to add a string to a WPF XAML binding How to format number of decimal places in wpf using style/template? How to set DataGrid's row Background, based on a property value using data bindings WPF C# button style How to clear a textbox once a button is clicked in WPF? Add Items to Columns in a WPF ListView Binding ConverterParameter

Examples related to .net-3.5

Get first element from a dictionary redistributable offline .NET Framework 3.5 installer for Windows 8 How to read an entire file to a string using C#? HTTP Error 500.22 - Internal Server Error (An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode.) Change the Textbox height? How to get current date in 'YYYY-MM-DD' format in ASP.NET? C# Numeric Only TextBox Control Will the IE9 WebBrowser Control Support all of IE9's features, including SVG? Use LINQ to get items in one List<>, that are not in another List<> Get Absolute URL from Relative path (refactored method)

Examples related to textbox

Add two numbers and display result in textbox with Javascript How to check if a text field is empty or not in swift Setting cursor at the end of any text of a textbox Press enter in textbox to and execute button command javascript getting my textbox to display a variable How can I set focus on an element in an HTML form using JavaScript? jQuery textbox change event doesn't fire until textbox loses focus? PHP: get the value of TEXTBOX then pass it to a VARIABLE How to clear a textbox once a button is clicked in WPF? Get current cursor position in a textbox