Правильный способ сделать туннельное событие
РЕДАКТИРОВАТЬ: Я думаю, я задал немного проблемы XY. Меня не волнует, как работают туннельные события, и мне важно получить событиеподнял из кода позади родительского окна быть поднятым и отреагированным элементом управления, который является дочерним элементом этого окна, без явной необходимости сообщать дочернему элементу, кто является его родителем, и вручную подписываться на событие.
Я пытаюсь вызвать событие в родительском элементе управления и заставить дочерние элементы управления прослушивать это событие и реагировать на него. Из моего исследования я подумал, что мне просто нужно сделатьRoutedEvent
но я делаю что-то неправильно.
Вот MCVE, показывающий, что я пробовал, это простая программа с окном и UserControl внутри него.
<Window x:Class="RoutedEventsTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RoutedEventsTest"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Name="button" Click="ButtonBase_OnClick" HorizontalAlignment="Left"
VerticalAlignment="Top">Unhandled in parent</Button>
<local:ChildControl Grid.Row="1"/>
</Grid>
</Window>
using System.Windows;
namespace RoutedEventsTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TestEventHandler += MainWindow_TestEventHandler;
}
void MainWindow_TestEventHandler(object sender, RoutedEventArgs e)
{
button.Content = "Handeled in parent";
e.Handled = false;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(TestEvent));
}
public static readonly RoutedEvent TestEvent = EventManager.RegisterRoutedEvent("TestEvent", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(MainWindow));
public event RoutedEventHandler TestEventHandler
{
add { AddHandler(TestEvent, value); }
remove { RemoveHandler(TestEvent, value); }
}
}
}
<UserControl x:Class="RoutedEventsTest.ChildControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock Name="textBlock">Unhandeled in child</TextBlock>
</Grid>
</UserControl>
using System.Windows;
using System.Windows.Controls;
namespace RoutedEventsTest
{
public partial class ChildControl : UserControl
{
public ChildControl()
{
InitializeComponent();
AddHandler(MainWindow.TestEvent, new RoutedEventHandler(TestEventHandler));
}
private void TestEventHandler(object sender, RoutedEventArgs routedEventArgs)
{
textBlock.Text = "Handled in child";
routedEventArgs.Handled = false;
}
}
}
Когда я запускаю программу, родительское окно реагирует так, как я ожидал, но дочерний UserControl никогда не запускает свой делегат, которому я передалAddHandler
.
Изменение дочернего элемента управления, чтобы быть
public partial class ChildControl : UserControl
{
public ChildControl()
{
InitializeComponent();
AddHandler(TestEvent, new RoutedEventHandler(TestEventHandler));
}
public static readonly RoutedEvent TestEvent = EventManager.RegisterRoutedEvent("TestEvent", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(ChildControl));
private void TestEventHandler(object sender, RoutedEventArgs routedEventArgs)
{
textBlock.Text = "Handled in child";
routedEventArgs.Handled = false;
}
}
не решил проблему также. Я много искал и нашел много примеров того, как сделать пузырьковое событие, переходящее от ребенка к родителю, но я не смог найти ни одного полного примера, показывающего, как сделать туннельное событие от родителя к ребенку.