49 votes

TextBox Binding TwoWay ne se met pas à jour avant le focus Lost WP7

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 comme suit 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 sauvegarder, et que la zone de texte a toujours le focus, les changements dans la zone de texte ne sont pas modifiés dans mon modèle de vue lors de l'événement de sauvegarde.

Existe-t-il un moyen de faire en sorte que la liaison enregistre la valeur de la zone de texte avant qu'elle ne perde le focus ? Ou dois-je faire quelque chose dans l'événement de sauvegarde ?

1 votes

Vous trouverez ici une solution fonctionnelle qui met à jour la liaison sur l'événement TextChanged : stackoverflow.com/a/4833196/928955

0 votes

Même problème sur WP8, la réponse de @StefanWick l'a résolu pour moi.

61voto

StefanWick Points 2396

Je suppose que votre bouton Enregistrer est un ApplicationBarButton (et non un bouton normal). Pour les boutons normaux, cela fonctionnera simplement parce qu'ils prennent le focus et donc la liaison de données sera activée.

Pour les boutons de la barre d'application sur le 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 se déclenche 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();
}

3 votes

Merci. C'est bon de savoir pourquoi.

0 votes

Merci pour cela. Nous sauvegardons automatiquement la structure de données chaque fois que la propriété du texte est mise à jour, et il n'était pas normal que cela se produise à chaque frappe de touche.

0 votes

Merci, cela m'a aidé car je n'utilise pas MVVM light.

17voto

Praetorian Points 47122

Télécharger le livre gratuit de Charles Petzold Programmation de Windows Phone 7 . À la page 387, il explique comment procéder.

En gros, il s'agit de définir le UpdateSourceTrigger de l Binding à Explicit . Ensuite, dans le TextBox 's TextChanged met à jour la source du Binding.

8voto

Derek Lakin Points 13119

Vous pouvez utiliser le UpdateTextBindingOnPropertyChanged comportement de la Bibliothèque Prism pour WP7 pour mettre à jour la valeur liée lorsque le texte change au lieu de le faire à la perte du focus.

4 votes

J'utilise déjà MVVM Light et je ne veux pas inclure Prism juste pour cela :(

0 votes

Le code source est également disponible, vous pourriez donc inclure ce seul fichier ;)

0 votes

Oui, c'est ce que je regarde en ce moment. Je n'avais pas réalisé à quel point Prism pour WP7 est léger. Je vais peut-être devoir regarder les différences entre Prism et MVVM Light. Prism semble avoir quelques éléments supplémentaires que je dois utiliser.

6voto

Code Chief Points 422

Voici une réponse rapide à la solution Microsoft suggérée par Derek. Plutôt que de télécharger et de passer en revue tous les éléments de Prism, copiez simplement cette classe dans votre projet et 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 de Microsoft Prism 4.1 (voir le document Silverlight \Prism.Interactivity si vous souhaitez parcourir le reste).

Maintenant, comment l'utiliser :

  1. Ajoutez une référence à l'assemblage System.Windows.Interactivity à votre projet Windows Phone.
  2. Dans chaque page où vous souhaitez utiliser le comportement, ajoutez une référence XAML à l'assemblage : xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
  3. Dans le XAML de chaque TextBox auquel vous voulez appliquer le bahvior (qui a déjà une liaison TwoWay avec votre propriété source), ajoutez ce qui suit :

    <i:Interaction.Behaviors>
    <my:UpdateTextBindingOnPropertyChanged />
    </i:Interaction.Behaviors>

    Remarque : le préfixe "my :" peut être différent dans votre code. Il s'agit simplement de la référence de l'espace de nom où vous avez ajouté la classe de comportement.

6voto

rrhartjr Points 877

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

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

Vous pouvez définir le déclencheur UpdateSourceTrigger sur PropertyChanged :

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

Desde http://msdn.microsoft.com/en-us/library/system.Windows.data.binding.updatesourcetrigger.aspx :

Une des valeurs de UpdateSourceTrigger. La valeur par défaut est Default, qui renvoie la valeur UpdateSourceTrigger par défaut de la propriété de dépendance cible. Toutefois, la valeur par défaut de la plupart des propriétés de dépendance est PropertyChanged, tandis que le texte 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 (en fait, à chaque pression sur une touche, au lieu d'un seul "flush" lorsque l'option TextBox perd le focus).

J'espère que cela vous aidera !

3 votes

Silverlight ne prend pas en charge la valeur "PropertyChanged" pour "UpdateSourceTrigger". Vous avez lié le sujet WPF, qui ne s'applique pas à WP7.

0 votes

Oups, je suis un gars de WPF, donc j'oublie toujours ça ! Désolé !

4 votes

La définition de la propriété Text en Text="{Binding TextViewModelProperty,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" a fonctionné pour moi (j'utilise SL5).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X