J'ai quelques zones de texte sur lesquelles j'aimerais que le focus se comporte un peu différemment que la normale pour une application WPF. En gros, j'aimerais qu'ils se comportent davantage comme un champ de texte sur une page Web. C'est-à-dire que si je clique n'importe où en dehors de la zone de texte, le focus disparaîtra. Quelle est la meilleure façon de le faire?
Si la solution consiste à supprimer le focus par programme, quel est le meilleur moyen de détecter un clic de souris en dehors des limites? Et si l'élément sur lequel je clique sera le nouveau destinataire de focus?
Plutôt que d'ajouter un nouveau contrôle à la fenêtre, je pense que vous devriez donner à votre Grille un nom et réagir à l'événement MouseDown sur votre fenêtre, en déplaçant le focus sur la Grille . Quelque chose comme ça:
<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 derrière:
private void window1_MouseDown(object sender, MouseButtonEventArgs e)
{
grid1.Focus();
}
Je pense que la meilleure façon de résoudre ce problème consiste à ajouter le gestionnaire d’événements MouseDown à la fenêtre avec le code derrière:
private void window_MouseDown(object sender, MouseButtonEventArgs e)
{
Keyboard.ClearFocus();
}
Une autre façon qui a fonctionné pour moi utilisait
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler
Par exemple, supposons que vous ayez un TextBlock qui, une fois cliqué, devienne éditable en affichant une TextBox ciblée. Ensuite, lorsque l'utilisateur clique en dehors de la zone de texte, celle-ci doit être masquée à nouveau. Voici comment vous pouvez le faire:
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;
}
Je ne suis pas sûr à 100%, mais si vous définissez Focusable
sur true sur l'élément conteneur (Grid, StackPanel, etc.), le focus devrait être retiré de la zone de texte.
Si vous avez cliqué sur l'élément qui peut capturer le focus, vous obtenez ce dont vous avez besoin. Si, par exemple, vous avez un panneau, vous pouvez gérer l'événement mouseClick pour répondre à vos besoins ou utiliser les conseils de Richard Szalay.
Pour éviter le code en retard, vous pouvez utiliser ce comportement Le comportement
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;
}
}
Utilisation en XAML:
Sur tout élément en dehors de la zone de texte sur lequel vous voulez qu'il efface le focus, cliquez sur Ajouter:
<i:Interaction.Behaviors>
<behaviors:ClearFocusOnClickBehavior/>
</i:Interaction.Behaviors>
J'ai essayé la réponse sélectionnée dans l'application native WPF de réaction, mais cela ne provoquait pas la perte de la focalisation de la zone de texte en raison de la zone de texte qui ne perdait pas la focalisation. La solution suivante fonctionne pour moi.
Lier un événement de souris vers le bas à la fenêtre:
<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>
et l'événement est:
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);
}
}
Vous pouvez utiliser l'événement 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
}
}
vous ne pouvez pas explicitement perdre le focus d'un contrôle
vous pouvez définir le focus sur un autre contrôle à la place
**txt.Focusable=true;
label.focus();
Keyboard.Focus(txtPassword);**
essaye ça
Je rencontrais un problème similaire, mais lorsque j’enveloppais mes champs de texte autour d’un contrôle ScrollViewer, tous les champs de texte perdaient automatiquement le focus lorsque vous cliquez à l’extérieur des texboxes.