You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让WPF ListBox失去焦点后仍保持选中项高亮?

解决ListBoxItem在焦点移到外部TextBox后丢失高亮的问题

我明白你的问题了:当焦点在ListBox内部的TextBox时,对应的ListBoxItem会高亮,但一旦焦点移到外部的theTextBox,这个高亮就消失了。这是因为你原来用的IsKeyboardFocusWithin触发器只有当焦点处于ListBoxItem的范围内时才会生效,焦点移出去后这个属性就变成False了。下面给你一个简单有效的解决方案:

核心思路

我们可以利用ListBox的SelectedItem来跟踪“活动”的项:当内部TextBox获得焦点时,把对应的Item设为ListBox的SelectedItem,然后让ListBoxItem在IsSelected状态下保持高亮。这样即使焦点移到外部TextBox,只要SelectedItem没改变,高亮就会保留。

修改后的完整代码

XAML部分

<DockPanel>
    <ListBox x:Name="itemListBox" ItemsSource="{Binding Items}" DockPanel.Dock="Top" Height="100" KeyboardNavigation.TabNavigation="Cycle">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="IsTabStop" Value="False"/>
                <Setter Property="Focusable" Value="False"/>
                <!-- 默认样式 -->
                <Setter Property="Background" Value="Transparent"/>
                <Style.Triggers>
                    <!-- 当Item被选中时保持高亮 -->
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="LightGreen" />
                    </Trigger>
                    <!-- 联动焦点与选中状态:焦点在内部时自动选中 -->
                    <Trigger Property="IsKeyboardFocusWithin" Value="True">
                        <Setter Property="IsSelected" Value="True"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Name}"/>
                    <TextBox Text="{Binding Description}" GotKeyboardFocus="TextBox_GotKeyboardFocus"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <!-- 修正了Name属性的语法错误:把-改成= -->
    <TextBox Name="theTextBox" AcceptsReturn="True" />
</DockPanel>

C#后台代码

在你的窗口/UserControl的代码文件中添加以下事件处理方法:

private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    var textBox = sender as TextBox;
    if (textBox == null) return;
    
    // 获取TextBox绑定的Item对象
    var currentItem = textBox.DataContext as Item;
    if (currentItem != null)
    {
        // 将对应的Item设为ListBox的选中项
        itemListBox.SelectedItem = currentItem;
    }
}

关键说明

  1. 修正语法错误:把原XAML中Name-"theTextBox"的笔误改成了Name="theTextBox",避免控件无法被正常识别。
  2. 重构高亮逻辑:现在ListBoxItem的高亮由IsSelected属性驱动,只要Item处于选中状态,就会持续显示浅绿色背景,不受外部焦点影响。
  3. 焦点联动选中:通过IsKeyboardFocusWithin触发器,确保焦点进入内部TextBox时自动选中对应Item;同时在TextBox获得焦点的事件中手动同步选中状态,保证逻辑的一致性。
  4. 保留原有体验:KeyboardNavigation.TabNavigation="Cycle"的设置依然生效,你可以继续用Tab键在各个内部TextBox间循环导航。

这样修改后,即使焦点移到外部的theTextBox,之前选中的ListBoxItem仍然会保持高亮状态,完美解决你的问题!

内容的提问来源于stack exchange,提问作者hjyanghj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:17:17