简体   繁体   中英

WPF Selected ListBoxItem with custom border



I'm trying to create a ListBoxItem template, that will be with rounded border at selection. I got this xaml, which doesn't work on selection:

<ListBox x:Name="filtersListBox" Grid.Row="1" 
         Background="Transparent" BorderThickness="0"
         ItemsSource="{Binding FilterItems}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
            </Style.Resources>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid HorizontalAlignment="Center">
                <Border CornerRadius="8" BorderThickness="0" BorderBrush="Orange" 
                        Margin="2" Background="Transparent" Name="itemBorder"
                        Width="275" VerticalAlignment="Center"
                        FocusManager.IsFocusScope="True" Focusable="True">
                    <Border.Effect>
                        <DropShadowEffect BlurRadius="1" ShadowDepth="2" Color="DarkOrange" Opacity="0.3"/>
                    </Border.Effect>
                    <Border.Style>
                        <Style TargetType="Border">
                            <Style.Triggers>
                                <Trigger Property="UIElement.IsFocused" Value="True">
                                    <Setter Property="Background" Value="Blue"/>
                                </Trigger>
                                <EventTrigger RoutedEvent="Border.MouseEnter">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ThicknessAnimation Duration="0:0:0.25"
                                                                To="2"
                                                                Storyboard.TargetProperty="BorderThickness"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                                <EventTrigger RoutedEvent="Border.MouseLeave">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ThicknessAnimation Duration="0:0:0.25"
                                                                To="0"
                                                                Storyboard.TargetProperty="BorderThickness"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <TextBlock Text="{Binding Text}" Margin="10, 2"/>
                </Border>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

So this is the ListBox that I'm working on.
The MouseEnter and MouseLeave events, work great!
However, the trigger of UIElement.IsFocused is not working.

Any advice would be very appreciated! :)
Thanks, Alex.

This is so easy to do, I'm quite surprised that nobody suggested this yet. Either define two DataTemplate s or two ControlTemplate s, one for the default look and one for the selected look. Then just add this Style (this first example uses DataTemplate s):

<Style x:Key="SelectionStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

You would use it like this:

<ListBox ItemContainerStyle="{StaticResource SelectionStyle}" ... />

Here is the other example using two ControlTemplate s (used in the same way):

<Style x:Key="SelectionStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="Template" value="{StaticResource DefaultTemplate}" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="Template" value="{StaticResource SelectedTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

I'll leave you to define what you want the items to look like as you know that best. One last note... if you use this method (using ControlTemplate s), make sure that you add a ContentPresenter so that the content of the items will still be shown. See the Control.Template Property page on MSDN for an example.

Have you tried setting Focusable property to true. By default the propery is false.

Take a look at this link:

http://msdn.microsoft.com/en-us/library/system.windows.uielement.focusable%28v=vs.110%29.aspx

If that doesnt help then maybe this approach will fit you more.

<ListBox.Resources>
    <Style TargetType="{x:Type ListBoxItem}">
        <EventSetter Event="GotFocus" Handler="ListBoxItem_GotFocus"/>
        <EventSetter Event="LostFocus" Handler="ListBoxItem_LostFocus"/>
    </Style>
</ListBox.Resources>

Why dont you set the Template for ItemContainerStyle, then you can use the Trigger with property IsSelected = true. See code below:

<Window x:Class="WpfApplication7.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <collections:ArrayList  x:Key="StringArray">
        <system:String>Hei</system:String>
        <system:String>Hei</system:String>
        <system:String>Hei</system:String>
        <system:String>Hei</system:String>
    </collections:ArrayList>
</Window.Resources>
<Grid>
    <ListBox x:Name="filtersListBox" Grid.Row="1" 
     Background="Transparent" BorderThickness="0"
     ItemsSource="{StaticResource StringArray}">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <Border CornerRadius="8" BorderThickness="0" BorderBrush="Orange" 
                    Margin="2" Background="Transparent" Name="itemBorder"
                    Width="275" VerticalAlignment="Center"
                    FocusManager.IsFocusScope="True" Focusable="True">
                                <Border.Effect>
                                    <DropShadowEffect BlurRadius="1" ShadowDepth="2" Color="DarkOrange" Opacity="0.3"/>
                                </Border.Effect>
                                <ContentPresenter />
                            </Border>
                                    <ControlTemplate.Triggers>
                                        <Trigger Property="IsSelected" Value="True">
                                            <Setter TargetName="itemBorder" Property="Background" Value="Blue"></Setter>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
                </Style.Resources>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid HorizontalAlignment="Center">
                    <Border CornerRadius="8" BorderThickness="0" BorderBrush="Orange" 
                    Margin="2" Background="Transparent" Name="itemBorder"
                    Width="275" VerticalAlignment="Center"
                    FocusManager.IsFocusScope="True" Focusable="True">
                        <Border.Effect>
                            <DropShadowEffect BlurRadius="1" ShadowDepth="2" Color="DarkOrange" Opacity="0.3"/>
                        </Border.Effect>
                        <Border.Style>
                            <Style TargetType="Border">
                                <Style.Triggers>
                                    <Trigger Property="UIElement.IsFocused" Value="True">
                                        <Setter Property="Background" Value="Blue"/>
                                    </Trigger>
                                    <EventTrigger RoutedEvent="Border.MouseEnter">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <ThicknessAnimation Duration="0:0:0.25"
                                                            To="2"
                                                            Storyboard.TargetProperty="BorderThickness"/>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                    <EventTrigger RoutedEvent="Border.MouseLeave">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <ThicknessAnimation Duration="0:0:0.25"
                                                            To="0"
                                                            Storyboard.TargetProperty="BorderThickness"/>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </Style.Triggers>
                            </Style>
                        </Border.Style>
                        <TextBlock Text="{Binding }" Margin="10, 2"/>
                    </Border>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

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