WPF中实现强制TextBox失去焦点

3,257 阅读1分钟

为建立中文知识库加块砖        ——中科大胡不归

问题描述

WPF 添加 TextBox 输入时,常希望输入完后,点击文本框外输入立即生效。

原生的 TextBox 似乎没有这样的功能,所以找到如下方式来曲线实现前述效果,即通过强制使 TextBox 失去焦点实现。

目前还没找到其他更优雅的方法。

解决办法

  1. 添加不可见的 TextBox 用来接收焦点,并增加 MouseDown 事件用来响应鼠标点击。
<Window x:Class="Kavand.WpfTextBoxStyle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <!-- 不可见的TextBox -->
        <TextBox x:Name="FocusHolder" Width="0"/>
        <ScrollViewer MouseDown="UIElement_OnMouseDown">
            <StackPanel>
                <WrapPanel>
                    <TextBox Style="{DynamicResource SimpleTextBox}" Text="My text...Top"/>
                </WrapPanel>
                
                <!-- PlaceHolder -->
                <Canvas Height="300"></Canvas>
                <WrapPanel>
                    <TextBox Style="{DynamicResource SimpleTextBox}" Text="My text...Center"/>
                </WrapPanel>
                
                <!-- PlaceHolder -->
                <Canvas Height="300"></Canvas>
                <WrapPanel>
                    <TextBox Style="{DynamicResource SimpleTextBox}" Text="My text...Bottom"/>
                </WrapPanel>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Window>

采用Grid布局可以避免在类似 ScrollViewer 的长布局中,FocusHolder 获得焦点后,页面会跳转到 FocusHolder 处。

  1. 当鼠标点击到正在的编辑的 TextBox 外部时,触发 MouseDown 事件,我们在事件中使前面的 TextBox 失去焦点
    public partial class MainWindow {
        public MainWindow() {
            InitializeComponent();
        }

        private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            //FocusHolder获得焦点将使正在编辑的 TextBox 失去焦点
            FocusHolder.Focus();
        }
    }

效果如下:

参考文章

  1. WPF中textbox强制失去焦点
  2. wpf-如何实现文本框外部单击时移除焦点?