Vous pouvez créer une approche XAML pure en créant un comportement attaché .
Quelque chose comme ça:
public static class InputBindingsManager
{
public static readonly DependencyProperty UpdatePropertySourceWhenEnterPressedProperty = DependencyProperty.RegisterAttached(
"UpdatePropertySourceWhenEnterPressed", typeof(DependencyProperty), typeof(InputBindingsManager), new PropertyMetadata(null, OnUpdatePropertySourceWhenEnterPressedPropertyChanged));
static InputBindingsManager()
{
}
public static void SetUpdatePropertySourceWhenEnterPressed(DependencyObject dp, DependencyProperty value)
{
dp.SetValue(UpdatePropertySourceWhenEnterPressedProperty, value);
}
public static DependencyProperty GetUpdatePropertySourceWhenEnterPressed(DependencyObject dp)
{
return (DependencyProperty)dp.GetValue(UpdatePropertySourceWhenEnterPressedProperty);
}
private static void OnUpdatePropertySourceWhenEnterPressedPropertyChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
UIElement element = dp as UIElement;
if (element == null)
{
return;
}
if (e.OldValue != null)
{
element.PreviewKeyDown -= HandlePreviewKeyDown;
}
if (e.NewValue != null)
{
element.PreviewKeyDown += new KeyEventHandler(HandlePreviewKeyDown);
}
}
static void HandlePreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
DoUpdateSource(e.Source);
}
}
static void DoUpdateSource(object source)
{
DependencyProperty property =
GetUpdatePropertySourceWhenEnterPressed(source as DependencyObject);
if (property == null)
{
return;
}
UIElement elt = source as UIElement;
if (elt == null)
{
return;
}
BindingExpression binding = BindingOperations.GetBindingExpression(elt, property);
if (binding != null)
{
binding.UpdateSource();
}
}
}
Ensuite, dans votre XAML, vous définissez la InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty
propriété sur celle que vous souhaitez mettre à jour lorsque la Entertouche est enfoncée. Comme ça
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>
(Vous devez simplement vous assurer d'inclure une référence xmlns clr-namespace pour "b" dans l'élément racine de votre fichier XAML pointant vers l'espace de noms dans lequel vous avez placé InputBindingsManager).
UpdatePropertySourceWhenEnterPressed
changement d'une valeur valide à une valeur valide différente, vous vous désabonnez et vous réinscrivez à l'PreviewKeyDown
événement inutilement. Au lieu de cela, tout ce que vous avez besoin est de vérifier si oui ou non l'e.NewValue
estnull
ou non. Sinonnull
, abonnez-vous; sinon, sinull
, alors désabonnez-vous.C'est ainsi que j'ai résolu ce problème. J'ai créé un gestionnaire d'événements spécial qui est entré dans le code derrière:
Ensuite, je viens d'ajouter ceci en tant que gestionnaire d'événements KeyUp dans le XAML:
Le gestionnaire d'événements utilise sa
sender
référence pour provoquer la mise à jour de sa propre liaison. Étant donné que le gestionnaire d'événements est autonome, il doit fonctionner dans un DataTemplate complexe. Ce gestionnaire d'événement unique peut maintenant être ajouté à toutes les zones de texte qui ont besoin de cette fonctionnalité.la source
KeyBinding
dans le XAML pour déclencher cette méthode car mon interface utilisateur a un contrôle "Default" qui attrape la clé d'entrée. Vous devez l'attraper dans cette zone de texte pour l'empêcher de se propager dans l'arborescence de l'interface utilisateur vers le contrôle "Par défaut".Je ne crois pas qu'il existe une manière "XAML pur" de faire ce que vous décrivez. Vous pouvez configurer une liaison afin qu'elle se mette à jour chaque fois que le texte d'un TextBox change (plutôt que lorsque le TextBox perd le focus) en définissant la propriété UpdateSourceTrigger , comme ceci:
Si vous définissez UpdateSourceTrigger sur "Explicit" et que vous gérez ensuite l'événement PreviewKeyDown de la zone de texte (à la recherche de la touche Entrée), vous pouvez obtenir ce que vous voulez, mais cela nécessiterait un code-behind. Peut-être une sorte de propriété attaché (semblable à mon EnterKeyTraversal propriété) de travail woudld pour vous.
la source
Vous pouvez facilement créer votre propre contrôle héritant de TextBox et le réutiliser tout au long de votre projet.
Quelque chose de similaire devrait fonctionner:
Il peut y avoir un moyen de contourner cette étape, mais sinon, vous devriez lier comme ceci (en utilisant Explicit):
la source
Si vous combinez à la fois les solutions de Ben et d'ausadmin, vous vous retrouvez avec une solution très conviviale pour MVVM:
... ce qui signifie que vous passez le
TextBox
lui - même comme paramètre auCommand
.Cela vous conduit à
Command
ressembler à ceci (si vous utilisez uneDelegateCommand
implémentation -style dans votre VM):Cette
Command
implémentation peut être utilisée pour n'importe quelTextBox
et le meilleur de tous aucun code dans le code-behind bien que vous souhaitiez peut-être le mettre dans sa propre classe afin qu'il n'y ait pas de dépendancesSystem.Windows.Controls
dans votre VM. Cela dépend de la rigueur de votre code.la source
Voici une approche qui me semble assez simple, et plus simple que l'ajout d'un AttachedBehaviour (qui est également une solution valable). Nous utilisons le UpdateSourceTrigger par défaut (LostFocus pour TextBox), puis ajoutons un InputBinding à la clé Entrée, lié à une commande.
Le xaml est le suivant
Ensuite, les méthodes de commande sont
Et le TextBox est lié à la propriété
Jusqu'à présent, cela semble bien fonctionner et capture l'événement Enter Key dans la zone de texte.
la source
Ce n'est pas une réponse à la question initiale, mais plutôt une extension de la réponse acceptée par @Samuel Jack. J'ai fait ce qui suit dans ma propre application et j'étais impressionné par l'élégance de la solution de Samuel. Il est très propre et très réutilisable, car il peut être utilisé sur n'importe quel contrôle, pas seulement le
TextBox
. J'ai pensé que cela devrait être partagé avec la communauté.Si vous avez une fenêtre avec un millier
TextBoxes
qui nécessitent tous de mettre à jour la source de liaison sur Entrée, vous pouvez attacher ce comportement à tous en incluant le XAML ci-dessous dans votreWindow
Resources
plutôt que de l'attacher à chaque zone de texte. Vous devez d'abord implémenter le comportement ci-joint conformément au message de Samuel , bien sûr.Vous pouvez toujours limiter la portée, si nécessaire, en mettant le style dans les ressources de l'un des éléments enfants de la fenêtre (c'est-à-dire a
Grid
) qui contient les TextBoxes cibles.la source
Si vous utilisez MultiBinding avec votre TextBox, vous devez utiliser
BindingOperations.GetMultiBindingExpression
method au lieu deBindingOperations.GetBindingExpression
.la source
Cela fonctionne pour moi:
la source
Répondu ici assez élégamment en utilisant des comportements attachés, ma méthode préférée pour presque tout.
WPF comment faire perdre le focus à la zone de texte après avoir appuyé sur Entrée
la source
Personnellement, je pense qu'avoir une extension de balisage est une approche plus propre.
la source
Une solution différente (n'utilisant pas xaml mais toujours assez propre je pense).
la source