Création d'un controle type liste [Résolu]

Signaler
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
-
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
-
Bonsoir,
J'ai déjà créé de nombreux controles Windows (allant d'un color picker à une liste d'images, passant pas une progressbar) et tout fonctionne parfaitement bien. Toutefois, et c'est le cas à chaque fois, le développement d'un controle de type liste comme la listview ou la treeview me titille le cerveau :)
Ma question est: comment structurer le controle pour que les modifications apporté à sa liste d'éléments se répercute sur l'affichage. J'ai évidement trouvé des solutions, mais je voudrais savoir comment le font les vrais pro, dans le but d'avoir une base solide dans la création de ce genre de controles.

Prenons par exemple un controle qui affiche une liste d'image:

Public Class ImageListBox
    Inherits UserControl
   
    Private _Items as new ImageListBoxItemCollection
    Public Readonly Property Items as ImageListBoxItemCollection
       Get
          return _Items
       End Get
    End Property

End Class

Je voudrais donc savoir comment les modifications apportées à Items doivent être intercepté pour mettre à jour l'affichage (dans l'événement Paint du controle par exemple).

Les solutions que j'ai déjà utilisé:
- Ajouter des événements à la collection ImageListBoxItemCollection pour signaler un ajout, une suppression ou une modification d'un Item. Solution que je pense correcte si on à de toute facon l'intention d'y implémenter ces événement publique
- Créer une collection dérivé ou on implémente des événements signalant les modifications. Ca permet de ne pas les rendres accessibles publiquement

- Créer une collection dérivé de ImageListBoxItemCollection, et lui ajouter une nouvelle propriété servant à définir un objet qui permet de dessiner sur le control (un renderer), et enfin, faire des OverRides (Les membres de la classe de base doivent être déclaré OverRidable) ou OverLoader tous les membres qui modifient la liste et y ajouter du code qui modifie l'affichage (à travers le renderer).Déclarer la collection interne (private) du control avec cette classe dérivée, mais faire un cast vers la classe de base dans la propriété publique Items.

Voilà pour les modifications de la collection, c'est pas bien compliqué jusqu'à là. Ou ça se complique, c'est lorsque on veut savoir qu'une propriété d'un des items de la collection à changé. Ben oui, ces items ont des propriétés définissants leur apparence (Text, BackColor, ForeColor, Image...) et on doit donc forcément savoir lorsque elles changent...

- Implémenter les événements Changed (TextChanged, ImageChanged, BackColorChanged...) dans l'Item. Lorsque un Item est ajouté à la collection, ajouter un Handler pour chaque événement qui nous intéresse pour pouvoir changer l'affichage, et le renlever lorsque l'item est supprimé.
- Sinon, comme avant, en créant des dérivés pour chaque item... qu'il faudra créer à chaque ajout d'item a la collection. Ca donne pas mal de code.

Bon je crois que je vais terminer là le développement de mon idée la dessus, mais j'ai encore quelques d'autres questions :)

Lorsque une propriété est une liste générique ou une de ses dérivés, on a une boite de dialogue très utile qui apparait lorsque on édite cette propriété dans l'IDE en mode création:

Mais lorsque la collection est une classe implémentant ICollection par exemple, celle-ci ne s'affiche pas. Donc ma question est, quel sont les conditions pour que cette boite de dialogue s'affiche, et comment forcer son affichage?

Ensuite, la persistance des items ajoutés. Lorsque on ajoute un item à notre collection, en mode création toujours, ces items ne restent pas dans la collection. Comment faire pour qu'ils y reste, même si on ferme la solution? (j'avais fais ça en VB6 il y a longtemps)

Le mieux serait d'avoir le code source d'un control de type liste complet qui implémente toutes ces possibilités comme exemple, mais je trouve pas ^^

Ma question n'est pas "Comment peut-on faire", mais plutot "Comment doit-on faire" pour cette histoire de mise à jour de l'affichage.

Alors si qqun aurait qqch à dire là dessus, genre un gars de chez microsoft qui pourrait me refiler le code source d'une listview, serait bien sympa ;)

Je vous remercie d'avance

3 réponses

Messages postés
6
Date d'inscription
jeudi 21 octobre 2004
Statut
Membre
Dernière intervention
10 avril 2009

Il y a un attribut qui peut t'aider :
DesignTimeVisible(true)
cet article est d'une grande utilité;
http://www.codeproject.com/KB/cs/dzcollectioneditor.aspx
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
9
Hé ben, mon post n'a pas eu le succès escompté

Ma fois, je continuerai à faire mes contrôles "comme je le sens"

Pour mes questions secondaires, c'est a dire l'affichage de l'éditeur de collection et la persistance des items, j'ai trouvé des réponses:

Affichage de l'éditeur de collection:

Utiliser l'attribut <EditorAttribute()>

Exemple:
<EditorAttribute(GetType(System.ComponentModel.Design.CollectionEditor), GetType(System.Drawing.Design.UITypeEditor))> _
Public Default Readonly Property Items(Index as Integer) as ItemCollection
    ...
End Property

Dans mon cas, j'ai implémenté IList dans ma collection. Avec l'attribut <EditorAttribute()> l'éditeur s'affiche bien, mais la collection est ReadOnly (Bouton Add désactivé)
Je comprends pas pourquoi.. Mais si on hérite de List plutot que d'implémenter IList, c'est OK.

Persistance des items d'un contrôle:

Suffit simplement que les Items soient sérialisables

Exemple:
<Serializable()> _
Public Class GroupListItem
    ...
End Class
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
9
Voilà qui est très intéressant en effet.
Merci d'avoir pris la peine de me donner ce lien, ceci peut être fort utile même si mon post date de plus d'un an

++