Как обрабатывать событие TextBlock.KeyDown, когда TextBlock является частью 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>

Я хочу обработать событие 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>

person Dennis    schedule 02.07.2012    source источник


Ответы (3)


Из документации для UIElement.KeyDown:

Происходит при нажатии клавиши, когда фокус находится на этом элементе.

Вы используете TextBlock, у которого нет фокуса, поэтому ваше событие KeyDown будет обрабатываться другим элементом управления.

Вы можете переключиться на TextBox и применить некоторые стили, чтобы он выглядел и вел себя как TextBlock, но вы сможете получить фокус и обработать событие.

person ShadeOfGrey    schedule 02.07.2012

Вы должны использовать событие PreviewKeyDown вместо события KeyDown.

person Nikhil Agrawal    schedule 02.07.2012
comment
Тот же результат. Он не срабатывает. Обновил вопрос. - person Dennis; 02.07.2012

Хорошо, хотя этот вопрос был опубликован давно, у меня была та же проблема, и я нашел способ заставить работать события KeyDown, хотя это может быть не то, что вы ищете, я опубликую код, чтобы помочь будущим людям с та же проблема.

Прежде всего, обработчик событий KeyDown в объекте Xaml срабатывает только в том случае, если этот объект имеет фокус. Поэтому вам нужен обработчик событий 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. В целях безопасности вы, как правило, захотите сделать это в конструкторе вашего класса функцией, которая вызывается только один раз в момент запуска класса (хотя я все же предпочитаю конструктор).

Этот метод можно использовать для создания обработчика любого события. Просто измените «KeyDown» на другой атрибут, такой как KeyUp, PointerMoved, PointerPressed, и измените «&CLASS::KeyPressed» на имя функции, которую вы хотите запустить в момент получения события соответствующего типа.

person Jader J Rivera    schedule 19.07.2013