EDIT: Я предполагаю, что я задал проблему 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;
}
}
не решить проблему либо. Я много искал и нашел много примеров того, как сделать событие с пузырьками, идущее от ребенка к родительскому, но я не смог найти ни одного полного примера, показывающего, как сделать туннелированное событие от родителя к ребенку.
Хорошо, поэтому я неправильно использую туннелированные события. Я действительно не забочусь о том, как правильно делать туннельное событие. Я хочу, чтобы событие **, поднятое в родительском окне **, было подобрано на дочернем элементе управления, без необходимости явно указывать ребенку, кто является его родителем. Возможно ли это в WPF? Я обновил свой вопрос, в то время как ваш ответ действительно хорош и объясняет, почему мой пример не работает, он не решает проблему, которую я пытаюсь решить. –
И если вы обновите свой вопрос, показывая, как решить мою настоящую проблему, оставьте свой исходный ответ тоже. Ваш текущий ответ - лучший, который я видел в Интернете, объясняя туннелированные события. –