Держите фокус на пользовательском (пользовательском) элементе управления в WPF

Скажем, мне нужно переместить пользовательский (пользовательский) элемент управления в форму с помощью клавиатуры.

Поведение простое: пользователь щелкает элемент управления, затем он может перемещать его с помощью клавиатуры (вверх/d/l/r).

В этом примере вместо UserControl я буду использовать Canvas.

Проблема в том, что когда я «сосредотачиваю» свой контроль, или теряю его после переворота «шагов» для текстового поля, или я вообще его не получаю...

XAML:

<Window x:Class="WpfApplication14.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        PreviewKeyDown="Window_PreviewKeyDown">
    <Grid>
        <TextBox Name="textBox1" 
                 Margin="91,66,292,223" Width="120" 
                 Text="Good morning, miss Hilton!"/>
        <Canvas Name="canvas1" Focusable="True"
                Margin="124,112,179,99" Width="200"
                Background="AliceBlue"
                MouseDown="canvas1_MouseDown"
                PreviewKeyDown="canvas1_PreviewKeyDown"  />
    </Grid>
</Window>

CS:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void canvas1_MouseDown(object sender, MouseButtonEventArgs e)
    {
        Console.WriteLine("canvas_MouseDown 0, canvas1.IsFocused? {0}",
            canvas1.IsFocused);

        canvas1.Focus();

        Console.WriteLine("canvas_MouseDown 1, canvas1.IsFocused? {0}",
            canvas1.IsFocused);
    }

    private void canvas1_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        Console.WriteLine("canvas_PreviewKeyDown, canvas1.IsFocused? {0}",
            canvas1.IsFocused);

        if (canvas1.IsFocused)
            MoveCanvas(e.Key);
    }

    private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        //Console.WriteLine("Window_PreviewKeyDown, canvas1.IsFocused? {0}",
        //    canvas1.IsFocused);

        //if (canvas1.IsFocused)
        //    MoveCanvas(e.Key);
    }

    void MoveCanvas(Key key)
    {
        int delta = 10;
        switch (key)
        {
            case Key.Left: canvas1.Margin = new Thickness(
                canvas1.Margin.Left - delta,
                canvas1.Margin.Top,
                canvas1.Margin.Right,
                canvas1.Margin.Bottom);
                break;
            case Key.Up: canvas1.Margin = new Thickness(
                canvas1.Margin.Left,
                canvas1.Margin.Top - delta,
                canvas1.Margin.Right,
                canvas1.Margin.Bottom + delta);
                break;
            case Key.Right: canvas1.Margin = new Thickness(
                canvas1.Margin.Left,
                canvas1.Margin.Top,
                canvas1.Margin.Right - delta,
                canvas1.Margin.Bottom);
                break;
            case Key.Down: canvas1.Margin = new Thickness(
                canvas1.Margin.Left,
                canvas1.Margin.Top + delta,
                canvas1.Margin.Right,
                canvas1.Margin.Bottom - delta);
                break;
            default:
                break;
        }
    }
}

Ниже приведен журнал выполнения после нажатия кнопки мыши на элементе управления и трех «keyUp»:

   canvas_MouseDown 0, canvas1.IsFocused? False ' before click '
   canvas_MouseDown 1, canvas1.IsFocused? True  ' after click ' 
Window_PreviewKeyDown, canvas1.IsFocused? True  ' up 1 '
canvas_PreviewKeyDown, canvas1.IsFocused? True  ' up 1 '
Window_PreviewKeyDown, canvas1.IsFocused? False ' up 2 '
Window_PreviewKeyDown, canvas1.IsFocused? False ' up 3 '

person serhio    schedule 14.04.2011    source источник


Ответы (1)


Две вещи, которые вы можете попробовать:

  1. Установите для e.Handled значение true, если вы обрабатываете событие. Это должно предотвратить реакцию других вещей на нажатие клавиши.

  2. Возможно, вам придется поиграть с KeyboardNavigation.DirectionalNavigation для всех предков. Клавиши со стрелками по умолчанию перемещают фокус клавиатуры, но это зависит от параметра DirectionalNavigation. Вы бы хотели установить для него значение «Нет», но это предполагает, что № 1 не устраняет проблему.

person CodeNaked    schedule 14.04.2011
comment
очень хорошо помогла установка Handled в true. Спасибо! - person serhio; 14.04.2011