tags:

views:

223

answers:

4

This question is inspired by this recent question and other situations I've encountered in my WPF development. How do I know whether it is enough to set a style on a control to override some default behavior vs creating a new control template?

More concretely, in the question above, the author wants to change the look of a ListBoxItem when it is selected. (See code reprinted below). Everything works, except the Background property. How is one supposed to know that they should override the Control Template for this?

<Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="Content" Value="{Binding Path=Name}"/>
        <Setter Property="Margin" Value="2"/>
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="FontWeight" Value="Bold"/>
                <Setter Property="FontSize" Value="18"/>
                <Setter Property="Background" Value="Yellow"/>
                <Setter Property="Foreground" Value="Red"/>
            </Trigger>
        </Style.Triggers>

    </Style>
+3  A: 

Hi siz

Styles can be thought of very closely to CSS styles in HTML. If all you want to do is change the basic properties of a control such as Background, Foreground or whatever properties it exposes then a Style is exactly what you need. Styles also allow you to apply triggers so for animations, a style is also sufficient.

If you're finding you want to change the intrinsice behaviours / inner workings on a control then a control template is what you want. For example, if you want to change how a button is laid out by adding some sort of grid behaviour, then using a control template is the way forward.

Ray Booysen
Ok that I understand. But take a look at the question I linked to. He wants to change the behavior of a ListBoxItem when it is selected (IsSelected property is set to true). He can do everything, BUT, he cannot change the Background. So... how does one know how to change this specific property?
siz
A: 

Unfortunately, for your specific example, you don't know unless you try it. Basically you first try it with a Style....and if that doesn't work for whatever reason, then you write a ControlTemplate. You usually only end up writing ControlTemplates for the reasons Ray mentioned.

My guess is that the trigger you're trying to set has also been hardcoded in the ControlTemplate...which is bad design imo because it prevents the Style from overriding it.

Bubblewrap
A: 

By "Background" I take it to mean the "blue" rectangle that surrounds the ListBoxItem when it is selected?

This is actually the FocusVisualStyle property, which is a style that describes what the item should look like when it is focused. The Control explicitly sets this property (described here), so in order to override it, you will have to redefine the Control Template, making sure to use a default Style setter to set it to {x:Null}.

KP Adrian
+5  A: 

As to whether to use a style or template Ray provided a great response.

As to how to solve your problem without creating a template, maybe I can help.

The background color is being set by the SystemColors. Using Blend and creating a template you can see the exact xaml.

So if NO TEMPLATES! is a requirement you can always change what that resource is.

Example :

    <ListBox>  
        <ListBox.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
                             Color="Yellow" />

            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Content" Value="{Binding Path=Name}"/>
                <Setter Property="Margin" Value="2"/>
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="FontWeight" Value="Bold"/>
                        <Setter Property="FontSize" Value="18"/>                            
                        <Setter Property="Foreground" Value="Red"/>
                    </Trigger>
                </Style.Triggers>

            </Style>

        </ListBox.Resources>

        <ListBoxItem>Test 1</ListBoxItem>
        <ListBoxItem>Test 2</ListBoxItem>
        <ListBoxItem>Test 3</ListBoxItem>
    </ListBox>

That will give you the background color for that given ListBox and not screw up anything else in the app.

JB
Not exactly what I was looking for; but a great answer. +1.
siz