Search code examples
wpflistboxselecteditemmultidatatrigger

ListBox expand selected item


I have the following code snippet (copy and paste into kaxaml, xamlpad, etc to try it) that collapses all but the selected item. However, I want to revert back to all visible when the mouse is not over the ListBox and I just cannot get it to work short of going code behind. I am using the IsMouseOver ListBox property to set selected item properties on the ListBox to attempt to trigger an update but no luck. Any ideas?

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid> <ListBox Name="lb" Width="100" Height="100" Background="Red" SelectionMode="Single"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <UniformGrid Columns="1"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBoxItem Background="AliceBlue">Item 1 </ListBoxItem> <ListBoxItem Background="Aquamarine">Item </ListBoxItem> <ListBoxItem Background="Azure">Item </ListBoxItem> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="Visibility" Value="Visible"/> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="False"/> <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}},Path=SelectedItems.Count}" Value="1"/> </MultiDataTrigger.Conditions> <MultiDataTrigger.EnterActions> <BeginStoryboard> <Storyboard Duration="0:0:1"> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Collapsed}"/> </ObjectAnimationUsingKeyFrames> <DoubleAnimation Duration="0:0:1" Storyboard.TargetProperty="Opacity" To="0"/> </Storyboard> </BeginStoryboard> </MultiDataTrigger.EnterActions> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True"/> <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}},Path=SelectedItems.Count}" Value="1"/> </MultiDataTrigger.Conditions> <MultiDataTrigger.EnterActions> <BeginStoryboard> <Storyboard Duration="0:0:0"> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/> </ObjectAnimationUsingKeyFrames> <DoubleAnimation Duration="0:0:0" Storyboard.TargetProperty="Opacity" To="1"/> </Storyboard> </BeginStoryboard> </MultiDataTrigger.EnterActions> </MultiDataTrigger> </Style.Triggers> </Style> </ListBox.ItemContainerStyle> <ListBox.Style> <Style> <Style.Triggers> <Trigger Property="ListBox.IsMouseOver" Value="False"> <Setter Property="ListBox.SelectedItem" Value="{x:Null}"/> <Setter Property="ListBoxItem.IsSelected" Value="False"/> <Setter Property="ListBox.SelectedIndex" Value="-1"/> </Trigger> <EventTrigger RoutedEvent="Mouse.MouseLeave"> <BeginStoryboard> <Storyboard> <Int32Animation Duration="0:0:0" Storyboard.TargetProperty="SelectedIndex" To="-1"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Style.Triggers> </Style> </ListBox.Style> </ListBox> </Grid> </Page>


Solution

  • Move your style to resources and apply it when the mouse is over the ListBox.`

    <Page.Resources>
        <Style x:Key="CustomStyle" TargetType="{x:Type ListBoxItem}">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="False"/>
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}},Path=SelectedItems.Count}" Value="1"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard Duration="0:0:1">
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Collapsed}"/>
                                </ObjectAnimationUsingKeyFrames>
                                <DoubleAnimation Duration="0:0:1" Storyboard.TargetProperty="Opacity" To="0"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>
                    <MultiDataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard Duration="0:0:0">
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
                                </ObjectAnimationUsingKeyFrames>
                                <DoubleAnimation Duration="0:0:0" Storyboard.TargetProperty="Opacity" To="1"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.ExitActions>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </Page.Resources>
    
    <Grid>
        <ListBox
           Name="lb"
           Width="100"
           Height="100"
           Background="Red"
           SelectionMode="Single">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="1"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBoxItem Background="AliceBlue">Item 1
            </ListBoxItem>
            <ListBoxItem Background="Aquamarine">Item
            </ListBoxItem>
            <ListBoxItem Background="Azure">Item
            </ListBoxItem>
            <ListBox.Style>
                <Style>
                    <Style.Triggers>
                        <Trigger Property="ListBox.IsMouseOver" Value="True">
                            <Setter 
                                Property="ListBox.ItemContainerStyle" 
                                Value="{StaticResource CustomStyle}"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.Style>
        </ListBox>
    </Grid>
    

    ` Also note the usage of the MultiDataTrigger.ExitActions, these are the actions to apply when the trigger object becomes inactive.