Question

Dans une application Silverlight 4.0 MVVMLight J'ai un listbox, une zone de texte et une case à cocher. Le ItemsSource de la zone de liste est lié à une liste d'objets dans le viewmodel. est dans les deux sens de SelectedItem de la zone de liste liée à un objet (SelectedActivity) dans le viewmodel.

Les deux sont liés dans les deux sens du texte et les propriétés isSelected de la case à cocher la zone de texte à l'objet SelectedActivity (Nom et Biens sélectionnés) dans le viewmodel. Il n'y a pas codebehind.

Cela fonctionne bien. La modification du nom dans la zone de texte ou cochant / décochant la case à cocher et changera la tabulation propriété sous-jacente de l'objet

Mais quand je change le nom (ou l'état vérifié) puis cliquez sur immediatelly un autre élément dans la liste, le changement est pas enregistré.

Quelqu'un at-il une solution de contournement pour cela?

cordiales salutations,

Karel

Ceci est le XAML:

<ListBox Height="251" HorizontalAlignment="Left" Margin="11,39,0,0" Name="activitiesListBox" ItemsSource="{Binding Activities.Items}" VerticalAlignment="Top" Width="139"
             SelectedItem="{Binding Activities.SelectedActivity, Mode=TwoWay}">

est la classe Activités tenant les éléments liés à la liste:

public class CLJActivitiesViewModel : ViewModelBase
{
    /// <summary>
    /// Initializes a new instance of the ActivitiesViewModel class.
    /// </summary>
    public CLJActivitiesViewModel()
    {
        ////if (IsInDesignMode)
        ////{
        ////    // Code runs in Blend --> create design time data.
        ////}
        ////else
        ////{
        ////    // Code runs "for real": Connect to service, etc...
        ////}
    }


    #region items
    /// <summary>
    /// The <see cref="Items" /> property's name.
    /// </summary>
    public const string ItemsPropertyName = "Items";

    private ObservableCollection<CLJActivityViewModel> m_Items = null;

    /// <summary>
    /// Gets the Items property.
    /// TODO Update documentation:
    /// Changes to that property's value raise the PropertyChanged event. 
    /// This property's value is broadcasted by the Messenger's default instance when it changes.
    /// </summary>
    public ObservableCollection<CLJActivityViewModel> Items
    {
        get
        {
            return m_Items;
        }

        set
        {
            if (m_Items == value)
            {
                return;
            }

            var oldValue = m_Items;
            m_Items = value;

            RaisePropertyChanged(ItemsPropertyName, oldValue, value, true);
        }
    }
    #endregion

    #region SelectedActivity
    /// <summary>
    /// The <see cref="SelectedActivity" /> property's name.
    /// </summary>
    public const string SelectedActivityPropertyName = "SelectedActivity";

    private CLJActivityViewModel m_SelectedActivity = null;

    /// <summary>
    /// Gets the SelectedActivity property.
    /// TODO Update documentation:
    /// Changes to that property's value raise the PropertyChanged event. 
    /// This property's value is broadcasted by the Messenger's default instance when it changes.
    /// </summary>
    public CLJActivityViewModel SelectedActivity
    {
        get
        {
            return m_SelectedActivity;
        }

        set
        {
            if (m_SelectedActivity == value)
            {
                return;
            }

            var oldValue = m_SelectedActivity;
            m_SelectedActivity = value;

            RaisePropertyChanged(SelectedActivityPropertyName, oldValue, value, true);
        }
    }
    #endregion



    public override void Cleanup()
    {
        // Clean own resources if needed

        base.Cleanup();
    }
}        
Était-ce utile?

La solution

Je suis tombé sur le peu la même question. Je devais déclencher la mise à jour que l'utilisateur a saisi le texte pour que je puisse faire une validation.

Un moyen facile d'y parvenir est de créer un comportement personnalisé que vous pouvez ajouter à tout TextBox.

Le mien est le suivant:

public static class TextChangedBindingBehavior
{
    public static readonly DependencyProperty InstanceProperty =
        DependencyProperty.RegisterAttached("Instance", typeof(object), typeof(TextChangedBindingBehavior), new PropertyMetadata(OnSetInstanceCallback));


    public static object GetInstance(DependencyObject obj)
    {
        return (object)obj.GetValue(InstanceProperty);
    }

    public static void SetInstance(DependencyObject obj, object value)
    {
        obj.SetValue(InstanceProperty, value);
    }

    private static void OnSetInstanceCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = d as TextBox;
        if (textBox != null)
        {
            textBox.TextChanged -= OnTextChanged;
            textBox.TextChanged += OnTextChanged;
        }
    }

    private static void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        var textBox = (TextBox)sender;

        if(!DesignerProperties.GetIsInDesignMode(textBox))
        {
            textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
        }
    }
}

et que vous définissez à l'TextBox comme ça (Behaviors est l'espace de noms où je mets la classe ci-dessus):

 <TextBox Behaviors:TextChangedBindingBehavior.Instance="" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />

Autres conseils

Je suis tombé sur la question comme ça avec TextBox, mais n'a pas vu que cela affecte case à cocher. question TextBox se produit parce que le texte lié est mis à jour puis mise au point est perdu. Voilà pourquoi si vous onglet, puis modifiez votre sélection, il fonctionne comme prévu. Si vous changez la sélection du texte directement lié ne soit pas mis à jour depuis le message perdu focus arrive trop tard.

Une façon de traiter ce problème est de forcer la mise à jour de liaison à chaque fois que le texte de types d'utilisateur dans la zone de texte. Vous pouvez faire un comportement personnalisé pour le garder MVVM.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top