简体   繁体   English

当TextBlock是UserControl的一部分时,如何处理TextBlock.KeyDown事件?

[英]How to handle TextBlock.KeyDown event, when TextBlock is a part of UserControl?

I have this simple UserControl : 我有这个简单的UserControl

<UserControl x:Class="WPFTreeViewEditing.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TextBlock Text="Hello, world!" KeyDown="TextBlock_KeyDown" />
    </Grid>
</UserControl>

I want to handle TextBlock.KeyDown event. 我想处理TextBlock.KeyDown事件。 So, I've added an event handler to the code-behind: 因此,我在后面的代码中添加了一个事件处理程序:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void TextBlock_KeyDown(object sender, KeyEventArgs e)
    {
        MessageBox.Show("Key up!");
    }
}

but it doesn't fire. 但它不会触发。 What's wrong? 怎么了?

UPDATE. UPDATE。

PreviewKeyDown doesn't fire too. PreviewKeyDown也不会触发。

This UserControl is used in HierarchicalDataTemplate then: 然后在HierarchicalDataTemplate使用此UserControl

<Window x:Class="WPFTreeViewEditing.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFTreeViewEditing"
        Title="MainWindow" Height="265" Width="419">
    <Grid>
        <TreeView ItemsSource="{Binding}">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:ViewModel}" ItemsSource="{Binding Items}">
                    <local:UserControl1 />
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>
</Window>

From the documentation for UIElement.KeyDown : UIElement.KeyDown的文档中:

Occurs when a key is pressed while focus is on this element. 焦点位于此元素上并且按下键时发生。

You're using TextBlock which doesn't have the focus, so your KeyDown event will be handled by another control. 您使用的TextBlock没有焦点,因此KeyDown事件将由另一个控件处理。

You can switch to TextBox and appy some styles so it'll look and behave like TextBlock, but you'll be able to get the focus and handle the event. 您可以切换到TextBox并应用一些样式,以使其外观和行为类似于TextBlock,但是您将能够获得焦点并处理事件。

您应该使用PreviewKeyDown事件而不是KeyDown事件。

Ok, even though this question was posted a long time ago I had the same problem and found a way to get KeyDown events working, though it might not be what you're looking for I'll post the code to help future people with the same problem. 好的,即使这个问题是很久以前发布的,我也遇到了同样的问题,并且找到了一种使KeyDown事件正常工作的方法,尽管它可能并不是您想要的,但我将发布代码以帮助将来的人们同样的问题。

First thing first a KeyDown event handler in an Xaml Object will only fire off if that object has focus. 首先,Xaml对象中的KeyDown事件处理程序仅在该对象具有焦点时才会触发。 Therefore you need a CoreWindow event handler, it's kind off the same thing but it will always run no matter what object or thing has focus. 因此,您需要一个CoreWindow事件处理程序,虽然有点类似,但无论对象或对象具有焦点如何,它都将始终运行。 The following will be the code. 以下是代码。

//CLASS.xaml.h
ref class CLASS{
private:
    Platform::Agile<Windows::UI::Core::CoreWindow> window;

public:
    void KeyPressed(Windows::UI::Core::CoreWindow^ Window, Windows::UI::Core::KeyEventArgs^ Args);


//CLASS.xaml.cpp
CLASS::CLASS(){
    InitializeComponent();
    window = Window::Current->CoreWindow;

    window->KeyDown += ref new TypedEventHandler
    <Windows::UI::Core::CoreWindow^, Windows::UI::Core::KeyEventArgs^>(this, &CLASS::KeyPressed);
};

void CLASS::KeyPressed(Windows::UI::Core::CoreWindow^ Window, Windows::UI::Core::KeyEventArgs^ Args){
SimpleTextBox->Text = Args->VirtualKey.ToString();
};

Basically you want a value to hold your window and use that to create a new TypedEventHandler. 基本上,您想要一个值来保存窗口并使用该值创建一个新的TypedEventHandler。 For safety you'll generally want to do this in your class' constructor a function that's only called once the moment the class starts (I still prefer the constructor though). 为了安全起见,通常需要在类的构造函数中执行此操作,该函数仅在类启动后才被调用(尽管我仍然更喜欢构造函数)。

You can use this method to create an event handler for any event. 您可以使用此方法为任何事件创建事件处理程序。 Just change the "KeyDown" for another attribute like KeyUp, PointerMoved, PointerPressed and change the "&CLASS::KeyPressed" to the name of the function you want to be fired the moment you get an event of a corresponding type. 只需为另一个属性(如KeyUp,PointerMoved,PointerPressed)更改“ KeyDown”,然后将“&CLASS :: KeyPressed”更改为要在获得相应类型的事件后立即触发的函数的名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM