WPF - 单击文本框外部时删除焦点

时间:2011-06-27 05:46:16

标签: c# wpf focus click

我有一些文本框,我希望专注于与WPF应用程序的正常行为略有不同。基本上,我希望他们的行为更像是网页上的文本框行为。也就是说,如果我点击文本框外的任何地方,它将失去焦点。这样做的最佳方式是什么?

如果答案是以编程方式移除焦点,那么在边界外检测鼠标点击的最佳方法是什么?如果我点击的元素将成为焦点的新接收者,该怎么办?

13 个答案:

答案 0 :(得分:27)

我认为你应该给你的 Grid 一个名字并对你窗口上的 MouseDown 事件做出反应,将焦点移到< strong>网格本身。像这样:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="412" Width="569" MouseDown="Window_MouseDown" Name="window1" >
    <Grid ShowGridLines="False" KeyDown="Grid_KeyDown" Name="grid1" Focusable="True">
          <TextBox HorizontalAlignment="Left" Margin="117,61,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
    </Grid>
</Window>
代码背后的代码:

private void window1_MouseDown(object sender, MouseButtonEventArgs e)
{
    grid1.Focus();
}

答案 1 :(得分:13)

我认为,解决此问题的更好方法是将MouseDown事件处理程序添加到窗口,后面带有代码:

private void window_MouseDown(object sender, MouseButtonEventArgs e)
{
    Keyboard.ClearFocus();
}

答案 2 :(得分:3)

另一种对我有用的方法是使用

Mouse.AddPreviewMouseDownOutsideCapturedElementHandler

例如,假设你有一个TextBlock,当点击时,它应该通过显示一个聚焦的TextBox变得可编辑。然后,当用户在TextBox外部单击时,应该再次隐藏它。这是你如何做到的:

private void YourTextBlock_OnMouseDown(object sender, MouseButtonEventArgs e)
{
    YourTextBox.Visibility = Visibility.Visible;
    YourTextBox.Focus();
    CaptureMouse();
    Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideElement);
}

private void OnMouseDownOutsideElement(object sender, MouseButtonEventArgs e)
{
    Mouse.RemovePreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideElement);
    ReleaseMouseCapture();
    YourTextBox.Visibility = Visibility.Hidden;
}

答案 3 :(得分:3)

为避免代码落后,您可以使用此行为 行为

 public class ClearFocusOnClickBehavior : Behavior<FrameworkElement>
 {
    protected override void OnAttached()
    {
        AssociatedObject.MouseDown += AssociatedObject_MouseDown;
        base.OnAttached();
    }

    private static void AssociatedObject_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        Keyboard.ClearFocus();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseDown -= AssociatedObject_MouseDown;
    }
}

在XAML中使用:

在文本框之外您希望他清除焦点的任何元素上,单击添加:

    <i:Interaction.Behaviors>
        <behaviors:ClearFocusOnClickBehavior/>
    </i:Interaction.Behaviors>

答案 4 :(得分:2)

我不是百分百肯定,但是如果你在容器元素(Grid,StackPanel等)上将Focusable设置为true,那么它应该将焦点从文本框中移开。

答案 5 :(得分:1)

如果你点击了可以抓住焦点的元素,你就可以得到你需要的东西。例如,如果你有一些面板,你可以处理面板的mouseClick事件以满足你的需求,或者使用Richard Szalay的建议。

答案 6 :(得分:1)

重要的是要提到一个文本框同时捕获了鼠标和键盘事件,因此,要从文本框中移动或移出焦点,必须释放这两个元素。

让我们从键盘开始,Keyboard.ClearFocus();将从文本框中删除键盘焦点,这对于隐藏闪烁的光标非常有用,但不会将焦点从文本框中移开,换句话说,文本框将保留作为焦点元素,但不显示光标。 您可以通过在FocusManager.GetFocusedElement(this);之后打印Keyboard.ClearFocus();进行检查。

因此,如果在文本框上附加了LostFocus事件或类似事件,则该事件将不会被触发,因为该元素尚未失去焦点。

PreviewMouseDown += (s, e) => FocusManager.SetFocusedElement(this, null);
PreviewMouseDown += (s, e) => Keyboard.ClearFocus();

作为解决方案,应通过调用以下命令将Window集中的元素设置为null: System.Windows.Input.FocusManager.SetFocusedElement(this, null);现在,如果您想知道是否可以摆脱Keyboard.ClearFocus();,那么答案是否定的,因为我们将删除鼠标焦点,但键盘焦点仍然存在。 (您会注意到闪烁的光标仍然存在,并且可以在文本框中键入一些文本。)

答案 7 :(得分:0)

你无法明确地忽略控件的焦点

您可以将焦点设置为其他控件

**txt.Focusable=true;
label.focus();
Keyboard.Focus(txtPassword);**

试试这个

答案 8 :(得分:0)

我遇到了类似的问题,但当我将文本框包裹在ScrollViewer控件周围时,所有文本框在点击texbox之外的任何地方时都会自动失去焦点。

答案 9 :(得分:0)

您可以使用IsKeyboardFocusedChanged事件:

myTextBox.IsKeyboardFocusedChanged += myTextBox_IsKeyboardFocusedChanged;

private void SendFileCaptionTextBox_IsKeyboardFocusedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue.ToString() == "True")
    {
        // it's focused
    }
    else
    {
        // it's not focused
    }
}    

答案 10 :(得分:0)

我已经在React Native WPF应用程序中尝试了选定的答案,但是由于该文本框没有失去焦点,它没有触发失去文本框的焦点。以下解决方案对我有用。

将鼠标按下事件绑定到窗口:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="412" Width="569" MouseDown="window_MouseDown" Name="window1" >
    <Grid ShowGridLines="False" KeyDown="Grid_KeyDown" Name="grid1" Focusable="True">
          <TextBox HorizontalAlignment="Left" Margin="117,61,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
    </Grid>
</Window>

事件是:

private void window_MouseDown(object sender, MouseButtonEventArgs e)
{
    TextBox textBox = Keyboard.FocusedElement as TextBox;
    if (textBox != null)
    {
        TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next);
        textBox.MoveFocus(tRequest);
    }
}

答案 11 :(得分:0)

public class ClearFocusOnOutsideClickBehavior : Behavior<FrameworkElement>
{
    protected override void OnAttached()
    {

        AssociatedObject.GotFocus += AssociatedObjectOnGotFocus;
        AssociatedObject.LostFocus += AssociatedObjectOnLostFocus;
        base.OnAttached();
    }

    private void AssociatedObjectOnLostFocus(object sender, RoutedEventArgs e)
    {
        App.Current.MainWindow.MouseUp -= _paren_PreviewMouseUp;
    }

    private void AssociatedObjectOnGotFocus(object sender, RoutedEventArgs e)
    {
        App.Current.MainWindow.MouseUp += _paren_PreviewMouseUp;
    }

    private void _paren_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        Keyboard.ClearFocus();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.GotFocus -= AssociatedObjectOnGotFocus;
        AssociatedObject.LostFocus -= AssociatedObjectOnLostFocus;
    }
}

在XAML中使用:

<TextBox Height="30" Width="200">
            <i:Interaction.Behaviors>
                <behaviours:ClearFocusOnOutsideClickBehavior/>
            </i:Interaction.Behaviors>
 </TextBox>

答案 12 :(得分:0)

您可以在应用启动时将<head>注册到App.xaml.cs中的每种元素。

PreviewMouseLeftButtonDownEvent