阻止在WPF中从TextBox冒泡到MainWindow的KeyDown事件

时间:2011-11-03 09:15:24

标签: c# wpf event-bubbling event-routing

我有一个包含文本框控件的程序。用户可以在此控件中输入文本。用户还可以按某些键来触发其他操作(这在MainWindow上处理)。我有示例XAML和C#代码来演示我的设置。

XAML

<Window x:Class="RoutedEventBubbling.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">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBox Grid.Row="0" />
        <TextBox x:Name="Output" Grid.Row="1" IsReadOnly="True" />
    </Grid>
</Window>

C#

using System.Windows;
using System.Windows.Input;

namespace RoutedEventBubbling
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private int mHitCount = 0;

        public MainWindow()
        {
            InitializeComponent();
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            this.Output.Text = string.Format("Hit Count: {0}", ++mHitCount);
        }
    }
}

正如您可能已经意识到的那样,对于此程序,如果我开始输入第一个TextBox,则第二个将使用命中计数进行更新。这是一个不理想的结果,因为在处理MainWindow的OnKeyDown方法时,我可能会触发某些操作。

因此,我的问题是:是否可以阻止在MainWindow上调用OnKeyDown方法,同时仍允许在文本框中输入文本?我知道e.Handled = true方法,但在这种情况下,在KeyDown的{​​{1}}事件上执行此操作会阻止输入文本。如果无法做到这一点,我将不得不找到其他一些方法来处理这一切。

提前致谢。

修改

我刚刚在这个问题上找到了一种适度的hacky方式。如果我改为处理MainWindow的TextBox方法,那么我将获得所需的结果,因为OnTextInput的{​​{1}}事件将被处理。以下是我使用的代码示例:

TextInput

2 个答案:

答案 0 :(得分:0)

您可以在该声明中添加基于类型的警卫:

protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown(e);

    if (e.OriginalSource is TextBoxBase == false)
    {
        mPressedKey = e.Key;
    }
}

尽管可能不是最佳解决方案。

答案 1 :(得分:0)

我最后使用以下设置解决了这个问题:

private Key mPressedKey;

protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown(e);

    mPressedKey = e.Key;
}

protected override void OnTextInput(TextCompositionEventArgs e)
{
    base.OnTextInput(e);

    // ... Handle mPressedKey here ...
}

protected override void OnMouseDown(MouseButtonEventArgs e)
{
    base.OnMouseDown(e);

    // Force focus back to main window
    FocusManager.SetFocusedElement(this, this);
}

这是在MainWindow.xaml.cs中完成的。这有点像黑客,但它达到了我想要的结果。