События клавиатуры WPF не запускаются для подкласса FrameworkElement только с визуальными элементами

Я создал подкласс FrameworkElement, который имеет коллекцию визуалов:

public class GameElement : FrameworkElement
{
    private VisualCollection Visuals { get; }

    public GameElement()
    {
        this.KeyDown += this.OnKeyDown;
        this.MouseDown += this.OnMouseDown;
    }

    private void OnKeyDown(object sender, KeyEventArgs keyEventArgs)
    {
        ... // Does not get fired.
    }

    private void OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        ... // Does get fired.
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        // Draw a transparent background to catch mouse events (otherwise hit testing won't hit anything).
        drawingContext.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height));
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return this.Visuals.Count;
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= this.Visuals.Count)
        {
            throw new ArgumentOutOfRangeException();
        }

        return this.Visuals[index];
    }
}

Я отображаю этот элемент в XAML со следующим кодом:

<UserControl
    x:Class="..."
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Black">

    <Grid Margin="10">
        <local:GameElement x:Name="GameElement" ClipToBounds="True" />
    </Grid>
</UserControl>

Я перепробовал все, что только мог придумать, но просто не могу запустить событие KeyDown. Наиболее часто используемый комментарий, который я нахожу в Интернете, связан с фокусом. Я пробовал каждую комбинацию Focusable="True" и вызова this.Focus(), но ничего не работает.

У кого-нибудь есть идеи, как это сделать? Спасибо!

2 ответа

Я наконец заставил его работать, зарегистрировав обработчик класса, который также обрабатывает обработанные события.

EventManager.RegisterClassHandler(typeof(Window), Keyboard.KeyDownEvent, new KeyEventHandler(OnKeyDown), true);

Чтобы иметь возможность обрабатывать клавиши, нажатие вашего элемента должно быть сфокусировано. Также попробуйте получить его из-под контроля вместо FramworkElement, если вы можете это сделать.

public class GameElement : Control
{
    private VisualCollection Visuals { get; }

    public GameElement()
    {
        this.KeyDown += this.OnKeyDown;
        this.MouseDown += this.OnMouseDown;
    }

    private void OnKeyDown(object sender, KeyEventArgs keyEventArgs)
    {
        // Does get fired.
    }

    private void OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        Focus();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        // Draw a transparent background to catch mouse events (otherwise hit testing won't hit anything).
        drawingContext.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height));
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return this.Visuals.Count;
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= this.Visuals.Count)
        {
            throw new ArgumentOutOfRangeException();
        }

        return this.Visuals[index];
    }
}
Другие вопросы по тегам