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

C# Discussion :

Element supprimé d'une BindingList


Sujet :

C#

  1. #1
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut Element supprimé d'une BindingList
    Bonjour,

    Si je supprime un élément d'une BindingList définie comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    BindingList<Test> tests = new BindingList<Test>
    {
    	new Test { Name = "aaa"},
    	new Test { Name = "bbb"},
    	new Test { Name = "ccc"}
    };
    est-il définitivement perdu ou existe t-il encore ? Y a t-il un moyen de le récupérer dans la méthode appelée par l'évènement ListChanged ?

    merci d'avance pour votre aide.

    mathmax
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  2. #2
    Rédacteur
    Avatar de Thomas Lebrun
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    9 161
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Points : 19 434
    Points
    19 434
    Par défaut
    Je ne suis pas sur de bien comprendre ta question: si tu supprimes un élément d'une list, comment veux-tu être en mesure de le récupéré puisque u viens de le supprimer

    Ensuite, ListChanged permet de savoir quel type de modification a été faîte, mais c'est tout

  3. #3
    Membre expert
    Avatar de hed62
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2007
    Messages
    2 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 029
    Points : 3 134
    Points
    3 134
    Par défaut
    Je pense qu'il désire récupérer l'instance de l'objet qui viens d'être retiré de la liste... C'est bien ca ?
    Hervé Delannoy, Ingénieur études&développement.

    Je n'accepte pas les demandes de mise en relation MSN/yahoo sans motif.
    ------------------------------------------------------------------------
    Si , ni , ne peuvent vous aider, mais nous oui, pensez à un pti et au !
    Merci de vous relire
    ____________________________________________________________________________________
    Recherche joueurs de "Magic" sur Lille et environs.
    Donner plutôt que jeter.

  4. #4
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    oui c'est ça.
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  5. #5
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Salut,

    BindingList<T> a une fonction protégée RemoveItem(int index) qui est surchargeable. Rien t'empêche de dériver de BindingList et de faire le traitement qui va bien (balancer un event, sauvegarder quelque part, etc.) avant de supprimer effectivement ton objet
    ಠ_ಠ

  6. #6
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Oui j'envisageais cette solution, mais je me demandais si une instance qui n'existe que dans une collection est détruite lorsqu'on la supprime de cette collection...
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  7. #7
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par maa Voir le message
    Oui j'envisageais cette solution, mais je me demandais si une instance qui n'existe que dans une collection est détruite lorsqu'on la supprime de cette collection...
    Quand tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    protected override RemoveItem(int i)
    {
    ... // ici, l'objet qui va disparaître doit être this[i]
    base.RemoveItem(int i);
    }
    A priori, là où j'ai mis ..., l'objet existe encore. A tester, mais je suis relativement confiant
    ಠ_ಠ

  8. #8
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    oui c'est sûr qu'il existe encore. La question c'est : est-ce qu'il existe toujours (en dehors de la collection bien sûr) après "base.RemoveItem(int i);" ? Ou est-ce que l'instance est détruite à jamais... ?
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  9. #9
    Membre expert
    Avatar de hed62
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2007
    Messages
    2 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 029
    Points : 3 134
    Points
    3 134
    Par défaut
    Essaie en affectant une variable globale à this[i] dans le code montré, et attaque cette avriable globale juste après la résolution de l'Event, tu seras fixé
    Hervé Delannoy, Ingénieur études&développement.

    Je n'accepte pas les demandes de mise en relation MSN/yahoo sans motif.
    ------------------------------------------------------------------------
    Si , ni , ne peuvent vous aider, mais nous oui, pensez à un pti et au !
    Merci de vous relire
    ____________________________________________________________________________________
    Recherche joueurs de "Magic" sur Lille et environs.
    Donner plutôt que jeter.

  10. #10
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par maa Voir le message
    oui c'est sûr qu'il existe encore. La question c'est : est-ce qu'il existe toujours (en dehors de la collection bien sûr) après "base.RemoveItem(int i);" ? Ou est-ce que l'instance est détruite à jamais... ?
    Ca, c'est le boulot du Garbage Collector, pas le nôtre. Cest comme quane tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    object bidule = new object();
    bidule = null;
    L'objet doit pas être supprimé de suite, je suppose, mais il n'est plus référencé nulle part et n'est donc plus accessible sauf peut être par quelques méthodes liées au GC.

    Evidemment, si l'objet de ta bindinglist était référencé ailleurs, sa suppression de la bindinglist ne le supprime pas. Là encore, à part dans des namespace faits pour (style Refelection et tout le méta-bazar ), je ne crois pas qu'il y ait de moyen simple de connaître les références d'un objet donné. Je reviens à ce que je disais en début de post : c'est le boulot du GC
    ಠ_ಠ

  11. #11
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Essaie en affectant une variable globale à this[i] dans le code montré, et attaque cette avriable globale juste après la résolution de l'Event, tu seras fixé
    Oui c'est clair qu'elle sera conservée. Mais je disais : "une instance qui n'existe que dans la collection".

    L'objet doit pas être supprimé de suite, je suppose, mais il n'est plus référencé nulle part et n'est donc plus accessible sauf peut être par quelques méthodes liées au GC.
    C'est la question que je me posais : Si un objet n'est plus référencé null part est-il supprimé par le GC ? Ok, tu supposes que non. Connais-tu les méthodes qui permettraient de le récupérer ?
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Si l'objet n'est plus referencé nul part, alors oui tu sais qu'il sera collecté, apres parler de destruction en soit ou savoir quand, on n'en sait rien, 'le GC à ses raisons que la raison ne connait pas' !

    A ma connaissance (a prendre au conditionnel), tu ne peux pas recuperer un objet sans reference, donc supprimer p'tete bin que oui, p'tete bin que non, mais innaccessible c'est quasi sur. Donc si tu veux retravailler (eventuellement) sur un objet, il te faut une reference quelque part.

  13. #13
    Membre expert
    Avatar de hed62
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2007
    Messages
    2 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 029
    Points : 3 134
    Points
    3 134
    Par défaut
    Citation Envoyé par SirJulio Voir le message
    Si l'objet n'est plus referencé nul part, alors oui tu sais qu'il sera collecté, apres parler de destruction en soit ou savoir quand, on n'en sait rien, 'le GC à ses raisons que la raison ne connait pas' !

    A ma connaissance (a prendre au conditionnel), tu ne peux pas recuperer un objet sans reference, donc supprimer p'tete bin que oui, p'tete bin que non, mais innaccessible c'est quasi sur. Donc si tu veux retravailler (eventuellement) sur un objet, il te faut une reference quelque part.
    Tout a fait d'accord !
    Hervé Delannoy, Ingénieur études&développement.

    Je n'accepte pas les demandes de mise en relation MSN/yahoo sans motif.
    ------------------------------------------------------------------------
    Si , ni , ne peuvent vous aider, mais nous oui, pensez à un pti et au !
    Merci de vous relire
    ____________________________________________________________________________________
    Recherche joueurs de "Magic" sur Lille et environs.
    Donner plutôt que jeter.

  14. #14
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Ok alors je vous explique où je voulais en venir. Peut-être trouverez-vous une solution.

    J'aimerais pour une collection donnée (de type BindingList<T>), créer une vue filtrée de cette collection.

    Une solution serait d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    var filtredList = list.Where(MonPredicat);
    Cela fonctionne, mais la méthode Where est appelée à chaque appel sur filtredList, ce qui n'est pas très performant...
    J'aimerais que le filtrage ne soit refait que si ma liste d'origine change ou mieux, que si ma liste est une nouvelle instance, chaque changement étant répercuté dans ma vue filtrée.
    Il me faut pour cela capter les événements de ma BindingList et mettre à jour ma vue filtrée. D'où mon problème : Je capte un événement "ListChangedType.ItemDeleted", mais je ne sais pas quel élément a été supprimé puisqu'il est irrécupérable après le Remove. Je connais l'index de l'élément supprimé, mais il ne m'est pas facilement utilisable car il ne correspond pas à la position dans la vue filtrée...
    Une solution ? A part dériver BindingList qui ne m'arrange pas vraiment...
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Salut,

    m'est d'avis qu'overrider la method Remove(int) reste la meilleure solution, tu lances un event perso, dans la methode en cherchant dans la liste l'element supprimé par son index, puis tu appelles la base (qui supprimera l'element).

    ca ne modifie en rien le reste de ton logiciel est tu auras juste à caster une fois ta bindinglist pour attacher le callback.

    Mais AMHA, supprimer d'une collection pour filtrer, c'est tres bourrin, l'evaluation bien que à evaluation quasi constante, permet d'eviter de manipuler une collection juste pour filtrer des données, et sans faire des Add et Remove en permanence (c'est autrement plus couteux qu'une evaluation, je pense).

  16. #16
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par maa Voir le message
    Ok alors je vous explique où je voulais en venir. Peut-être trouverez-vous une solution.
    Je pense que la seule solution (à part tripatouiller le GC, ce que je te déconseille) est de garder dans ta vue la position des objets dans la source.

    Mais je comprends bien ta problématique : quand on veux échapper aux datatable / dataset / dataview, on se jette sur les bindinglist. Mais elles ne font ni filtre ni tri... Microsoft n'a pas cru utile de fournir une implémentation de IBindingListView, qui est à peu près tout ce dont a besoin un DataGridView par exemple. Après avoir pas mal cherché sur le net, je suis tombé sur la (tadam) BindingListView : http://sourceforge.net/projects/blw
    C'est pas la seule solution de ce type mais je l'utilise en production depuis quelques temps et elle me satisfait bien. Elle est à la BindingList ce que la DataView est à la DataTable. Et ce projet, qui a le même problème que le tien, se débrouille en retenant la position de l'objet dans la source.
    ಠ_ಠ

  17. #17
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    ca ne modifie en rien le reste de ton logiciel est tu auras juste à caster une fois ta bindinglist pour attacher le callback.
    Si car j'utilise de BindingList dans mon code et j'ai moyennement envie d'aller les changer une à une en BindingListExtend...
    Je pense que la seule solution (à part tripatouiller le GC, ce que je te déconseille) est de garder dans ta vue la position des objets dans la source.
    C'est justement ce que je commençais à bricoler. Voici un premier jet d'une méthode d'extension qui garde en mémoire un dictionary contenant les position de ma liste d'origine et ses éléments et répercute les modifications de la BindingList dans ce dictionary :

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
         public static class BindingListExtension
        {
            private static IBindingList internalList;
            private static Dictionary<int, object> internalFilteredList;
            private static bool hasChanged = true;
     
            public static IEnumerable<T> View<T>(this BindingList<T> list, Func<T, bool> filter) where T: class
            {
                if (internalList != list)
                {
                    Action Init = new Action(()=>
                        {
                            internalList = list;
     
                            internalFilteredList = new Dictionary<int, object>();
                            for (int i = 0; i < internalList.Count; i++)
                            {
                                var item = internalList[i];
                                if (filter(item as T))
                                    internalFilteredList.Add(i, item);
                            }
                        });
     
                    Init();
     
                    internalList.ListChanged += new ListChangedEventHandler((s, e) =>
                        {
                            int i = e.NewIndex;
                            if (e.ListChangedType == ListChangedType.ItemDeleted)
                                internalFilteredList.Remove(i);
                            else if (e.ListChangedType == ListChangedType.ItemAdded)
                                internalFilteredList.Add(i, internalList[i]);
                            else if (e.ListChangedType == ListChangedType.Reset)
                                Init();
                        });
                }
     
                //return internalFilteredList.Values.Cast<T>();
     
                foreach (var item in internalFilteredList.Values.Cast<T>())
                    yield return item;
            }
     
            private static BindingList<T> ToBindingList<T>(this IEnumerable<T> en)
            {
                BindingList<T> b = new BindingList<T>();
                foreach (T item in en)
                    b.Add(item);
                return b;
            }
        }
    Mais je crois que je vais m'arrêter là, pour plusieurs raisons :
    - quand j'insère/supprime un élément dans ma bindingList, il faut mettre à jour les clés de mon dictionary ce qui risque d'être assez gourmands en performance... (il faut supprimer et ajouter un nouvelle paire)
    - A chaque appel, je suis obligé de faire un cast sur internalFilteredList.Values ce qui n'est pas le top non plus...


    Mais AMHA, supprimer d'une collection pour filtrer, c'est très bourrin, l'évaluation bien que à évaluation quasi constante, permet d'éviter de manipuler une collection juste pour filtrer des données, et sans faire des Add et Remove en permanence (c'est autrement plus coûteux qu'une évaluation, je pense).
    Ca doit dépendre du filtre que l'on fait, mais j'avoue ne pas connaître les performance des Add() et Remove(). Mais il faut aussi prendre en compte qu'il ne concerne généralement qu'un ou 2 éléments dans mon cas. Et la liste d'origine change très peu comparée aux appels sur la vue filtrée...

    Après avoir pas mal cherché sur le net, je suis tombé sur la (tadam) BindingListView : http://sourceforge.net/projects/blw
    oui j'avais déjà regardé des sources de genre (je sais pas si c'est exactement celle là) mais je filtrage était refait à chaque appel sur cette vue il me semble...
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  18. #18
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    J'ai regardé ta BindingListView. Elle est pas mal. J'aimerais cependant déclencher le filtrage dans un Thread afin de pouvoir l'interrompre si un autre filtrage est demandé avant que le premier ne soit finit.
    J'ai transformé un peu la propriété Filter comme ceci :

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
            public IItemFilter<T> Filter
            {
                get
                {
                    return _filter;
                }
                set
                {
                    // Do not allow a null filter. Instead, use the "include all items" filter.
                    if (value == null) value = IncludeAllItemFilter<T>.Instance;
                    if (_filter != value)
                    {
                        _filter = value;
                        if (thrFilter != null)
                            thrFilter.Abort();
     
                        thrFilter = new Thread(() =>
                            {
                                FilterAndSort();
                                // The list has probably changed a lot, so get bound controls to reset.
                                OnListChanged(ListChangedType.Reset, -1);
                            });
     
                        thrFilter.Priority = ThreadPriority.Lowest;
                        thrFilter.Start();
                    }
                }
            }
    Le problème est que mon contrôle auquel ma listeview est bindée n'est plus mis à jour. Je pense que c'est parce que l'événement listChanged n'est pas déclenché dans le même Thread que celui dans lequel on a fait le binding. Auriez-vous une idée pour résoudre ce problème ?

    Merci.

    mathmax
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

Discussions similaires

  1. Supprimer efficacement une table
    Par stigma dans le forum Access
    Réponses: 5
    Dernier message: 09/02/2006, 16h43
  2. element selectionné d une liste
    Par tioseb dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 31/01/2006, 13h47
  3. Réponses: 1
    Dernier message: 26/10/2005, 09h15
  4. Bases à supprimé après une installation de SQL Server ?
    Par webtheque dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 29/03/2005, 16h57
  5. [WSAD 5.1.2] [CVS] Supprimer/Créer une branche...
    Par Scoubidoo dans le forum Eclipse Java
    Réponses: 4
    Dernier message: 03/08/2004, 10h30

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