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

时间:2012-07-02 08:28:11

标签: c# wpf textblock

我有这个简单的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>

我想处理TextBlock.KeyDown事件。所以,我为代码隐藏添加了一个事件处理程序:

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

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

但它没有发射。怎么了?

更新

PreviewKeyDown也不会发射。

UserControl用于HierarchicalDataTemplate然后:

<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>

3 个答案:

答案 0 :(得分:4)

来自UIElement.KeyDown的文档:

  

焦点在此元素上时按下某个键时发生。

您正在使用没有焦点的TextBlock,因此您的KeyDown事件将由另一个控件处理。

你可以切换到TextBox并设置一些样式,这样它的外观和行为就像TextBlock,但你将能够获得焦点并处理事件。

答案 1 :(得分:0)

您应该使用PreviewKeyDown事件代替KeyDown事件。

答案 2 :(得分:0)

好的,即使这个问题在很久以前发布过,我遇到了同样的问题,并找到了让KeyDown事件正常工作的方法,虽然它可能不是你想要的,但我会发布代码以帮助未来有同样问题的人。

首先,Xaml对象中的KeyDown事件处理程序仅在该对象具有焦点时才会触发。因此,你需要一个CoreWindow事件处理程序,它是同样的东西,但无论什么对象或事物有焦点它总是会运行。以下是代码。

//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();
};

基本上你需要一个值来保存你的窗口并使用它来创建一个新的TypedEventHandler。为了安全起见,您通常希望在类的构造函数中执行此操作,该函数仅在类启动时调用(我仍然更喜欢构造函数)。

您可以使用此方法为任何事件创建事件处理程序。只需更改KeyUp,PointerMoved,PointerPressed等其他属性的“KeyDown”,并在获得相应类型的事件时将“&amp; CLASS :: KeyPressed”更改为您想要触发的函数的名称。