Select ListBoxItem if TextBox in ItemTemplate gets focus Select ListBoxItem if TextBox in ItemTemplate gets focus wpf wpf

Select ListBoxItem if TextBox in ItemTemplate gets focus


You can trigger on the property IsKeyboardFocusWithin in the ItemContainerStyle and set IsSelected to true.

<ListBox.ItemContainerStyle>    <Style TargetType="{x:Type ListBoxItem}">        <Style.Triggers>            <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True">                <DataTrigger.EnterActions>                    <BeginStoryboard>                        <Storyboard>                            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(ListBoxItem.IsSelected)">                                <DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>                            </BooleanAnimationUsingKeyFrames>                        </Storyboard>                    </BeginStoryboard>                </DataTrigger.EnterActions>            </DataTrigger>        </Style.Triggers>    </Style></ListBox.ItemContainerStyle>

You could also use a Setter instead of a single frame animation but then the selection will be lost again once the focus leaves the ListBox:

<ListBox.ItemContainerStyle>    <Style TargetType="{x:Type ListBoxItem}">        <Style.Triggers>            <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True">                <Setter Property="IsSelected" Value="True"/>            </DataTrigger>        </Style.Triggers>    </Style></ListBox.ItemContainerStyle>


If you have multiple instance of ListBox then you may consider using your custom listbox (by deriving it from ListBox). See the explanation here.


Or, use this hack if you have only 1 (or only small number of) such ListBox and don't want to create a separate class for that:

<TextBox x:Name="TextBoxInsideListBoxItemTemplate" ... >    <TextBox.Style>        <Style TargetType="{x:Type TextBox}">            <Setter Property="IsHitTestVisible" Value="False" />            <Style.Triggers>                <DataTrigger                        Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor,                     AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}"                        Value="True">                    <Setter Property="IsHitTestVisible" Value="True" />                </DataTrigger>            </Style.Triggers>        </Style>    </TextBox.Style></TextBox>

Note that you'll have to click once again to edit text in the TextBox (which is actually cool according to me).


I had a situation where the selection of a listbox item would change its layout, so the control might have moved away from the cursor before the mouse button is released. I have found no better solution than to use a slight delay in the Storyboard if I want to keep everything in xaml.

More importantly, GotKeyboardFocus seems to work better than IsKeyboardFocusWithin for repeated selections.

<EventTrigger RoutedEvent="GotKeyboardFocus">    <BeginStoryboard>        <Storyboard>            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">                <DiscreteBooleanKeyFrame KeyTime="00:00:00.3" Value="True"/>            </BooleanAnimationUsingKeyFrames>        </Storyboard>    </BeginStoryboard></EventTrigger>