我已经创建了一个列表框控件,并且重新定义了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文件中指定事件处理程序,该如何设置它。
答案 0 :(得分:0)
我能够通过在EventManager中注册一个类处理程序来使它正常工作。 在FilterDataGrid类的公共构造函数中,输入以下代码:
EventManager.RegisterClassHandler(typeof(FilterDataGrid), CheckedListBox.RefreshDataSetEvent, new CheckedListBox.RefreshDataSetEventHandler(FilterDataGridRefreshEventHandler));
考虑到FilterDataGrid和CheckedListBox都是自定义控件,我认为在两者之间建立硬链接是可以的(请随时告诉我潜在的陷阱,对于该控件的创作我还是很陌生)。