我有一些文本框,希望WPF应用程序中的焦点行为与正常行为略有不同。基本上,我希望它们的行为更像网页上的文本框。也就是说,如果我在文本框之外的任何地方单击,它将失去焦点。最好的方法是什么?
如果答案是通过编程方式删除焦点,那么检测范围之外的鼠标单击的最佳方法是什么?如果我点击的元素将成为新的焦点接收者怎么办?
我有一些文本框,希望WPF应用程序中的焦点行为与正常行为略有不同。基本上,我希望它们的行为更像网页上的文本框。也就是说,如果我在文本框之外的任何地方单击,它将失去焦点。最好的方法是什么?
如果答案是通过编程方式删除焦点,那么检测范围之外的鼠标单击的最佳方法是什么?如果我点击的元素将成为新的焦点接收者怎么办?
与其向窗口添加新控件,我认为你应该给你的 Grid 命名,并在窗口上响应 MouseDown 事件,将焦点移动到 Grid 本身。类似于这样:
<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>
后端代码:
private void window1_MouseDown(object sender, MouseButtonEventArgs e)
{
grid1.Focus();
}
Background="Transparent"
,事件将会被触发。 - birgersp我的想法是,更好的解决此问题的方法是在窗口中添加MouseDown事件处理程序,代码如下:
private void window_MouseDown(object sender, MouseButtonEventArgs e)
{
Keyboard.ClearFocus();
}
Keyboard.FocusedElement
,然后执行element.RaiseEvent(new RoutedEventArgs(UIElement.LostFocusEvent))
来绕过这个问题 - 我不得不这样做,因为我的文本框的边框取决于焦点状态。 - Brandon Hood 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>
我发现另一种方法是使用Mouse.AddPreviewMouseDownOutsideCapturedElementHandler
比如,假设你有一个元素,当用户点击它时,应该出现聚焦的元素,以实现编辑功能。当用户再次在外面单击时,这个将被隐藏。以下是实现的代码:
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;
}
YourTextBlock_OnMouseDown
中使用MessageBox.Show
才能正常工作。 CaptureMouse
返回true,OnMouseDownOutsideElement
将不会被调用。 - Meow Cat 2012需要注意的是,文本框可以捕获鼠标和键盘事件,因此为了移动或删除文本框的焦点,必须释放这两个元素。
首先来说键盘,Keyboard.ClearFocus();
将从文本框中移除键盘焦点,并且它可以很好地隐藏闪烁的光标,但不会移动文本框的焦点,换句话说,文本框仍然保持为焦点元素,但没有显示光标。您可以在Keyboard.ClearFocus();
之后打印FocusManager.GetFocusedElement(this);
来检查。
所以,如果您已经将LostFocus
事件或类似事件附加到文本框上,因为该元素尚未失去焦点,所以该事件不会被触发。
PreviewMouseDown += (s, e) => FocusManager.SetFocusedElement(this, null);
PreviewMouseDown += (s, e) => Keyboard.ClearFocus();
System.Windows.Input.FocusManager.SetFocusedElement(this, null);
现在,如果您想知道我们是否可以摆脱Keyboard.ClearFocus();
,答案是否定的,因为我们将移除鼠标焦点,但键盘焦点仍然存在。(您会注意到文本框中仍有闪烁的光标,并且您仍然可以输入一些文本)。我尝试了在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);
}
}
我不是100%确定,但如果您在容器元素(Grid、StackPanel等)上将Focusable
设置为true,则应该会将焦点从文本框中移开。
这可以用很少的代码完成。只需在文本框或其他控件所放置的窗口中设置窗口的 Focusable="True"
,并在其 MouseDown
事件上添加以下内容:
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
FocusManager.SetFocusedElement(this, this);
}