WPF - Remove focus when clicking outside of a textbox

瘦欲@ 提交于 2019-11-28 05:23:49
love Computer science

Rather than adding new control to window, I think you should give your Grid a name and react to the MouseDown event on your window, moving the focus to the Grid itself. Something like this:

<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>

code behind:

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

I think, better way to solve this problem is adding MouseDown event handler to window with code behind:

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

Another way that worked for me was using

Mouse.AddPreviewMouseDownOutsideCapturedElementHandler

For example, say you had a TextBlock that when clicked, should become editable by showing a focused TextBox. Then when the user clicked outside the TextBox, it should be hidden again. Here's how you can do it:

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;
}

To avoid code behind you can use this Behavior The behavior

 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;
    }
}

Useing in XAML:

On any element outside the text box that you want him to clear the focus on click add:

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

I'm not 100% sure, but if you set Focusable to true on the container element (Grid, StackPanel, etc) then it should take the focus away from the text box.

If you clicked on the element, which can grab the focus, you get what you need. if, for example, you have some panel, you can handle panel's mouseClick event to achive your needs, or use Richard Szalay advice.

Kristofer Escobar

I was running into a similar issue, but when I wrapped a ScrollViewer control around my textboxes , all the textboxes would automatically lose focus when clicking anywhere outside the texboxes.

you cant explicitly loose the focus of a control

you can set the focus to other control instead

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

try this

You can use the IsKeyboardFocusedChanged event:

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
    }
}    

I have tried the selected answer in react native WPF application but it was not triggering lost focus of textbox due to which textbox was not losing the focus. Following solution work for me.

Bound a mouse-down event to Window:

<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>

and event is:

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);
    }
}
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;
    }
}

Using in XAML:

<TextBox Height="30" Width="200">
            <i:Interaction.Behaviors>
                <behaviours:ClearFocusOnOutsideClickBehavior/>
            </i:Interaction.Behaviors>
 </TextBox>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!