IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

Filtrer une listView avec un predicate


Sujet :

Windows Presentation Foundation

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut Filtrer une listView avec un predicate
    Bonjour,

    Je suis en train de galérer sur ma fonction de filtre dans une listView.
    J'utilise le code suivant pour lancer la procédure de filtrage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    this.Cursor = Cursors.Wait; // Indicate to user that operation can be long
    ICollectionView view = CollectionViewSource.GetDefaultView(listView.Items);
    view.Filter = new Predicate<object>(FilterCallback));
    this.Cursor = Cursors.Arrow; // End long operation
    Tout fonctionne sauf mon Cursors.Arrow qui est appelé directement sans attendre la fin de ma fonction FilterCallback.
    J'aurais besoin d'un coup de main pour essayer de comprendre comment ça fonctionne et sur quoi je peux m'orienter pour attendre la fin du Filter Predicate.
    Merci pour vos avis !

  2. #2
    Invité
    Invité(e)
    Par défaut
    Rebonjour PetitRasta,
    Utilises à la place "Mouse.OverrideCursor".
    Regarde ici pour les détails.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    Re Ph_Gr,

    En fait ça ne répond pas vraiment à ma problématique...
    Mon réel problème c'est l'appel à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.Cursor = Cursors.Arrow;
    ou à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    finally
    {
        Mouse.OverrideCursor = null;
    }
    Cet appel se fait sans attendre la fin de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    view.Filter = new Predicate<object>(FilterCallback));
    Pour chaque ligne de ma collection, il y a un a appel à la fonction FilterCallback.
    C'est en sorte un Thread qui se charge de filtrer de façon autonome et ligne par ligne.
    Le thread principale n'attend pas la fin du "thread" annexe, c'est ça qui m'enlève mon cursors.await avant la fin du filtrage

  4. #4
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Petit Rasta Voir le message
    Cet appel se fait sans attendre la fin de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    view.Filter = new Predicate<object>(FilterCallback));
    Pour chaque ligne de ma collection, il y a un a appel à la fonction FilterCallback.
    C'est en sorte un Thread qui se charge de filtrer de façon autonome et ligne par ligne.
    Le thread principale n'attend pas la fin du "thread" annexe, c'est ça qui m'enlève mon cursors.await avant la fin du filtrage
    A ma connaissance, l'appel du filtre de la collection se fait sur le même thread que l'IHM, donc normalement les callbacks sont appelés sur le même thread... Donc à mon avis, le problème c'est plutôt que l'IHM n'a pas le temps de rafraîchir le curseur de la souris.
    Si tu es en Framework 4.5, essaye de faire ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    this.Cursor = Cursors.Wait; // Indicate to user that operation can be long
    await Task.Delay(10); //ça permettra au curseur d'avoir le temps de changer de forme
    ICollectionView view = CollectionViewSource.GetDefaultView(listView.Items);
    view.Filter = new Predicate<object>(FilterCallback));
    this.Cursor = Cursors.Arrow; // End long operation
    et mets bien un "async" sur l'appel de la méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    async void MaMethode() { ... }

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    Oui tu dois avoir raison pour le thread puisque l'UI se bloque quand je réalise les traitements.
    Je n'ai pas pu tester ton code, je suis malheureusement en 4.0 avec VS 2010

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Petit Rasta Voir le message
    Oui tu dois avoir raison pour le thread puisque l'UI se bloque quand je réalise les traitements.
    Je n'ai pas pu tester ton code, je suis malheureusement en 4.0 avec VS 2010
    Ah, mince, ça c'est dommage.
    En Framework 4.0, c'est un peu plus compliqué mais c'est jouable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    this.Cursor = Cursors.Wait; // Indicate to user that operation can be long
     
    Task.Factory.StartNew(()=> { Thread.Sleep(10); })
    .ContinueWith(tsk =>
    {
    ICollectionView view = CollectionViewSource.GetDefaultView(listView.Items);
    view.Filter = new Predicate<object>(FilterCallback));
    this.Cursor = Cursors.Arrow; // End long operation
    }, TaskContinuationOptions.ExecuteSynchronously);
    Notes bien le "TaskContinuationOptions.ExecuteSynchronously" en second paramètre sur le "ContinueWith" qui va lui indiquer que ça doit être fait sur le même thread que l'appelant de la tâche d'origine.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    J'ai tenté d'exécuter ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Mouse.OverrideCursor = Cursors.Wait;
                Task.Factory.StartNew(() => { Thread.Sleep(10); })
                    .ContinueWith(tsk => {
                        ICollectionView view = CollectionViewSource.GetDefaultView(listView.Items);
                        view.Filter = new Predicate<object>(FilterCallback);
                    }, TaskContinuationOptions.ExecuteSynchronously);
                this.Cursor = Cursors.Arrow;
    J'ai sorti les traitements sur les cursors.
    J'ai une erreur sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    view.Filter = new Predicate<object>(FilterCallback);
    Le thread appelant ne peut pas accéder à cet objet parce qu'un autre thread en est propriétaire.
    J'ai tenté en mettant cet appel dans un Dispatcher mais rien n'y fait ...

  8. #8
    Invité
    Invité(e)
    Par défaut
    Alors essaye comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Mouse.OverrideCursor = Cursors.Wait;
                Task.Factory.StartNew(() => { Thread.Sleep(10); })
                    .ContinueWith(tsk =>
                    {
                        this.BeginInvoke((Action)delegate()
                        {
                           ICollectionView view = CollectionViewSource.GetDefaultView(listView.Items);
                           view.Filter = new Predicate<object>(FilterCallback);
                           this.Cursor = Cursors.Arrow;
                        }
                    });

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    Aïe décidément ce n'est pas ma journée !!
    J'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    using System.Windows.Controls;
    et non
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    using System.Windows.Forms;
    Conséquence n'est pas reconnu
    Si je passe en Forms, j'ai tous mes contrôles à redéfinir ...

  10. #10
    Invité
    Invité(e)
    Par défaut
    Ah mince, sorry quel abruti quand je m'y mets!
    Voilà ce que c'est de faire plusieurs choses en même temps!
    N'hésites pas à me mettre des pouces rouges quand je mets des âneries

    J'avais oublié qu'en WPF il faut passer par "Dispatcher".
    Ceci devrait mieux fonctionner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Mouse.OverrideCursor = Cursors.Wait;
                Task.Factory.StartNew(() => { Thread.Sleep(10); })
                    .ContinueWith(tsk =>
                    {
                        this.Dispatcher.BeginInvoke((Action)delegate()
                        {
                           ICollectionView view = CollectionViewSource.GetDefaultView(listView.Items);
                           view.Filter = new Predicate<object>(FilterCallback);
                           this.Cursor = Cursors.Arrow;
                        }
                    });
    J'espère que je n'ai rien oublié cette fois...

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    Ce n'est pas grave, il n'y a pas de soucis
    On avance mais ce n'est pas encore ça ...
    Je n'ai plus d'exception et j'entre aperçois le 'sablier' mais il disparait avant que l'interface ne soit libérée.
    En fait j'ai l'impression qu'il fait comme avant sauf que là je le vois le temps du Sleep.

  12. #12
    Invité
    Invité(e)
    Par défaut
    C'est bizarre, normalement lorsque le curseur revient à la normale, alors le tri devrait être terminé... Il faudrait que tu sois capable de me dire quel est le type réel de ton objet "view". Normalement ce devrait être un "ListCollectionView".

    Bon sinon, pour être sûr, on va sortir l'artillerie lourde.
    L'idée : on va s'abonner à "CollectionChanged" du view à la vollée, et on va changer le curseur et se désabonner en même temps lorsque l'action est "Reset" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Mouse.OverrideCursor = Cursors.Wait;
                Task.Factory.StartNew(() => { Thread.Sleep(10); })
                    .ContinueWith(tsk =>
                    {
                        this.Dispatcher.BeginInvoke((Action)delegate()
                        {
                           ICollectionView view = CollectionViewSource.GetDefaultView(listView.Items);
                           NotifyCollectionChangedEventHandler handler = null;
                           handler = (snd,evt) =>
                           {
                               if (evt.Action!=NotifyCollectionChangedAction.Reset) return; //On ne s'arrête que s'il fait un Reset
                               view.CollectionChanged -= handler; //Désabonnement
                               Mouse.OverrideCursor = null; //Remise à la normale du curseur
                           }
                           view.CollectionChanged += handler; //Abonnement au Handler
     
                           //La mise en place du nouveau filtre va déclencher "CollectionChanged" à la fin normalement.
                           view.Filter = new Predicate<object>(FilterCallback);
                        }
                    });
    Voilà, avec ça normalement il ne remettra le curseur en place que lorsqu'il notifiera que la collection a changé à cause de la mise en place du filtre...
    Tu m'en diras des nouvelles.

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    Bon Bon Bon ... Il doit y avoir un canard quelque part !
    Je n'ai toujours pas ce foutu sablier lorsque la listview est un peu volumineuse et que le traitement prend du temps ...
    Mon objet view c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ICollectionView view = CollectionViewSource.GetDefaultView(listViewDevices.Items);
    Sachant que la listView fait du binding sur une ObservableCollection<T>.
    Ce serait lié à l'ObservableCollection ?

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Petit Rasta Voir le message
    Mon objet view c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ICollectionView view = CollectionViewSource.GetDefaultView(listViewDevices.Items);
    Oui, j'ai bien compris cela... ça ne fonctionne pas ce que je viens de te mettre? Tu l'as essayé?

    Si ça ne fonctionne pas, peux-tu me montrer ton projet complet? Je le regarderai alors quand j'aurais du temps...

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    Bonjour,

    J'ai mis un peu de temps à répondre ...
    Oui j'ai testé le code ci-dessus et le sablier n'apparaît pas en exécution normale.
    Par contre, j'ai remarqué qu'en exécutant le code en pas à pas, le sablier est bien présent lors de l'exécution de la fonction FilterCallback.
    Je ne comprends pas pourquoi il ne s'affiche pas du coup

  16. #16
    Invité
    Invité(e)
    Par défaut
    Rebonjour,
    Est-ce que ce ne serait pas tout simplement parce que l'exécution de "FilterCallback" serait très rapide?
    Bon je dis peut-être n'importe quoi mais on ne sait jamais.

    Si ce n'est pas la bonne réponse, il faudrait que tu montres plus de code, notamment ce qu'il y a dans la fonction "FilterCallback"...

  17. #17
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 200
    Points : 76
    Points
    76
    Par défaut
    J'ai continué mes petits tests et j'ai un peu avancé.
    J'ai mis un Sleep dans la fonction "FilterCallback" et là, le sablier est présent pendant l'exécution.
    Ce que j'ai remarqué c'est qu'après l'appel à "FilterCallback", il y a des appels pour chaque ligne à un des accesseurs de mon objet (vu en faisant du pas à pas après la fonction).
    Je ne sais pas du tout pourquoi c'est cet accesseur qui est appelé parce qu'il n'a aucun lien avec mon filtre ^^
    Au final ce sont ces appels qui prennent du temps et qui ne sont pas pris en compte par le sablier.

Discussions similaires

  1. Remplir une ListView avec le contenu d'une requête
    Par callo dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 19/10/2006, 08h44
  2. Filtrer une requete avec un autre parametre
    Par fadedstar dans le forum Access
    Réponses: 1
    Dernier message: 25/05/2006, 12h02
  3. Filtrer une requete avec une variable array
    Par hugo69 dans le forum Requêtes
    Réponses: 7
    Dernier message: 04/11/2005, 14h33
  4. Remplir une ListView avec une BD
    Par manikou dans le forum MFC
    Réponses: 1
    Dernier message: 17/05/2005, 09h48
  5. comment filtrer une table avec deux criteres càd 2 colonnes
    Par athmane2dz dans le forum Bases de données
    Réponses: 7
    Dernier message: 28/07/2004, 15h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo