问题
I have some textboxes where I would like focus to behave a little differently than normal for a WPF application. Basically, I would like them to behave more like a textbox behaves on a webpage. That is, if I click anywhere outside of the textbox, it will lose its focus. What is the best way to do so?
If the answer is to programmatically remove focus, what is the best way to detect a Mouseclick outside of the bounds? What if the element I'm clicking on will be the new recipient of focus?
回答1:
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"
Background="#01FFFFFF"
KeyDown="Grid_KeyDown"
Name="grid1"
Focusable="True">
<TextBox Width="120" Margin="117,61,0,0"
Name="textBox1"
VerticalAlignment="Top"
HorizontalAlignment="Left"/>
</Grid>
</Window>
code behind:
private void window1_MouseDown(object sender, MouseButtonEventArgs e)
{
grid1.Focus();
}
回答2:
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();
}
回答3:
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;
}
回答4:
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>
回答5:
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.
回答6:
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.
回答7:
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.
回答8:
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
回答9:
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
}
}
回答10:
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);
}
}
回答11:
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>
来源:https://stackoverflow.com/questions/6489032/wpf-remove-focus-when-clicking-outside-of-a-textbox