如何捕获父控件中子项生成的事件?

How can I catch an event generated by a child in a parent control?

我创建了一个列表框控件,并重新定义了 ListBoxItem 的样式,如下所示:

    <Style TargetType="{x:Type customControls:CheckedListBox}"
           BasedOn="{StaticResource {x:Type ListBox}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Expander x:Name="PART_Expander" IsExpanded="True">
                        <ItemsPresenter/>
                    </Expander>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="SelectionMode" Value="Multiple"/>
        <Style.Resources>
            <Style TargetType="ListBoxItem" x:Name="PART_ListBoxItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <CheckBox Selector.IsSelected="True" IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Content="{Binding Path=.}">
                            </CheckBox>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="IsSelected" Value="True"/>
            </Style>
        </Style.Resources>
    </Style>

在 CheckedListBox 后面的代码中,我在单击任何复选框时引发事件:

       protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            RaiseRefreshDataEvent(e.RemovedItems);
        }
        protected virtual void RaiseRefreshDataEvent(IList changedItems)
        {
            RefreshDataSetEventArgs args = new RefreshDataSetEventArgs(CheckedListBox.RefreshDataSetEvent, changedItems);
            RaiseEvent(args);
        }
        public static readonly RoutedEvent RefreshDataSetEvent =
    EventManager.RegisterRoutedEvent("RefreshDataSet", RoutingStrategy.Bubble,
    typeof(RefreshDataSetEventHandler), typeof(CheckedListBox));

        public event RefreshDataSetEventHandler RefreshDataSet
        {
            add { AddHandler(RefreshDataSetEvent, value); }
            remove { RemoveHandler(RefreshDataSetEvent, value); }
        }


        public delegate void RefreshDataSetEventHandler(Object sender, RefreshDataSetEventArgs e);
 public class RefreshDataSetEventArgs : RoutedEventArgs
        {
            public IList ValueChanged { get; set; }
            public RefreshDataSetEventArgs(RoutedEvent routedEvent, IList valuesChanged) : base(routedEvent)
            {
                ValueChanged = valuesChanged;
            }
        }

现在,我想在 CheckedListBox 的父项之一中捕获 RefreshDataSetEvent。 我已经能够通过浏览可视化树对象、找到 CheckedListBox 并使用 RefreshDataSet 从父 class 添加一个方法到对象来做到这一点。 这 对我来说 像是一个 hack。我希望如果事件真的在可视化树中冒泡,我 应该 能够捕获它而不必显式向源对象添加处理程序。 知道如何在不显式设置对象处理程序的情况下捕获此事件吗?

编辑

CheckBoxList 在另一个名为 FilterDataGrid 的自定义控件中使用(这是 class 我想处理的事件)。这是 FilterDataGrid 的样式:

<Style TargetType="{x:Type customControls:FilterDataGrid}"
            BasedOn="{StaticResource {x:Type DataGrid}}">
        <Style.Resources>
            <Style TargetType="{x:Type DataGridColumnHeader}" x:Name="PART_DataGridColumnHeader">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <StackPanel>
                                <customControls:CheckedListBox ItemsSource="{Binding Path=.}"/>
                            </StackPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="Height" Value="Auto"/>
                <Setter Property="Background" Value="Black"/>
            </Style>
        </Style.Resources>
    </Style>

因此,当我尝试将 customControls:CheckedListBox.RefreshDataSet="TestThis" 添加到样式时,我收到一条错误消息,提示我使用 EventSetter。 当我将以下内容添加到事件 setter 的样式时,我得到一个 "Unknown build error, Object reference not set to an instance of an object": 根据文档,您不能在 Generic.xaml 文件中使用事件 setter。或者至少这是我从中收集到的:

Event setters cannot be used in a style that is contained in a theme resource dictionary. This is because a theme resource dictionary at run time is often loose binary XAML (BAML) files, and does not have any scope defined where accompanying code-behind that defines the handlers can exist.

所以我想知道如果无法在 Themes/Generic.xaml 文件中指定事件处理程序,我该如何设置它。

我可以通过在 EventManager 中注册一个 class 处理程序来实现它。 在 FilterDataGrid class 的 public 构造函数中,放入以下代码:

EventManager.RegisterClassHandler(typeof(FilterDataGrid), CheckedListBox.RefreshDataSetEvent, new CheckedListBox.RefreshDataSetEventHandler(FilterDataGridRefreshEventHandler));

考虑到 FilterDataGrid 和 CheckedListBox 都是自定义控件,我认为在两者之间放置一个硬 link 是可以的(请随时让我知道潜在的陷阱,我对这个控件还是很陌生创作的东西)。