1

我的路由事件在子元素之前点击了根 UI 元素。这是预期的吗?如何让路由事件首先命中子元素?

目标:如果在“自定义文本框”以外的任何地方输入文本,请将文本放入“默认文本框”

结果:Window_PreviewTextInput 在 custom_PreviewTextInput 之前被点击,即使我的光标焦点在“自定义文本框”上

我应该怎么做?


XAML

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" SizeToContent="WidthAndHeight"
        PreviewTextInput="Window_PreviewTextInput"
        >
    <Grid Margin="100,100,100,100">
        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="default" Width="100"/>
                <TextBox x:Name="defaultTB" Width="300" Height="50"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="custom" Width="100"/>
                <TextBox x:Name="custom" PreviewTextInput="custom_PreviewTextInput" Width="300" Height="50"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

代码背后:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        //goal:  if text is typed anywhere except custom textbox, put text in default textbox
        private void Window_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            Keyboard.Focus(defaultTB); 
        }

        //goal:  if text is typed in custom TB, put text there, and end the event routing
        private void custom_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            e.Handled = true; 
        }
    }
}
4

1 回答 1

2

路由事件可能是冒泡或隧道。你有一个隧道事件行为。

来自 MSDN,UIElement.PreviewTextInput 事件

路由策略 - 隧道

对应的冒泡事件是 TextInput。

路由事件概述 - 路由策略:

冒泡:调用事件源上的事件处理程序。路由事件然后路由到连续的父元素,直到到达元素树根。大多数路由事件使用冒泡路由策略。冒泡路由事件通常用于报告来自不同控件或其他 UI 元素的输入或状态更改

直接:只有源元素本身有机会调用处理程序作为响应。这类似于 Windows 窗体用于事件的“路由”。但是,与标准 CLR 事件不同的是,直接路由事件支持类处理(类处理将在下一节中介绍)并且可由 EventSetter 和 EventTrigger 使用。

隧道:最初,调用元素树根处的事件处理程序。然后,路由事件沿着路由穿过连续的子元素,到达作为路由事件源的节点元素(引发路由事件的元素)。隧道路由事件通常作为控件合成的一部分使用或处理,这样来自合成部分的事件可以被故意抑制或替换为特定于完整控件的事件。WPF 中提供的输入事件通常以隧道/冒泡对的形式实现。由于对使用的命名约定,隧道事件有时也称为预览事件。

于 2011-09-22T14:57:56.240 回答