2009-06-18 7 views
0

J'ai besoin de créer plusieurs combos pour représenter les valeurs d'énumération. Je veux que les valeurs soient représentées avec un aperçu graphique à gauche et un texte à droite. La partie "prévisualisation" de l'affichage peut être un contrôle, une image ou un autre contenu. J'ai essayé deux approches et échoué à la fois, donc je suis curieux de savoir quelles pourraient être les alternatives. Dans mes tests, l '"aperçu" est un bouton car il est pratique de le créer, mais en réalité il s'agira de contrôles personnalisés ou de contrôles DrawingImage.Comment faire un ComboBox qui affiche du contenu arbitraire dans le modèle d'élément?

Pour la première approche, j'ai décidé d'utiliser ContentPresenter pour afficher le contenu de l'aperçu pour moi. Pour ce faire, j'ai créé un contrôle avec les propriétés et le modèle appropriés. J'ai créé un type de collection qui s'est rempli d'instances de ce contrôle, puis j'ai placé une instance de la collection dans les ressources de ma fenêtre. J'ai lié la propriété ItemSource de ComboBox à cette collection. Cela fonctionne très bien lorsqu'il existe un ComboBox, mais lorsque plusieurs ComboBox utilisent la ressource, l'un des ComboBoxes n'affiche aucune valeur. Je crois que cela est probablement lié au fait que les contrôles sont son contenu, et qu'une sorte de problème de réparation se poursuit. J'ai décidé que c'était la mauvaise façon de l'aborder, et j'ai essayé d'utiliser le ItemTemplate de la ComboBox pour faire mon sale boulot. J'ai redessiné la classe de données pour hériter de DependencyObject au lieu de Control, et utilisé l'ancien style du contrôle comme modèle de données pour le type de données. Cela a toujours des problèmes si plusieurs ComboBoxes se lient à la même instance de ressource; le premier ComboBox affiche correctement le contenu de l'aperçu, mais une fois que vous avez déroulé le deuxième ComboBox, le contenu de l'aperçu disparaît des deux ComboBox. Dans cette approche, l'élément sélectionné ne s'affiche pas non plus dans la zone de liste déroulante, même si j'ai peut-être manqué un autre modèle que je dois définir pour cela. Si je définis directement le DataTemplate en tant que ItemTemplate de la zone de liste déroulante, l'élément sélectionné s'affiche correctement mais ruine le contrôle dans le menu contextuel. Je ne fais absolument pas les choses ici.

La seconde méthode fonctionne si je crée deux instances de la collection dans mes ressources, mais ce n'est pas vraiment pratique. Je pourrais restructurer mon application pour mettre en place les liaisons aux instances privées de la collection dans le code, mais cela semble plutôt méchant. Je pourrais dériver un nouveau ComboBox pour chaque type de collection et l'utiliser automatiquement une nouvelle instance de la collection, mais cela semble trop de travail. Il semble que ce que je veux soit quelque chose qui ne soit pas si rare, mais je n'arrive pas à trouver quelque chose qui fonctionne. Qu'est-ce que je fais mal?

+0

Je suis en train de contourner ce problème en faisant en sorte que la partie d'aperçu soit représentée par un contrôle Image et que le contenu souhaité soit rendu à ImageSource. – OwenP

Répondre

2

Vous ne devez pas utiliser les objets dérivés FrameworkElement comme contenu dans ItemControls, car ils ne peuvent être affichés qu'une seule fois.

À la place, utilisez DataTemplates pour contrôler la manière dont vos éléments sont affichés dans votre zone de liste déroulante. Dans les cas très complexes, vous pouvez utiliser un sélecteur DataTemplate. Bea Stollnitz a un excellent poste à ce sujet here.

+0

J'ai pensé que le premier point faisait partie du problème, mais même lorsque j'utilise DataTemplates, je suis toujours confronté au problème. Comme les deux ComboBox utilisent la même collection source, ils utilisent le même contrôle. – OwenP

+0

Bon, c'est le problème. L'image dérive de FrameworkElement, ce qui signifie qu'elle ne peut pas être réutilisée par différents contrôles, elle ne peut être affichée qu'une seule fois. Au lieu de cela, vous souhaiterez avoir le contrôle Image dans votre DataTemplate et que vos données exposent un ImageSource au lieu d'une image. – micahtan

+0

C'est ce que j'ai accepté dans le dernier commentaire. La solution de contournement que j'utilise actuellement nécessite l'élément de données pour renvoyer un ImageSource où il a renvoyé l'objet.Maintenant, lorsqu'un élément de données souhaite utiliser un contrôle comme aperçu, il est nécessaire d'utiliser un RenderTargetBitmap pour rendre le contrôle à un ImageSource, qui est lié au contrôle Image dans mon DataTemplate. – OwenP

Questions connexes