Select ListBoxItem if TextBox in ItemTemplate gets focus

£可爱£侵袭症+ 提交于 2019-11-27 09:17:18
mg007

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).

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>

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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!