Search code examples
c#wpftextboxkey-bindingsinputbinding

How can I write something in a TextBox that's also used as a KeyBinding?


I have a global input binding for the key period (.). I'd still like to be able to enter it in a TextBox? Is there a way to accomplish this?

Here's a simple sample case. The command is executed when I type the period in the TextBox.

XAML:

<Window x:Class="UnrelatedTests.Case6.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <Window.InputBindings>
        <KeyBinding Key="OemPeriod" Command="{Binding Command}" />
    </Window.InputBindings>
    <Grid>
        <TextBox >Unable to type "." here!</TextBox>
    </Grid>
</Window>

C#:

using System;
using System.Windows;
using System.Windows.Input;

namespace UnrelatedTests.Case6
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = this;
        }

        public ICommand Command
        {
            get { return new CommandImpl(); }
        }


        private class CommandImpl : ICommand
        {
            public bool CanExecute(object parameter)
            {
                return true;
            }

            public void Execute(object parameter)
            {
                MessageBox.Show("executed!");
            }

            public event EventHandler CanExecuteChanged;
        }
    }
}

Solution

  • You can bind the Key in your KeyBinding and change it's value to Key.None when your TextBox got focus:

    Xaml:

    <Window x:Class="UnrelatedTests.Case6.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Window1" Height="300" Width="300"
            GotFocus="Window_GotFocus">
        <Window.InputBindings>
            <KeyBinding Key="{Binding MyKey}" Command="{Binding Command}" />
        </Window.InputBindings>
        <Grid>
            <TextBox/>
        </Grid>
    </Window>
    

    MainWindow.cs: (with INotifyPropertyChanged implemented)

        Key _myKey;
        public Key MyKey
        {
            get
            {
                return _myKey;
            }
            set
            {
                _myKey = value;
                OnPropertyChanged("MyKey");
            }
        }
    
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            MyKey = Key.OemPeriod;
        }
    
        private void Window_GotFocus(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is TextBox)
                MyKey = Key.None;
            else
                MyKey = Key.OemPeriod;
        }