События клавиатуры 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];
}
}