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

时间:2019-05-03 16:18:00

标签: c# wpf custom-controls

我已经创建了一个列表框控件,并且重新定义了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从父类向对象添加方法,我已经能够做到这一点。 在我看来,这 就像是骇客。我希望,如果该事件确实使可视树冒泡,我应该能够捕获它,而不必显式向源对象添加处理程序。 知道如何在不显式设置对象处理程序的情况下捕获该事件吗?

编辑

CheckBoxList在另一个名为FilterDataGrid的自定义控件中使用(这是我想要处理事件的类)。这是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。 当我将以下内容添加到事件设置器的样式中时,出现“未知的生成错误,对象引用未设置为对象的实例”:                                根据文档,您不能在Generic.xaml文件中使用事件设定者。或者至少是我从中收集的信息:

  

事件设置器不能以主题中包含的样式使用   资源字典。这是因为主题资源字典位于   运行时通常是松散的二进制XAML(BAML)文件,并且没有   在定义了以下内容的伴随代码的地方定义的任何范围   处理程序可以存在。

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

1 个答案:

答案 0 :(得分:0)

我能够通过在EventManager中注册一个类处理程序来使它正常工作。 在FilterDataGrid类的公共构造函数中,输入以下代码:

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

考虑到FilterDataGrid和CheckedListBox都是自定义控件,我认为在两者之间建立硬链接是可以的(请随时告诉我潜在的陷阱,对于该控件的创作我还是很陌生)。