简体   繁体   中英

WPF Custom Control: changing additional template defaults

With a ListBox , I can "Edit a copy..." of the control's template and the template for a generated item container (which styles a ListBoxItem ) independently - the relevant default style gets copied out wherever I want it and I'm good to go.

I've created a custom control derived from ListBox and modified the defaults of both these templates and put them in Themes/Generic.xaml . Unfortunately, the only way I can find to get the item container style to apply when the custom control is used is by making it a setter on the main style:

<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>

What I want is to have them separate, so the style for the ListBoxItem is not included when I edit a copy of the default control template:

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

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

Is there any way I can get my control to pick up a separate style for its ListBoxItem from Generic.xaml ?

Edit

A custom control needs to be told to look for default styling information. This is done in its static constructor by setting the default value for the dependency property responsible:

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

We can't change it for ListBoxItem , unfortunately, because a) it would presumably affect all ListBoxItem s and b) an attempt causes an exception (because it's already set).

One avenue might be to create a DerivedListBoxItem and apply default styling in the same manner as DerivedListBox . The questions then become:

  1. Where is ListBox told to use ListBoxItem s (the template just has an ItemsPresenter element)?
  2. What is the appropriate technique to replace it with a DerivedListBoxItem ?
  3. Is this likely to cause any undesirable side effects for consumers of the control?

Further Edit...

It seems there is an attribute on ListBox that sets the type of style accepted for ItemContainerStyle and a protected method that generates new Items:

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

Unfortunately, this appears not to be the whole story. I've changed / overridden both to reference DerivedListBoxItem but the styling is not applied and attempting to edit either an empty version or a copy of the existing version of the ItemContainerStyle results in the error, "Copy Style failed".

Why don't you provide Key to each style template and then use it separately?

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

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

then use it like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM