我有一个带有UserControl的页面.如果用户在我想要处理的页面上的任何位置按Esc.
我认为这就像挂钩PreviewKeyDown事件,测试Esc键,然后处理它一样简单.但是,当我在事件处理程序中放置断点时,我发现它永远不会被调用.我想也许UserControl可能会被击中,所以我尝试了PreviewKeyDown ......结果相同.
有没有人知道在Page对象上测试KeyDown或PreviewKeyDown的正确位置?
Dan*_*iel 38
加载控件后,使用如下所示附加到Window的KeyDown事件(或任何事件)Window.GetWindow(this):
XAML
<UserControl Loaded="UserControl_Loaded">
</UserControl>
Run Code Online (Sandbox Code Playgroud)
守则背后
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
var window = Window.GetWindow(this);
window.KeyDown += HandleKeyPress;
}
private void HandleKeyPress(object sender, KeyEventArgs e) {
//Do work
}
Run Code Online (Sandbox Code Playgroud)
小智 26
我曾经有过同样的问题.我有一个窗口,它承载一个框架,它加载/导航到各个页面,而这些页面只包含1个UserControl,其中包含正常的控件/元素(标签,超链接等).
我发现的(当然是经过几个小时的挫折!!!)是因为如果你没有关注上面提到的一个控件/元素,那么PreviewKeyDown事件不会触发UserControl(在Frame级别的某处停止)但是一旦你将焦点(例如在UserCotrol的Loaded事件处理程序中调用ctrl.Focus())放在其中一个控件上,就会发生魔法,它会起作用,事件也会为UserControl触发.
当然,考虑到它后来这已经足够了但我100%肯定这将至少让10个人中的5个惊讶:)疯狂的小东西叫WPF ...
干杯!
And*_*ndy 21
我相信PreviewKeyDown事件是隧道路由事件,而不是冒泡事件.如果是这种情况,那么如果您的页面没有获得该事件,则UserControl不应该是因为它位于可视树中的页面下方.也许尝试在应用程序的顶层处理它(可能是Window?)并查看它是否正在获取该事件?
另一个可能有用的选择是在CodePlex中使用Snoop之类的东西来确定事件发生的位置.
我提出了一种加强所提到的@Doc的方法.
提到的以下代码@Doc将起作用,因为KeyDown路由事件被冒泡到最外面Window.一旦Window收到从内部元素冒泡的KeyDown事件,Window就会触发注册到它的任何KeyDown事件处理程序,就像这样HandleKeyPress.
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
var window = Window.GetWindow(this);
window.KeyDown += HandleKeyPress;
}
private void HandleKeyPress(object sender, KeyEventArgs e) {
//Do work
}
Run Code Online (Sandbox Code Playgroud)
但这+=有风险,程序员更可能忘记取消注册事件处理程序.然后内存泄漏或一些错误将发生.
在这里我建议,
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
// You need to have a reference to YourUserControlViewModel in the class.
YourUserControlViewModel.CallKeyDown(e);
// Or, if you don't like ViewModel, hold your user-control in the class then
YourUserControl.CallKeyDown(e);
}
Run Code Online (Sandbox Code Playgroud)
public void CallKeyDown(KeyEventArgs e) {
//Do your work
}
Run Code Online (Sandbox Code Playgroud)
无需在xaml中编码.
什么对我有用:
仅在窗口Loaded 事件上监听 PreviewKeyDown 事件:
void GameScreen_Loaded(object sender, RoutedEventArgs e)
{
this.PreviewKeyDown += GameScreen_PreviewKeyDown;
this.Focusable = true;
this.Focus();
}
void GameScreen_PreviewKeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("it works!");
}
Run Code Online (Sandbox Code Playgroud)