功能说明
一个用于 WPF TextBox 的附加行为,实现 TextBox 与 Popup 控件的联动效果:
-
自动弹出/关闭:
- TextBox 获得焦点时自动打开关联的 Popup
- TextBox 失去焦点时自动关闭关联的 Popup
-
点击外部关闭:
- 点击 TextBox 和 Popup 外部区域时关闭 Popup
-
焦点状态处理:
- 解决 TextBox 保持焦点但 Popup 关闭后的重新触发问题
核心代码解析
// 解决在 TextBox 外其他地方点击时,仅关闭 Popup,但是 TextBox 还是 Focused 状态,导致再点击进来时不会触发弹出 Popup
private void AssociatedObject_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
if (AssociatedObject?.IsFocused == true && Popup != null && !Popup.IsOpen) {
Popup.IsOpen = true;
}
}
private void Window_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
if (Popup == null || !Popup.IsOpen || AssociatedObject == null || _parentWindow == null) { return; }
Point position = e.GetPosition(null);
Rect textBoxRect = new Rect(AssociatedObject.TranslatePoint(new Point(0, 0), _parentWindow), AssociatedObject.RenderSize);
Rect popupRect = new Rect(Popup.TranslatePoint(new Point(0, 0), _parentWindow), Popup.RenderSize);
if (!textBoxRect.Contains(position) && !popupRect.Contains(position)) {
Popup.SetCurrentValue(Popup.IsOpenProperty, false);
}
}
使用方法
<TextBox x:Name="SearchBox"
Width="400"
Height="30"
Text="{Binding ElementName=list, Path=SelectedItem.Content}">
<hc:Interaction.Behaviors>
<controls:TextBoxPopupBehavior Popup="{Binding ElementName=SuggestionsPopup}" />
</hc:Interaction.Behaviors>
</TextBox>
<Popup x:Name="SuggestionsPopup"
Placement="Bottom"
PlacementTarget="{Binding ElementName=SearchBox}"
StaysOpen="True">
<Border Background="White"
BorderBrush="Gray"
BorderThickness="1">
<ListBox x:Name="list"
Width="200"
Height="150">
<ListBoxItem>选项1</ListBoxItem>
<ListBoxItem>选项2</ListBoxItem>
<ListBoxItem>选项3</ListBoxItem>
</ListBox>
</Border>
</Popup>
注意事项
- 确保 Popup 的 PlacementTarget 正确绑定
- 在 MVVM 模式下可通过绑定设置 Popup 属性
- 控件卸载时会自动清理事件监听