Search code examples
c#wpftextboxkeypress

how can i focus textbox in xaml with keybinding?


How can I set focus on a TextBox when F3 key pressed.

In other words, do some thing like bellow:

private void Window_PreviewKeyDown(object sender, KeyEventArgs )
{
       switch (e.Key)
       {
           case Key.F3:
               myTextBox1.Focus();
               break;
           case Key.F4:
               myTextBox2.Focus();
               break;
           default:
               break;
      }
}

note:I want to do it in xaml.


Solution

  • You could do this by created an attached property that takes a shortcut key then create an input binding on the window hosting that control.. it's a bit of a complex class but very easy to use.

    start by adding a new class to your project below.

     public class TextBoxHelper : DependencyObject
        {
            public class MvvmCommand : DependencyObject, ICommand
            {
                readonly Action<object> _execute;
                readonly Func<object, bool> _canExecute;
                public event EventHandler CanExecuteChanged;
                public MvvmCommand(Action<object> execute, Func<object, bool> canExecute = null)
                {
                    if (execute == null) throw new ArgumentNullException("command");
                    _canExecute = canExecute == null ? parmeter => MvvmCommand.AlwaysCanExecute() : canExecute;
                    _execute = execute;
                }
                public object Tag
                {
                    get { return (object)GetValue(TagProperty); }
                    set { SetValue(TagProperty, value); }
                }
                public static readonly DependencyProperty TagProperty = DependencyProperty.Register("Tag", typeof(object), typeof(MvvmCommand), new PropertyMetadata(null));
                static bool AlwaysCanExecute()
                {
                    return true;
                }
                public void EvaluateCanExecute()
                {
                    EventHandler temp = CanExecuteChanged;
                    if (temp != null)
                        temp(this, EventArgs.Empty);
                }
                public virtual void Execute(object parameter)
                {
                    _execute(parameter == null ? this : parameter);
                }
                public virtual bool CanExecute(object parameter)
                {
                    return _canExecute == null ? true : _canExecute(parameter);
                }
            }
    
            public static Key GetFocusKey(DependencyObject obj)
            {
                return (Key)obj.GetValue(FocusKeyProperty);
            }
    
            public static void SetFocusKey(DependencyObject obj, Key value)
            {
                obj.SetValue(FocusKeyProperty, value);
            }
    
            public static readonly DependencyProperty FocusKeyProperty =
                DependencyProperty.RegisterAttached("FocusKey", typeof(Key), typeof(TextBoxHelper), new PropertyMetadata(Key.None, new PropertyChangedCallback((s, e) =>
                    {
                        UIElement targetElement = s as UIElement;
                        if (targetElement != null)
                        {
                            MvvmCommand command = new MvvmCommand(parameter => TextBoxHelper.FocusCommand(parameter))
                                {
                                    Tag = targetElement, 
                                };
                            InputGesture inputg = new KeyGesture((Key)e.NewValue);
                            (Window.GetWindow(targetElement)).InputBindings.Add(new InputBinding(command, inputg));
                        }
                    })));
    
            public static void FocusCommand(object parameter)
            {
                MvvmCommand targetCommand = parameter as MvvmCommand;
                if (targetCommand != null)
                {
                    UIElement targetElement = targetCommand.Tag as UIElement;
                    if (targetElement != null)
                    {
                        targetElement.Focus();
                    }
                }
            }
        }
    

    now in XAML all you need to do to set your focus keys is assign that FocusKey property, an example below has 2 textboxes, one gets focus when F1 is pressed, the other when F7 is pressed.

    <Window x:Class="WpfApplication5.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfApplication5"
            DataContext="{Binding RelativeSource={RelativeSource Self}}"
            Title="MainWindow" Height="131" Width="460">
    
        <Grid Margin="10">
            <TextBox Margin="0,0,0,60" local:TextBoxHelper.FocusKey="F1" />
            <TextBox Margin="0,35,0,0" local:TextBoxHelper.FocusKey="F7" />
        </Grid>
    </Window>