从 Unloaded 事件处理程序引发的 RoutedEvent 不冒泡
RoutedEvent raised from Unloaded event handler not bubbling
我有一个继承自 ItemsControl 的自定义用户控件。通过它的 ItemTemplate,它从 ObservableCollection 为每个附加的 ViewModel 创建一个 ChildControl。
public class ChildControl : FrameworkElement
{
public static readonly RoutedEvent CreatedEvent = EventManager.RegisterRoutedEvent(
nameof(Created),
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(ChildControl));
public static readonly RoutedEvent RemovedEvent = EventManager.RegisterRoutedEvent(
nameof(Removed),
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(ChildControl));
public ChildControl
{
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
public event RoutedEventHandler Created
{
add => AddHandler(CreatedEvent, value);
remove => RemoveHandler(CreatedEvent, value);
}
public event RoutedEventHandler Removed
{
add => AddHandler(RemovedEvent, value);
remove => RemoveHandler(RemovedEvent, value);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(CreatedEvent));
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(RemovedEvent));
}
}
和 CustomItemsControl
public class CustomItemsControl : ItemsControl
{
public CustomItemsControl()
{
AddHandler(ChildControl.CreatedEvent, new RoutedEventHandler(OnCreatedEvent));
AddHandler(ChildControl.RemovedEvent, new RoutedEventHandler(OnRemovedEvent));
}
private void OnCreatedEvent(object sender, RoutedEventArgs e)
{
// stuff
}
private void OnRemovedEvent(object sender, RoutedEventArgs e)
{
// stuff
}
}
除了 RemovedEvent 处理程序之外,一切正常。当事件在 ChildControl 的 Unloaded 事件处理程序中引发时,它不会被 CustomItemsControl 捕获。但是,当调用 RemovedEvent 时,假设在 Loaded 事件处理程序中,它会被 CustomItemsControl 捕获。所以证明一切正常。
我是不是做错了什么,或者这是否意味着从 Unloaded 事件处理程序中调用的 RoutedEvents 没有按设计冒泡?
东西没了
但你还是希望听到它。
Re-consider 卸载事件。
想想发生了什么。
“当元素从加载元素的元素树中移除时发生。”
没了
因为没有。
不在任何视觉树中,不在任何东西中。
因为它是从UI.
卸载的
来自它的路由事件不能冒泡或隧道或任何涉及可视化树的事件。因为 ui 元素不再在那棵树中。
您需要做的是首先引发自定义路由事件,然后卸载您的控件。也许完全使用不同的方法会是更好的方法。示例包括:prism eventaggregator 或 mvvmlight messenger 或将引用从父级传递给子级以便它可以直接调用方法。
我有一个继承自 ItemsControl 的自定义用户控件。通过它的 ItemTemplate,它从 ObservableCollection 为每个附加的 ViewModel 创建一个 ChildControl。
public class ChildControl : FrameworkElement
{
public static readonly RoutedEvent CreatedEvent = EventManager.RegisterRoutedEvent(
nameof(Created),
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(ChildControl));
public static readonly RoutedEvent RemovedEvent = EventManager.RegisterRoutedEvent(
nameof(Removed),
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(ChildControl));
public ChildControl
{
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
public event RoutedEventHandler Created
{
add => AddHandler(CreatedEvent, value);
remove => RemoveHandler(CreatedEvent, value);
}
public event RoutedEventHandler Removed
{
add => AddHandler(RemovedEvent, value);
remove => RemoveHandler(RemovedEvent, value);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(CreatedEvent));
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(RemovedEvent));
}
}
和 CustomItemsControl
public class CustomItemsControl : ItemsControl
{
public CustomItemsControl()
{
AddHandler(ChildControl.CreatedEvent, new RoutedEventHandler(OnCreatedEvent));
AddHandler(ChildControl.RemovedEvent, new RoutedEventHandler(OnRemovedEvent));
}
private void OnCreatedEvent(object sender, RoutedEventArgs e)
{
// stuff
}
private void OnRemovedEvent(object sender, RoutedEventArgs e)
{
// stuff
}
}
除了 RemovedEvent 处理程序之外,一切正常。当事件在 ChildControl 的 Unloaded 事件处理程序中引发时,它不会被 CustomItemsControl 捕获。但是,当调用 RemovedEvent 时,假设在 Loaded 事件处理程序中,它会被 CustomItemsControl 捕获。所以证明一切正常。
我是不是做错了什么,或者这是否意味着从 Unloaded 事件处理程序中调用的 RoutedEvents 没有按设计冒泡?
东西没了
但你还是希望听到它。
Re-consider 卸载事件。 想想发生了什么。
“当元素从加载元素的元素树中移除时发生。”
没了
因为没有。
不在任何视觉树中,不在任何东西中。
因为它是从UI.
卸载的来自它的路由事件不能冒泡或隧道或任何涉及可视化树的事件。因为 ui 元素不再在那棵树中。
您需要做的是首先引发自定义路由事件,然后卸载您的控件。也许完全使用不同的方法会是更好的方法。示例包括:prism eventaggregator 或 mvvmlight messenger 或将引用从父级传递给子级以便它可以直接调用方法。