Maintaining keyboard focus on a single control, but ListBox can still be used

Working with the TouchScreen application, which also has a keyboard, I have the following problem:

The WPF window has a TextBox, which should receive ALL keyboard input. There are also buttons and ListBox that are exclusively used by TouchScreen (= Mouse).

A very simple example looks like this:

<Window x:Class="KeyboardFocusTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1">
    <StackPanel>
        <TextBox Text="{Binding Input, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                 PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus"/>
        <Button Click="Button_Click">Add</Button>
        <ListBox ItemsSource="{Binding Strings}" />
    </StackPanel>
</Window>

To keep the TextBox always focused, I just do:

private void TextBox_PreviewLostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
    e.Handled = true;
}

So far so good - the problem is that I can no longer select items from the list. This seems to work if the ListBox has keyboard focus. But if I lose the focus of the keyboard on the TextBox, I can no longer enter text without first pressing.

Any ideas, suggestions, comments are welcome!

+3
2

, PreviewKeyDown Window TextBox, , . , ListBox , , , TextBox. , , - , ListBox.

, , :

private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (!textBox.IsFocused)
    {
        textBox.Focus();
    }
}
+2

(!), , :

<TextBox Helpers:KeyboardFocusAttractor.IsAttracted="true" />

, , ANTS . WPF , , !

public static class KeyboardFocusAttractor
{
    public static readonly DependencyProperty IsAttracted = DependencyProperty.RegisterAttached("IsAttracted",
        typeof (bool), typeof (KeyboardFocusAttractor), new PropertyMetadata(false, OnIsAttracted));

    private static void OnIsAttracted(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var isAttracted = (bool) e.NewValue;
        var controlWithInputFocus = d as Control;

        if (controlWithInputFocus != null)
        {
            if (isAttracted)
            {
                new KeyboardInputFocusEventManager(controlWithInputFocus);
            }
        }
    }

    public static void SetIsAttracted(DependencyObject dp, bool value)
    {
        dp.SetValue(IsAttracted, value);
    }

    public static bool GetIsAttracted(DependencyObject dp)
    {
        return (bool) dp.GetValue(IsAttracted);
    }

    private class KeyboardInputFocusEventManager
    {
        private readonly Control _control;
        private Window _window;

        public KeyboardInputFocusEventManager(Control control)
        {
            _control = control;
            _control.Loaded += ControlLoaded;
            _control.IsVisibleChanged += ControlIsVisibleChanged;
            _control.Unloaded += ControlUnloaded;
        }

        private void ControlLoaded(object sender, RoutedEventArgs e)
        {
            _window = Window.GetWindow(_control);
            if (_window != null)
            {
                _control.Unloaded += ControlUnloaded;
                _control.IsVisibleChanged += ControlIsVisibleChanged;
                if (_control.IsVisible)
                {
                    _window.PreviewKeyDown += ParentWindowPreviewKeyDown;
                }
            }
        }

        private void ControlUnloaded(object sender, RoutedEventArgs e)
        {
            _control.Unloaded -= ControlUnloaded;
            _control.IsVisibleChanged -= ControlIsVisibleChanged;
        }

        private void ControlIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (_window != null)
            {
                _window.PreviewKeyDown -= ParentWindowPreviewKeyDown;
            }

            if (_control.IsVisible)
            {
                _window = Window.GetWindow(_control);
                if (_window != null)
                {
                    _window.PreviewKeyDown += ParentWindowPreviewKeyDown;
                }
            }
        }

        private void ParentWindowPreviewKeyDown(object sender, KeyEventArgs e)
        {
            Keyboard.Focus(_control);
        }
    }
}
+3

Source: https://habr.com/ru/post/1735280/


All Articles