Проблема Routed Events - попадание в корневой элемент пользовательского интерфейса перед дочерним элементом
Мои перенаправленные события попадают в корневой элемент пользовательского интерфейса перед дочерним элементом. Это ожидается? Как можно, чтобы перенаправленные события сначала попадали в дочерний элемент?
Цель: если текст набирается где-либо, кроме "пользовательского текстового поля", поместите текст в "текстовое поле по умолчанию"
Результат: Window_PreviewTextInput запускается перед custom_PreviewTextInput, даже если мой курсор находится в фокусе "Custom Textbox"
Что я должен делать по-другому?
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;
}
}
}
1 ответ
Маршрутизируемое событие может быть пузырьковым или туннельным. У вас есть поведение события туннелирования.
Из MSDN, событие UIElement.PreviewTextInput:
Стратегия маршрутизации - Туннелирование
Соответствующее всплывающее событие - TextInput.
Обзор маршрутизируемых событий - стратегии маршрутизации:
Bubbling: Вызываются обработчики событий в источнике событий. Затем перенаправленное событие направляется к последующим родительским элементам до достижения корня дерева элементов. В большинстве маршрутизируемых событий используется стратегия маршрутизации пузырьков. Пузырьковые перенаправленные события обычно используются для сообщения об изменениях ввода или состояния из отдельных элементов управления или других элементов пользовательского интерфейса.
Direct: только самому исходному элементу предоставляется возможность вызывать обработчики в ответ. Это аналогично "маршрутизации", которую Windows Forms использует для событий. Однако, в отличие от стандартного события CLR, события с прямой маршрутизацией поддерживают обработку классов (обработка классов описана в следующем разделе) и могут использоваться EventSetter и EventTrigger.
Туннелирование: изначально запускаются обработчики событий в корне дерева элементов. Затем перенаправленное событие проходит маршрут через последовательные дочерние элементы вдоль маршрута к элементу узла, который является источником перенаправленного события (элемент, вызвавший перенаправленное событие). Туннелирование перенаправленных событий часто используется или обрабатывается как часть компоновки для элемента управления, так что события из составных частей могут быть преднамеренно подавлены или заменены событиями, характерными для всего элемента управления. Входные события, предоставляемые в WPF, часто реализуются в виде пары туннелирование / пузыри. Туннельные события также иногда называют предварительными событиями из-за соглашения об именах, которое используется для пар.