ListBox.ItemTemplate 內含 TextBox 等可聚焦控件時,滑鼠點擊項目內的控件,ListBoxItem 不會自動被選取(焦點被子控件捕獲),導致焦點與選取狀態不一致。
雖可在 PreviewMouseDown 強制選取,但會提前觸發 LostFocus 破壞驗證邏輯(驗證通常在 LostFocus 執行)。
於項目容器(TextBox)取得焦點時,向上尋找視覺樹中的 ListBoxItem 並設定 IsSelected = true。
public static class ListBoxService
{
public static readonly DependencyProperty AutoSelectProperty =
DependencyProperty.RegisterAttached("AutoSelect", typeof(bool), typeof(ListBoxService),
new PropertyMetadata(OnAutoSelectChanged));
private static void OnAutoSelectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is UIElement element)
{
if ((bool)e.NewValue) element.GotFocus += OnElementGotFocus;
else element.GotFocus -= OnElementGotFocus;
}
}
private static void OnElementGotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is DependencyObject src)
{
var item = src.FindAncestor<ListBoxItem>();
if (item != null) item.IsSelected = true;
}
}
}
// FindAncestor 擴充方法略(視覺樹向上搜尋)
<Application.Resources>
<Style TargetType="{x:Type ListBox}">
<Setter Property="local:ListBoxService.AutoSelect" Value="True" />
</Style>
</Application.Resources>
零侵入式套用至全專案所有 ListBox,解決焦點與選取不同步問題,且不干擾驗證流程。