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 Forms Discussion :

[C#] Collections et sérialisation... galère [FAQ]


Sujet :

Windows Forms

  1. #1
    Membre régulier Avatar de Ingham
    Profil pro
    Inscrit en
    Août 2002
    Messages
    156
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 156
    Points : 75
    Points
    75
    Par défaut [C#] Collections et sérialisation... galère
    Bonjour à tous

    Je dois souvent (comme beaucoup sûrement ) pour certains projets, créer des nouveaux composants, hors là je bute sur un problème dont j'entends parler un peu partout, je trouve parfois des "idées de solution" mais c'est vachement complexe pour ce que c'est, et en plus, ça ne marche jamais chez moi

    J'explique...
    Je créé un composant, et je veux, simplement, lui ajouter une Collection en propriété...
    Comme pour une comboBox par exemple, sa propriété Items...
    Jusque là pas de soucis, je me créé une class Collection, et je l'applique et j'en fais une propriété sur mon composant

    Ca marche !
    Sauf que ...
    En Design-Time, quand j'ajoute des objets à ma collection, que je fais OK et que je reviens dans ma collection... je la retrouve vide... idem quand je compile (run-time donc)...
    La seule solution pour que mes items restent, serait d'ajouter les items à la collection par code... Mais c'est pas pratique du tout, surtout dans mon cas J'ai vraiment besoin que tout se fasse par l'IDE.

    Donc concrètement...:
    : Comment faire une sérialisation d'une collection, pour qu'elle garde en mémoire les items que j'ai ajouté dans l'IDE... même au moment de la compilation !


    Le code...

    Ma collection:
    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
     
        [Serializable]
        public class MaCollection : CollectionBase
        {
            public MaCollection() : base()
    	{}
            public int Add(MonItem item)
            {
                return List.Add(item);
            }
            public void Insert(int index, MonItem item)
            {
                List.Insert(index, item);
            }
            public void Remove(MonItem item)
            {
                List.Remove(item);
            }
            public bool Contains(MonItem item)
            {
                return List.Contains(item);
            }
            public int IndexOf(MonItem item)
            {
                return List.IndexOf(item);
            }
            public void CopyTo(MonItem[] array, int index)
            {
                List.CopyTo(array, index);
            }
            public MonItem this[int index]
            {
                get { return (MonItem)List[index]; }
                set { List[index] = value; }
            }
        }
    Comme vous le voyez j'ai essayé d'y mettre un Serializable mais ca change queudal...


    Et dans le composant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            private MaCollection _items = new MaCollection();
            public MaCollection Items
            {
                get
                {
                    return _items;
                }
                set
                {
                    _items = value;
                }
            }
    Là aussi j'ai tout essayé, stocker les items de la Collec dans un array au lieu de faire directement _items = value, mais rien n'y fait...


    Voilà j'espère que vous pourrez m'aider...
    Merci d'avance

    Ingham

  2. #2
    Expert éminent
    Avatar de neguib
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 627
    Détails du profil
    Informations personnelles :
    Âge : 63
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 627
    Points : 7 879
    Points
    7 879
    Par défaut
    Salut
    je ne suggères une reponse assez classique, il me semble qu'un classe serializable doit également avoir ses membres serializables, ajoute donc cet attribut devant les propriétés concernées
    Pour le bien de ceux qui vous lisent, ayez à coeur le respect du forum et de ses règles

  3. #3
    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
    Citation Envoyé par neguib
    Salut
    je ne suggères une reponse assez classique, il me semble qu'un classe serializable doit également avoir ses membres serializables, ajoute donc cet attribut devant les propriétés concernées

    +1 pour cette idée

  4. #4
    Membre régulier Avatar de Ingham
    Profil pro
    Inscrit en
    Août 2002
    Messages
    156
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 156
    Points : 75
    Points
    75
    Par défaut
    Non j'ai essayé ca me gardait ma liste seulement dans l'IDE
    Mais j'ai trouvé une solution qui à l'air de marcher nickel, je vous la post ce soir

  5. #5
    Membre régulier Avatar de Ingham
    Profil pro
    Inscrit en
    Août 2002
    Messages
    156
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 156
    Points : 75
    Points
    75
    Par défaut
    Alors comme promis voilà la méthode que j'ai trouvé, des fois que ça serve à quelqu'un
    C'est assez bordélique mais j'ai pas pu faire mieux

    Tout d'abord:
    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
     
        internal class CollectionItemConverter : TypeConverter
        {
            public override Boolean CanConvertTo(ITypeDescriptorContext context, Type destinationType)
            {
                if (destinationType == typeof(InstanceDescriptor))
                    return true;
                return base.CanConvertTo(context, destinationType);
            }
            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
            {
                if (destinationType == typeof(InstanceDescriptor))
                {
                    Type valueType = value.GetType();
                    System.Reflection.ConstructorInfo ci = valueType.GetConstructor(System.Type.EmptyTypes);
                    return new InstanceDescriptor(ci, null, false);
                }
                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    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
     
        [TypeConverter(typeof(CollectionItemConverter))]
        [Serializable]
        public class BaseCollectionItem
        {
            private BaseCollection _collection;
            [Browsable(false)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public BaseCollection Collection
            {
                get { return _collection; }
                set { _collection = value; }
            }
            bool ShouldSerializeCollection()
            { return true; }
            public BaseCollectionItem()
            {
            }
        }
    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
    53
    54
    55
    56
    57
    58
    59
     
        public class BaseCollection : CollectionBase
        {
            #region Vérifications
            private void SetItemCollection(BaseCollectionItem item)
            {
                if (item.Collection != null && item.Collection != this)
                    item.Collection.Remove(item);
                item.Collection = this;
            }
            #endregion
            #region Fonctions internes
            public Int32 Add(BaseCollectionItem item)
            {
                Int32 tmp = -1;
                if (item != null)
                {
                    SetItemCollection(item);
                    tmp = List.Add(item);
                }
                return tmp;
            }
            public void Insert(Int32 index, BaseCollectionItem item)
            {
                if (item != null)
                {
                    SetItemCollection(item);
                    List.Insert(index, item);
                }
            }
            public void Remove(BaseCollectionItem item)
            {
                if (item != null)
                {
                    if (item.Collection == this)
                        item.Collection = null;
                    List.Remove(item);
                }
            }
            public Boolean Contains(BaseCollectionItem item)
            {
                return List.Contains(item);
            }
            public Int32 IndexOf(BaseCollectionItem item)
            {
                return List.IndexOf(item);
            }
            public void CopyTo(BaseCollectionItem[] array, Int32 index)
            {
                List.CopyTo(array, index);
            }
     
            public object this[Int32 index]
            {
                get
                { return (BaseCollectionItem)List[index]; }
            }
            #endregion
        }
    Voilà ces trois types ils sont créés, je les ai placé au fond d'un fichier .cs auquel je ne toucherai probablement plus

    Maintenant, dans le composant, je déclare le type de mon item:
    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
     
        public class MonItem : BaseCollectionItem
        {
            #region Properties
            private string _text;
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public string Text
            {
                get { return _text; }
                set { _text = value; }
            }
            bool ShouldSerializeText()
            { return true; }
            #endregion
            public MonItem()
            {
            }
            public MonItem(string Text)
            {
                this.Text = Text;
            }
        }
    Voilà, là, faudra, pour chaque propriété, mettre [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] devant et bool ShouldSerializenomdelapropriété(){ return true; } après

    Et pour la collection:
    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
     
        public class MaCollection : BaseCollection
        {
            public Int32 Add(MonItem item)
            {
                return base.Add(item);
            }
            public Int32 Add(string Text)
            {
                return base.Add(new MonItem(Text));
            }
            public void Insert(Int32 index, MonItem item)
            {
                base.Insert(index, item);
            }
            public void Remove(MonItem item)
            {
                base.Remove(item);
                ((IDisposable)item).Dispose();
            }
            public bool Contains(MonItem item)
            {
                return base.Contains(item);
            }
            public Int32 IndexOf(MonItem item)
            {
                return base.IndexOf(item);
            }
            public void CopyTo(MonItem[] array, Int32 index)
            {
                base.CopyTo(array, index);
            }
            public new MonItem this[Int32 index]
            {
                get
                {
                    return (MonItem)List[index];
                }
                set
                {
                    List[index] = value;
                }
            }
        }
    Là, rien de spécial...

    Et pour finir, dans le composant final:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    private MaCollection _items = new MaCollection();
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public MaCollection Items
        {
            get { return _items; }
            set
            {
                _items = value;
                this.Invalidate();
            }
        }
    bool ShouldSerializeItems()
    { return true; }
    Là, pareil que plus haut pour le DesignerSerializationVisibility, en mode Content cette fois, et le ShouldSerializexxxx


    Voilà, merci de vous être interessés à mon problème en tout cas
    Bonne nuit

    Ingham

  6. #6
    Expert éminent
    Avatar de neguib
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 627
    Détails du profil
    Informations personnelles :
    Âge : 63
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 627
    Points : 7 879
    Points
    7 879
    Par défaut
    Salut, beau travail tout de même
    Bien que résolu, il serait souhaitable que ce post ne soit pas trop vite delesté, je crois que l'on pourait tirer du code offert par Ingham (en le nettoyant un peu ) quelques Q/R interressantes.
    Pour le bien de ceux qui vous lisent, ayez à coeur le respect du forum et de ses règles

  7. #7
    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
    On va en effet mettre ca dans la FAQ



  8. #8
    Membre régulier Avatar de Ingham
    Profil pro
    Inscrit en
    Août 2002
    Messages
    156
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 156
    Points : 75
    Points
    75
    Par défaut
    Merci
    Et pas de problème pour le code (En effet un petit nettoyage serait sûrement nécessaire, y'a probablement des choses inutiles mais j'ai préféré mettre tout ce que je savais, pour être sûr que ça marche )

  9. #9
    Expert éminent
    Avatar de neguib
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 627
    Détails du profil
    Informations personnelles :
    Âge : 63
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 627
    Points : 7 879
    Points
    7 879
    Par défaut
    Ohlala
    j'ai comme un gros doute, rassures toi c'est peu de chose mais je me demandes si finalement tu n'avais pas déjà à ta disposition un typeConverter tout fait
    As-tu essayer d'utiliser ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    [TypeConverter(typeof(CollectionConverter))] 
    [Serializable] 
    public class BaseCollectionItem 
     {//...
    CollectionConverter est une classe existante et dérivée de TypeConverter :
    Pour le bien de ceux qui vous lisent, ayez à coeur le respect du forum et de ses règles

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Sérialisation de collection en XML
    Par MrWeb dans le forum VB.NET
    Réponses: 1
    Dernier message: 29/03/2007, 11h38
  2. [Débutant] Problème de sérialisation collection
    Par Michel Hubert dans le forum VC++ .NET
    Réponses: 1
    Dernier message: 21/12/2006, 15h17
  3. Réponses: 6
    Dernier message: 22/05/2006, 20h12
  4. [VB.NET] Comment peut-on sérialiser une Collection ?
    Par Jabbal'H dans le forum VB.NET
    Réponses: 6
    Dernier message: 09/03/2006, 21h24
  5. [VB.NET] Sérialisation XML de Collections
    Par nico-pyright(c) dans le forum Windows Forms
    Réponses: 8
    Dernier message: 15/12/2004, 15h28

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