WPF 페이지 또는 UserControl 개체에서 KeyDown 이벤트를 캡처하려면 어떻게 해야 합니까?
사용자 컨트롤이 있는 페이지가 있습니다.사용자가 처리하고자 하는 페이지에서 Esc 키를 누른 경우.
PreviewKeyDown 이벤트 후크업, Esc 키 테스트, 처리처럼 간단하다고 생각했습니다.그러나 이벤트 핸들러에 브레이크 포인트를 배치했을 때 호출되지 않았습니다.UserControl이 히트하고 있는 것 같아서 PreviewKeyDown을 시도했습니다.같은 결과입니다.
페이지 오브젝트에서 KeyDown 또는 PreviewKeyDown을 테스트하는 적절한 장소를 알고 있는 사람이 있습니까?
창의 이벤트에 연결
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」KeyDown
의 이벤트)를 사용합니다.Window.GetWindow(this)
다음과 같이 합니다.
XAML
<UserControl Loaded="UserControl_Loaded">
</UserControl>
이면의 코드
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
}
나도 같은 문제가 있었다.다양한 페이지로 로드/내비게이트하는 프레임을 호스트하는 창이 있으며, 이 창에는 일반 컨트롤/요소(라벨, 하이퍼링크 등)가 포함된 사용자 컨트롤이 하나만 포함됩니다.
내가 발견한 것(물론 몇 시간 동안의 좌절 후에!!!)위의 컨트롤/요소에 포커스가 없는 경우 PreviewKeyDown 이벤트는 UserControl(프레임레벨의 어딘가에 정지)에서 실행되지 않고 포커스를 두는 즉시(예를 들어 ctrl을 호출하는 경우) 실행됩니다.UserCotrol의 Loaded 이벤트 핸들러 내의 Focus() 컨트롤 중 하나의 마법이 발생하여 동작하며 UserControl에서도 이벤트가 실행됩니다.
물론 나중에 생각하면 충분히 말이 되지만, 적어도 10명 중 5명은 깜짝 놀랄 거라고 100% 확신해:) WPF라고 불리는 말도 안 되는 작은 것...
건배!
PreviewKeyDown 이벤트는 버블링 이벤트가 아니라 터널링 라우팅 이벤트라고 생각합니다.이 경우 페이지가 이벤트를 수신할 수 없는 경우 UserControl은 시각적 트리의 페이지 아래에 있으므로 둘 다 수신할 수 없습니다.앱의 최상위 레벨(윈도?)에서 이벤트를 받을 수 있는지 확인해 보십시오.
CodePlex의 Snoop과 같은 기능을 사용하여 이벤트의 진행 위치를 파악하는 것도 도움이 될 수 있습니다.
UserControl에서 Focusable 속성을 true로 설정하면 문제가 해결되었습니다.
@Doc을 강화하는 방법을 제안합니다.
가 가장 바깥쪽의 KeyDown으로 합니다.Window
한 번.한번만Window
는 내부인 "" 에서 버블된 KeyDown 합니다.Window
된 모든 됩니다.를 들어 다음과 같습니다.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
}
★★★★★★★★★★★★★★★.+=
위험합니다.프로그래머는 이벤트 매니저의 등록 해제를 잊어버릴 가능성이 높습니다.메모리 누전이나 버그가 발생합니다.
여기서 제안합니다.
YourWindow.xaml.cs
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);
}
YourUserControlViewModel.cs 또는 YourUserControl.xaml.cs
public void CallKeyDown(KeyEventArgs e) {
//Do your work
}
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!");
}
WinForms에서 WPF 창을 호출했을 때도 같은 문제가 있었습니다.KeyDown 이벤트와 PreviewKeyDown 이벤트 모두 실행되지 않았습니다.
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.Show();
그러나 창을 대화상자로 표시하여 작동했다.
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.ShowDialog();
PreviewKeyDown 이벤트가 이스케이프 키와 화살표 키에 대한 부적처럼 발생하였습니다.
void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Escape:
this.Close();
break;
case Key.Right:
page_forward();
break;
case Key.Left:
page_backward();
break;
}
}
이게 먹히길 바라.
창의 이벤트에 첨부하지 않으려면 UserControl 또는 페이지의 변경 내용을 볼 수 있도록 이벤트를 추가하십시오.
IsVisibleChanged="Page_IsVisibleChanged"
그 후 코드 배후에:
private void Page_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if(this.Visibility == Visibility.Visible)
{
this.Focusable = true;
this.Focus();
}
}
아무 키나 누르면 KeyDown 이벤트가 발생합니다.
.Weindow_KeyDown
여기 예가 있다
private void Window_KeyDown(object sender, KeyEventArgs e)
{
// ... Test for F1 key.
if (e.Key == Key.F1)
{
this.Title = "You pressed F1 key";
}
}
꼭 해 주세요.Weindow_KeyDown
의
<Window x:Class="WpfApplication25.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"
KeyDown="Window_KeyDown">
</Window>
@Daniel 솔루션 대신 다음 작업을 수행합니다.이 솔루션에서는 윈도 전체에 이벤트 핸들러를 추가할 필요가 없습니다.
public partial class MyControl : UserControl{
public MyControl()
{
MouseEnter+= MouseEnterHandler;
MouseLeave+= MouseLeaveHandler;
}
protected void MouseEnterHandler(object sender, MouseEventArgs e)
{
var view = sender as MyControl;
view.KeyDown += HandleKeyPress;
view.KeyUp += HandleKeyReleased;
view.Focus();
}
protected void MouseLeaveHandler(object sender, MouseEventArgs e)
{
var view = sender as MyControl;
view.KeyDown -= HandleKeyPress;
view.KeyUp -= HandleKeyReleased;
}
protected void HandleKeyPress(object sender, KeyEventArgs e)
{
// What happens on key pressed
}
protected void HandleKeyReleased(object sender, KeyEventArgs e)
{
// What happens on key released
}
}
이렇게 하면 보기의 다른 부분에서 동일한 이벤트의 다른 핸들을 가질 수 있습니다.핸들은 로컬이며 컨트롤에 고유하며 전역 창에 핸들을 추가하지 않습니다.
ElementHost를 사용하여 창을 활성화해 보십시오.EnableModelessKeyboard상호 운용.이 경우 키다운 이벤트에서 화살표 키를 캡처합니다.
전화로 이 문제를 해결했습니다.뷰의 버튼에 포커스()를 붙여 창이 모든 요소의 로드를 완료했는지 확인합니다.
사용자 제어에 이니셜라이저가 있습니다.뒤에 있는 코드에 핸들러를 추가합니다.XAML에서는 아무것도 할 필요가 없습니다.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
KeyDown += Handle_KeyDown;
}
private void Handle_KeyDown(object sender, KeyEventArgs e)
{
throw new NotImplementedException();
}
}
온로드 이벤트는 필요 없습니다.이니셜라이저에 포함되어 있습니다.또한 모든 것을 한 파일에 보관하면 유지보수가 쉬워집니다.
다른 사용자가 언급했듯이 필요에 따라 PreviewKeyDown이 KeyDown보다 더 유용할 수 있습니다.
이것은 테스트 완료이며, 확실히 동작합니다.
Private Sub textbox1_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles textbox1_input.PreviewKeyDown
If (e.Key = Key.Down) Then
MessageBox.Show("It works.")
End If
End Sub
'detect key state directly with something like this below
Dim x As KeyStates = System.Windows.Input.Keyboard.GetKeyStates(Key.Down)
PreviewKeyDown은 대부분의 사람들이 놓치는 것입니다.PreviewKeyDown은 키보드이벤트의 전체적인 옵서버라고 생각하시면 됩니다(단, 틀리지 않으면 영향을 줄 수 없습니다).또, KeyDown event는, 현재 사용하고 있는 컨트롤이나 클래스의 범위내에서 재생되고 있습니다.
언급URL : https://stackoverflow.com/questions/347724/how-can-i-capture-keydown-event-on-a-wpf-page-or-usercontrol-object
'programing' 카테고리의 다른 글
AVFundation AVPlayer를 사용한 비디오 루프 (0) | 2023.04.15 |
---|---|
WPF 사용자 제어에서 Import된 리소스와 로컬 리소스를 결합하는 방법 (0) | 2023.04.15 |
디렉토리(중간 디렉토리 포함)를 안전하게 작성하려면 어떻게 해야 합니까? (0) | 2023.04.15 |
NS 프리픽스는 무엇을 의미합니까? (0) | 2023.04.15 |
rm이 파일을 찾을 수 없음을 보고하지 않도록 하려면 어떻게 해야 합니까? (0) | 2023.04.15 |