WPF - удаление фокуса при нажатии за пределами текстового поля
У меня есть несколько текстовых полей, в которых я бы хотел, чтобы фокус вел себя немного иначе, чем обычно для приложения WPF. В принципе, я бы хотел, чтобы они больше походили на текстовое поле на веб-странице. То есть, если я щелкнул где-нибудь за пределами текстового поля, он потеряет фокус. Каков наилучший способ сделать это?
Если ответ заключается в программном удалении фокуса, что лучший способ обнаружить Mouseclick за пределами границ? Что, если элемент, на который я нажимаю, станет новым получателем фокуса?
Ответы
Ответ 1
Вместо того, чтобы добавлять новый элемент управления в окно, я думаю, что вы должны дать вашей 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" 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();
}
Ответ 2
Я думаю, лучший способ решить эту проблему - добавить обработчик событий MouseDown в окно с кодом:
private void window_MouseDown(object sender, MouseButtonEventArgs e)
{
Keyboard.ClearFocus();
}
Ответ 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;
}
Ответ 4
Чтобы избежать кода позади, вы можете использовать это поведение
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>
Ответ 5
Я не уверен на 100%, но если вы устанавливаете Focusable
на true в элемент контейнера (Grid, StackPanel и т.д.), тогда он должен отвлечь фокус от текстового поля.
Ответ 6
Если вы нажмете на элемент, который может захватить фокус, вы получите то, что вам нужно. если, например, у вас есть панель, вы можете обрабатывать событие mouseClick панели для достижения ваших нужд или использовать рекомендации Ричарда Салаи.
Ответ 7
У меня была похожая проблема, но когда я обернул элемент управления ScrollViewer вокруг своих текстовых полей, все текстовые поля автоматически теряли фокус при щелчке в любом месте за пределами текстовых полей.
Ответ 8
вы не можете явно потерять фокус элемента управления
вы можете установить фокус на другое управление вместо
**txt.Focusable=true;
label.focus();
Keyboard.Focus(txtPassword);**
попробуйте это
Ответ 9
Вы можете использовать событие IsKeyboardFocusedChanged
:
myTextBox.IsKeyboardFocusedChanged += myTextBox_IsKeyboardFocusedChanged;
private void SendFileCaptionTextBox_IsKeyboardFocusedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue.ToString() == "True")
{
// it focused
}
else
{
// it not focused
}
}
Ответ 10
Я попробовал выбранный ответ в приложении 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
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>