J'ai une page avec des zones de texte pour la saisie de données. La liaison de la zone de texte est définie sur TwoWay
. Les données de mon modèle de vue ne sont mises à jour que si la zone de texte perd le focus. Si je clique sur un bouton, tel que Enregistrer, et que la zone de texte a toujours le focus, les modifications apportées à la zone de texte ne sont pas modifiées dans mon modèle d'affichage lors de l'enregistrement.
Existe-t-il un moyen de faire en sorte que la liaison enregistre la valeur de la zone de texte avant qu'elle ne perd son focus? Ou dois-je faire quelque chose dans l'événement de sauvegarde?
Vous pouvez utiliser le comportement UpdateTextBindingOnPropertyChanged
de Prism Library pour WP7 pour mettre à jour la valeur liée lorsque le texte est modifié au lieu d’être perdu dans le focus.
Je suppose que votre bouton Enregistrer est un ApplicationBarButton (pas un bouton normal). Pour les boutons normaux, cela fonctionnera simplement car ils prendront le focus et donc la liaison de données entrera.
Pour les boutons ApplicationBar au téléphone, c'est un peu différent, car ils ne détournent pas l'attention de l'application cliente. Pour vous assurer que la liaison de données entre en action lorsque vous cliquez sur le bouton Enregistrer, vous pouvez ajouter le code suivant dans votre gestionnaire:
object focusObj = FocusManager.GetFocusedElement();
if (focusObj != null && focusObj is TextBox)
{
var binding = (focusObj as TextBox).GetBindingExpression(TextBox.TextProperty);
binding.UpdateSource();
}
Téléchargez le livre gratuit de Charles Petzold Programmation Windows Phone 7 . À la page 387, il explique comment procéder.
Fondamentalement, définissez la propriété UpdateSourceTrigger
de Binding
sur Explicit
. Ensuite, dans le rappel TextBox
de la TextChanged
, mettez à jour la source de liaison.
Je vais dans le sens opposé de @Petorian.
Votre TextBox
a une valeur par défaut UpdateSourceTrigger
de LostFocus
. Cela signifie que la valeur n'est transmise à votre propriété ViewModel que .., elle perd le focus.
Vous pouvez définir UpdateSourceTrigger sur PropertyChanged:
<TextBox UpdateSourceTrigger="PropertyChanged" Text="{Binding TextViewModelProperty}" />
De http://msdn.Microsoft.com/en-us/library/system.windows.data.binding.updatesourcetrigger.aspx :
Une des valeurs UpdateSourceTrigger . La valeur par défaut est Default, qui renvoie la valeur par défaut UpdateSourceTrigger de la propriété de dépendance cible . Cependant, la valeur par défaut pour la plupart des les propriétés de dépendance sont PropertyChanged, tandis que le texte propriété a une valeur par défaut de LostFocus.
Gardez à l'esprit que cela signifie que tout ce qui est déclenché par une mise à jour de cette propriété se produira beaucoup plus fréquemment (essentiellement à chaque pression de touche, au lieu d'un "vidage" unique lorsque la variable TextBox
perd son focus).
J'espère que cela pourra aider!
Voici une réponse rapide à la solution Microsoft proposée par Derek. Plutôt que de télécharger et de parcourir tous les éléments de Prism, copiez simplement cette classe dans votre projet, puis suivez les étapes suivantes pour l'activer:
UpdateBindingOnPropertyChangedBehviour.cs
using System;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Interactivity;
namespace MyCompany.MyProduct
{
/// <summary>
/// Custom behavior that updates the source of a binding on a text box as the text changes.
/// </summary>
public class UpdateTextBindingOnPropertyChanged : Behavior<TextBox>
{
/// <summary>
/// Binding expression this behavior is attached to.
/// </summary>
private BindingExpression _expression;
/// <summary>
/// Called after the behavior is attached to an AssociatedObject.
/// </summary>
/// <remarks>
/// Override this to hook up functionality to the AssociatedObject.
/// </remarks>
protected override void OnAttached()
{
base.OnAttached();
// Hook events to change behavior
_expression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
AssociatedObject.TextChanged += OnTextChanged;
}
/// <summary>
/// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
/// </summary>
/// <remarks>
/// Override this to unhook functionality from the AssociatedObject.
/// </remarks>
protected override void OnDetaching()
{
base.OnDetaching();
// Un-hook events
AssociatedObject.TextChanged -= OnTextChanged;
_expression = null;
}
/// <summary>
/// Updates the source property when the text is changed.
/// </summary>
private void OnTextChanged(object sender, EventArgs args)
{
_expression.UpdateSource();
}
}
}
Il s'agit essentiellement d'une version épurée du code Microsoft Prism 4.1 (consultez le projet Silverlight\Prism.Interactivity si vous souhaitez parcourir le reste).
Maintenant comment l'utiliser:
Dans le XAML de chaque zone de texte à laquelle vous voulez appliquer le bahvior (qui a déjà une liaison TwoWay à votre propriété source), ajoutez ce qui suit:
<i: Interaction.Behaviors>
<my: UpdateTextBindingOnPropertyChanged />
</ i: Interaction.Behaviors>
Remarque: le préfixe "mon:" peut être différent dans votre code. C'est simplement la référence de l'espace de noms où vous avez ajouté la classe de comportement.
essayez de définir la propriété UpdateSourceTrigger
sur 'PropertyChanged'
comme ça
Property="{Binding PropertyBinding, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Je n'ai pas essayé la réponse de @ Praetorian, donc si cela fonctionne bien, faites-le. Sinon, utilisez les deux événements KeyUp AND TextChanged pour mettre à jour la source Binding.
Ce lien a une solution qui a fonctionné parfaitement dans WinRT. Il hérite de TextBox et ajoute une nouvelle propriété: BindableText.
http://www.familie-smits.com/post/2012/07/29/UpdateSourceTrigger-in-WinRT.aspx