user256890
user256890

Reputation: 3424

Customizing visualization of selection in a ListBox in WPF

I have a control with a ListBox like this:

<local:MyControl x:Name="LayoutRoot" ...>

  <local:MyControl.Resources>
    <ItemsPanelTemplate x:Key="myTemplate">
      <StackPanel Background="Yellow"/>
    </ItemsPanelTemplate>
  </local:MyControl.Resources>

  <Border>    
    ...
    <ListBox  ItemsPanel="{DynamicResource myTemplate}">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Rectangle Height="50" Width="200" Margin="10" Fill="Red"/>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
    ...
  </Border>
</local:MyControl>

This is how it looks like when I run it:

enter image description here

The ListBox paints a "frame" around each items based on their state:

I guess the "frame" is the visible part of the background of the ListBoxItem under the Margin of the Rectangle object, but I am not sure.

I would like to customize the look of the "frame"-s for each different state. Could you give me an example how to do that?

Upvotes: 2

Views: 1490

Answers (3)

GameAlchemist
GameAlchemist

Reputation: 19294

It is not a "frame" that you see, but just the result of the margin you set in your rectangle. Note that you should not set a rectangle as DataTemplate, otherwise you'll just see... rectangles in your list. Just use a border for this, in which you can put your content (using a < ContentControl Content={Binding} />)

To get your colours right, use a style into the ItemContainerStyle. The issue is that the triggers won't work in the 'IsSelected' case, due to the default template setting the Backgound color to Blue when selected with no chance of changing it. So you must redefine the template for that BackGround not to be seen, and define triggers inside that template. Your Style should look a little like that :

    <Style x:Key="myStyle" TargetType="ListBoxItem" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border Background="{TemplateBinding Background}">
                        <Border Background="Red"  Margin="10">
                            <ContentControl Content="{Binding}" />
                        </Border>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="Black" />
                        </Trigger>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="Red" />
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter Property="Background" Value="Orange" />
                        </Trigger>
                    </ControlTemplate.Triggers >
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

and you can now use this style in your ListBox with : ItemContainerStyle="{StaticResource myStyle}"

Beware that the order of your triggers change the resulting color : the last win (for an item which is both selected and mouseover for example)

Upvotes: 2

gprasant
gprasant

Reputation: 16043

If you are using Expression Blend, here is how to do it.

If you are not using Blend(like me,) i remember having a similar issue some time back and I was thinking that applying the Styles and Templates(the right way to do this) would be too much effort and I came up with this.

<Style TargetType="{x:Type ListViewItem}">
     <Style.Resources>
         <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#00000000"/>
         <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#00000000"/>
     </Style.Resources>
</Style>

Note that I am using ListView in place of ListBox.Just add this to your nearest resources block. In my case it was the <Window.Resources></Window.Resources> Also, feel free to experiment with the colors. I have tried something that does not do any hhighlighting whatsoever when an element is selected.

UPDATE: Even though I am using ListView here, I think this approach should work fine even for ListBox. This is because I have tried setting the properties on SystemColors object and not on ListView. Try this with your List Box control and post back if it works.

Upvotes: 2

Kent Boogaart
Kent Boogaart

Reputation: 178780

You can play with the ItemContainerStyle, which in this case applies to each ListBoxItem:

<ItemsControl ...>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <!-- go nuts here if you want -->
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

Of course, you may not need to alter the entire ListBoxItem template - it's unclear from your question what you're actually trying to achieve so I couldn't say. You may get away with just altering other properties that the default template leverages.

Upvotes: 1

Related Questions