La liaison TextBox TwoWay ne se met pas à jour Jusqu'à ce que le Focus perde WP7

J'ai une page avec quelques 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 de la zone de texte ne sont pas modifiées dans mon modèle de vue sur l'événement enregistrer.

Existe-t-il un moyen d'enregistrer la valeur de la zone de texte avant de perdre le focus? Ou dois-je faire quelque chose dans l'événement de sauvegarde?

42
demandé sur Josh Close 2011-04-06 20:23:56

8 réponses

Vous pouvez utiliser le comportement UpdateTextBindingOnPropertyChanged de la bibliothèque Prism pour WP7 pour mettre à jour la valeur liée lorsque le texte change au lieu de la mise au point perdue.

7
répondu Derek Lakin 2011-04-06 16:31:09

Je suppose que votre bouton de sauvegarde est un ApplicationBarButton (pas un bouton normal). Pour les boutons normaux, cela fonctionnera simplement parce qu'ils prennent le focus et donc la liaison de données entrera en jeu.

Pour ApplicationBarButtons sur le téléphone, c'est un peu différent car ils ne détournent pas le focus de l'application cliente. Pour vous assurer que la liaison de données commence 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();
}
55
répondu Stefan Wick MSFT 2011-04-09 17:19:25

Téléchargez le livre gratuit de Charles PetzoldProgramming Windows Phone 7 . À la page 387, Il parle de la façon de le faire.

Fondamentalement, définissez la propriété UpdateSourceTrigger du Binding sur Explicit. Ensuite, dans le rappel TextBox de TextChanged, Mettez à jour la source de liaison.

16
répondu Praetorian 2011-04-06 18:13:29

Je vais dans la direction opposée à @Praetorian.

Votre TextBox est un défaut UpdateSourceTrigger valeur de LostFocus. Cela signifie que la valeur n'est poussée vers votre propriété ViewModel que lorsque.. il perd le focus.

Vous pouvez définir le UpdateSourceTrigger sur PropertyChanged:

<TextBox UpdateSourceTrigger="PropertyChanged" Text="{Binding TextViewModelProperty}" />

Depuis 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 UpdateSourceTrigger par défaut de la cible de la propriété de dépendance. Cependant, la valeur par défaut pour la plupart propriétés de dépendance est PropertyChanged, tandis que le texte la propriété a une valeur par défaut 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 avec chaque pression de touche, au lieu d'un seul "flush" lorsque le TextBox perd le focus).

Espérons que cela aide!

6
répondu rrhartjr 2011-04-06 18:19:41

Voici une réponse rapide à la solution Microsoft suggérée par Derek. Plutôt que de télécharger et de passer au crible toutes les choses 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 nettoyée du code Microsoft Prism 4.1 (voir le Silverlight\Prism.Projet d'interactivité si vous voulez parcourir le reste).

Maintenant comment utiliser il:

  1. Ajouter une référence au système.Windows.Ensemble d'interactivité à votre projet Windows Phone.
  2. dans chaque page où vous souhaitez utiliser le comportement, ajoutez une référence XAML à l'assembly: xmlns: i= " clr-namespace: système.Windows.Interactivité; assemblage = Système.Windows.Interactivité "
  3. Dans le XAML de chaque zone de texte à laquelle vous souhaitez appliquer le bahvior (qui a déjà une liaison TwoWay à votre propriété source), ajoutez le suivant:



    Remarque: le préfixe" my: "peut être différent dans votre code. C'est juste la référence d'espace de noms où vous avez ajouté la classe de comportement.

6
répondu Tony Wall 2013-03-04 18:29:58

Essayez de définir la propriété UpdateSourceTrigger sur 'PropertyChanged'

Comme ceci

Property="{Binding PropertyBinding, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
5
répondu Rajiv 2016-08-01 12:56:35

Je n'ai pas essayé la réponse de @Praetorian, donc si cela fonctionne bien, faites - le-sinon, utilisez à la fois les événements KeyUp et TextChanged pour mettre à jour la source de liaison.

1
répondu PhilChuang 2011-04-06 17:37:09

Ce lien a une solution qui a parfaitement fonctionné 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

0
répondu jlo 2013-04-16 01:12:50