43 votes

Déterminez si l'événement Selector.SelectionChanged a été initié par un utilisateur

Est-il possible de déterminer si un événement Selector.SelectionChanged a été déclenché par l'utilisateur ou de manière programmatique ?

Par exemple, j'ai besoin de quelque chose comme une propriété booléenne "IsUserInitiated" qui est vraie uniquement si l'événement SelectionChanged a été déclenché parce que l'utilisateur a modifié la sélection à l'aide de la souris ou du clavier.

25voto

jim31415 Points 2884

Simple solution de contournement :

Vous pourriez créer une méthode qui désactive temporairement l'événement SelectionChanged et l'appeler lorsque vous avez besoin de changer la sélection de manière programmée.

private void SelectGridRow( int SelectedIndex )
{
    myDataGrid.SelectionChanged -= myDataGrid_SelectionChanged;
    myDataGrid.SelectedIndex = SelectedIndex;

    // other work ...

    myDataGrid.SelectionChanged += myDataGrid_SelectionChanged;
}

18voto

David Sherret Points 3205

Ceci devrait fonctionner dans la plupart des scénarios :

private void cboStatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (this.cboStatus.IsDropDownOpen)
    {
        //OPTIONNEL:
        //Empêche le déclenchement du changement de sélection de la combobox si quoi que ce soit
        //dans la fonction ci-dessous modifie la sélection (comme dans mon cas étrange)
        this.cboStatus.IsDropDownOpen = false;

        //mettez maintenant le code que vous souhaitez exécuter lorsque l'utilisateur sélectionne une option ici
    }
}

11voto

Justin Pavatte Points 903

C'est un problème auquel j'ai dû faire face depuis WinForms. J'espérais qu'en WPF, ils ajouteraient un booléen à SelectionChangedEventArgs appelé quelque chose comme IsUserInitiated comme mentionné dans la question. J'en ai le plus souvent besoin lorsque je veux ignorer tout ce qui se passe pendant le chargement des données et la liaison à l'écran. Par exemple, disons que je définis une valeur par défaut en fonction de la nouvelle valeur dans SelectionChanged, MAIS je veux que l'utilisateur puisse remplacer cette valeur par défaut, et je veux seulement que l'utilisateur le fasse, PAS l'application lorsque l'écran se recharge. J'ai toujours l'impression que ce que je fais est un bricolage, mais je le posterai car je ne le vois pas mentionné. Pas de tours de passe-passe, juste simple et efficace.

1) Créez un booléen au niveau de la classe appelé _loading

private bool _loading;

2) Mettez à jour le booléen dans la méthode effectuant le chargement

private async Task Load()
{
    _loading = true;
    // charger des trucs
    _loading = false;
}

3) Utilisez le booléen chaque fois que vous en avez besoin

private void SetDefaultValue(object sender, SelectionChangedEventArgs e)
{
    if (!_loading) {
        // définir une valeur par défaut
    }
}

7voto

mlemay Points 907

Extrait de http://social.msdn.microsoft.com où l'utilisateur pose la même question

Je ne pense pas que nous puissions distinguer si un événement SelectionChanged a été initié par l'entrée de l'utilisateur ou de manière programmée. L'événement SelectionChanged ne s'en soucie pas.

En général, vous pouvez toujours savoir s'il est initié de manière programmée car c'est votre code qui l'initie.

Si vous utilisez la liaison de données pour lier l'élément sélectionné, vous pouvez définir les propriétés NotifyOnSourceUpdated et NotifyOnTargetUpdated sur True. Et vous pouvez gérer les événements Binding.SourceUpdated et Binding.TargetUpdated. Dans la plupart des cas, le changement initié par les entrées de l'utilisateur va du Target vers le Source. Si le changement est initié de manière programmée, il va du Source vers le Target.

Je ne sais pas si cela peut aider...

3voto

harri Points 536

Vous pourriez utiliser un événement routé personnalisé et connecter les gestionnaires appropriés dans un comportement comme ceci :

    public class UserSelectionChangedEventArgs : RoutedEventArgs
    {
        public UserSelectionChangedEventArgs( RoutedEvent id, SelectionChangedEventArgs args , bool changedByUser) :base(id)
        {
            SelectionChangedByUser = changedByUser;
            RemovedItems = args.RemovedItems;
            AddedItems = args.AddedItems;
        }

        public bool SelectionChangedByUser { get; set; }
        public IList RemovedItems { get; set; }
        public IList AddedItems { get; set; }
    }
    public delegate void UserSelectionChangedEventHandler( object sender, UserSelectionChangedEventArgs e );

    public class UserSelectionChangedBehavior : Behavior
    {
        private bool m_expectingSelectionChanged;

        public static readonly RoutedEvent UserSelectionChangedEvent = EventManager.RegisterRoutedEvent( "UserSelectionChanged", RoutingStrategy.Bubble, typeof( UserSelectionChangedEventHandler ), typeof( Selector ) );

        public static void AddUserSelectionChangedHandler( DependencyObject d, UserSelectionChangedEventHandler handler )
        {
            ( (Selector) d ).AddHandler( UserSelectionChangedEvent, handler );
        }

        public static void RemoveUserSelectionChangedHandler( DependencyObject d, UserSelectionChangedEventHandler handler )
        {
            ( (Selector) d ).RemoveHandler( UserSelectionChangedEvent, handler );
        }

        private void RaiseUserSelectionChangedEvent( UserSelectionChangedEventArgs args )
        {
            AssociatedObject.RaiseEvent( args );
        }

        protected override void OnAttached()
        {
            AssociatedObject.PreviewKeyDown += OnKeyDown;
            AssociatedObject.PreviewKeyUp += OnKeyUp;
            AssociatedObject.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
            AssociatedObject.PreviewMouseLeftButtonUp += OnMouseLeftButtonUp;
            AssociatedObject.SelectionChanged += OnSelectionChanged;
            base.OnAttached();
        }

        protected override void OnDetaching()
        {
            AssociatedObject.PreviewKeyDown -= OnKeyDown;
            AssociatedObject.PreviewKeyUp -= OnKeyUp;
            AssociatedObject.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
            AssociatedObject.PreviewMouseLeftButtonUp -= OnMouseLeftButtonUp;
            AssociatedObject.SelectionChanged -= OnSelectionChanged;
            base.OnDetaching();
        }

        private void OnMouseLeftButtonUp( object sender, MouseButtonEventArgs e )
        {
            m_expectingSelectionChanged = false;
        }

        private void OnKeyDown( object sender, KeyEventArgs e )
        {
            m_expectingSelectionChanged = true;
        }

        private void OnKeyUp( object sender, KeyEventArgs e )
        {
            m_expectingSelectionChanged = false;
        }

        private void OnMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
        {
            m_expectingSelectionChanged = true;
        }

        private void OnSelectionChanged( object sender, SelectionChangedEventArgs e )
        {
            RaiseUserSelectionChangedEvent( new UserSelectionChangedEventArgs( UserSelectionChangedEvent, e, m_expectingSelectionChanged ) );
        }
    }

En XAML, vous pourriez simplement vous abonner à l'événement UserSelectionChangedEvent comme ceci :

Gestionnaire :

private void OnUserSelectionChanged( object sender, UserSelectionChangedEventArgs e )
{
    if(e.SelectionChangedByUser)
    {
        Console.WriteLine( "Sélection modifiée par l'utilisateur" );
    }
    else
    {
        Console.WriteLine( "Sélection modifiée par le code" );
    }
}

Il ne s'agit que d'une idée. Vous n'aurez probablement même pas besoin du comportement et pourrez simplement définir l'événement routé joint. Mais alors je ne sais pas où stocker le drapeau m_expectingSelectionChanged. Je ne sais pas non plus si cela fonctionne dans tous les cas. Mais peut-être que cela vous donnera un point de départ.

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