WPF自定义控件:更改其他模板默认值

时间:2015-07-02 09:12:18

标签: .net wpf xaml wpf-controls

使用ListBox,我可以“编辑副本...”控件的模板和生成的项容器的模板(样式ListBoxItem)独立 - 相关的默认样式获取在任何我想要的地方复制出去,我很高兴。

我已经创建了一个源自ListBox的自定义控件,并修改了这两个模板的默认值并将它们放在Themes/Generic.xaml中。不幸的是,在使用自定义控件时,我能找到让项目容器样式应用的唯一方法是使其成为主样式的setter:

<Sty1e TargetType="{x:Type local:DerivedListBox}">
    <Setter Property="Template">...</Setter>

    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Sty1e TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">...</Setter>
            </Style>
        </Setter.Value>
    </Setter>

</Style>

想要的是将它们分开,因此当我编辑默认控件模板的副本时,不包括ListBoxItem的样式:

<Sty1e TargetType="{x:Type local:DerivedListBox}">
    <Setter Property="Template">...</Setter>
</Style>

<Sty1e TargetType="{x:Type ListBoxItem}">
    <Setter Property="Template">...</Setter>
</Style>

有什么方法可以让我控制从ListBoxItemGeneric.xaml提取单独的样式吗?

修改

需要告知自定义控件以查找默认样式信息。这是通过设置负责依赖项属性的默认值在其静态构造函数中完成的:

DefaultStyleKeyProperty.OverrideMetadata(typeof(DerivedListBox), new FrameworkPropertyMetadata(typeof(DerivedListBox)));

不幸的是,我们无法为ListBoxItem更改它,因为a)它可能会影响所有ListBoxItem和b)尝试会导致异常(因为它已经设置)。

一种途径可能是创建DerivedListBoxItem并以与DerivedListBox相同的方式应用默认样式。然后问题变成:

  1. ListBox在哪里被告知使用ListBoxItem s( 模板只有一个ItemsPresenter元素?)
  2. DerivedListBoxItem替换它的适当技巧是什么?
  3. 这是否可能对控件的消费者造成任何不良副作用?
  4. 进一步编辑......

    似乎ListBox上有一个属性设置了ItemContainerStyle接受的样式类型以及生成新项目的受保护方法:

    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(ListBoxItem))]
    public class ListBox : Selector
    {
      ...
      protected override DependencyObject GetContainerForItemOverride()
      {
        return new ListBoxItem();
      }
    

    不幸的是,这似乎不是全部。我已更改/覆盖两者以引用DerivedListBoxItem但未应用样式并尝试编辑空ItemContainerStyle的现有版本的空版本或副本导致错误,“复制样式失败”。

1 个答案:

答案 0 :(得分:0)

为什么不为每个样式模板提供Key,然后单独使用它?

 <Style TargetType="{x:Type local:DerivedListBox}" x:Key="customListBoxStyleKey">
    <Setter Property="Template">...</Setter>
</Style>

<ItemTemplate  x:Key="customListBoxItemStyleKey">
   ...
</ItemTemplate>

然后像这样使用它:

<local:DerivedListBox Style="{StaticResource customListBoxStyleKey}"
                      Itemtemplate="{StaticResource customListBoxItemStyleKey}">
</local:DerivedListBox>