stumpf
stumpf

Reputation: 11

How to draw a ListBoxItem Border over the ListBox Border in WPF?

I want to design a ListBox in a way that it looks like the selected item is highlighted outside the ListBox. The ListBox has a border with 1px. The ListBoxItem has a border with "0 0 0 1" and a highlight color when IsSelected is true.

When an item is selected its border on the right should be drawn over the border of the ListBox.

Here is an image demonstrating how it should look:

enter image description here

I tried to work with margins of the ListBox and ListBoxItem but the border of the ListBoxItem is cut off when reaching the border of the ListBox.

Is there a way to draw the ListBoxItems border over the ListBox's border?

Upvotes: 0

Views: 609

Answers (1)

Corentin Pane
Corentin Pane

Reputation: 4943

You could re-template both the ListBox (to have better control over margins etc) and the ListBoxItem to define the BorderBrush based on the IsSelected property.

"its border on the right should be drawn over the border of the ListBox"

Well, you can work around this issue by not having a right Border at all for the ListBox. You could let each ListBoxItem be responsible for its right Border color. The ListBox in itself would look like this, without right Border:

listbox without right border

Now you only need to add a right Border on each ListBoxItem.

I ended up adding a Margin="1 0 0 0" adjustment in the inner ItemsPresenter to make the overall appearance smoother.

<ListBox HorizontalAlignment="Left"
         VerticalAlignment="Top"
         Background="LightGray"
         BorderThickness="5 5 0 5"
         BorderBrush="Black">
    <ListBox.Template>
        <ControlTemplate TargetType="ListBox">
            <Border BorderThickness="{TemplateBinding BorderThickness}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    Background="{TemplateBinding Background}">
                <ItemsPresenter Margin="1 0 0 0"/>
            </Border>
        </ControlTemplate>
    </ListBox.Template>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Border BorderThickness="0 0 5 0" Padding="5">
                            <ContentPresenter/>
                            <Border.Style>
                                <Style TargetType="Border">
                                    <Setter Property="BorderBrush" Value="Black"/>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}" Value="True">
                                            <Setter Property="BorderBrush" Value="Blue"/>
                                            <Setter Property="Control.Foreground" Value="Blue"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Border.Style>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBoxItem Content="Item1"/>
    <ListBoxItem Content="Item2"/>
    <ListBoxItem Content="Item3"/>
</ListBox>

Final look:

screen capture of middle element selected

You would have to add a lot of styling to achieve the full result but that's a way you could go.

Upvotes: 2

Related Questions