EXEMPLE DE PROPRIÉTÉ D'OBJET AVEC UN PETIT PLUS DANS LA FENETRE PROPRIETE (STYLE

cs_claudetom Messages postés 115 Date d'inscription jeudi 11 octobre 2001 Statut Membre Dernière intervention 15 octobre 2012 - 14 janv. 2005 à 05:08
cs_Kelpan Messages postés 70 Date d'inscription mercredi 24 avril 2002 Statut Membre Dernière intervention 17 septembre 2006 - 30 juin 2008 à 01:10
cs_Kelpan Messages postés 70 Date d'inscription mercredi 24 avril 2002 Statut Membre Dernière intervention 17 septembre 2006
30 juin 2008 à 01:10
Bon, j'ai trouvé une solution pour mon problème de serialisation.
Je n'ai pas vraiment d'explication sur le pourquoi du comment et ça m'agace un peu.

Je vais garder cette solution pour le moment car c'est la seule que j'ai :-)
En fait, en reprenant l'exemple qu'on a dans ce source, je vais créer dans ma classe Mon_ensemble_de_propriete une variable défaut pour chaque variable

Private NomDefaut As String = ""
Private PrenomDefaut As String = ""

Je vire les attributs DefaultValue au dessus des propriétés et j'ajoute mes méthodes ShouldSerialize(Property) et Reset(Property) dans lesquels je vais tester mes valeurs par défaut.

-----------------------
Public Property Nom As String
Get
Return _Nom
End Get
Set(ByVal Value As String)
_Nom = Value
End Set

Private Function ShouldSerializeNom As Boolean
Return _Nom <> _NomDefaut
End Function

Private Sub ResetNom
_Nom = _NomDefaut
End Sub

'... Idem pour prénom
--------------------

Vous me direz, ça ne change pas grand chose.
Et bien voici la subtilité.

En implémentant ICloneable à la classe, on remarque que la méthode Clone est appelé au moment du design, lorsqu'on affecte la propriété.
Pourquoi ? je ne sais pas encore.

Voilà ce que j'ai fait pour le moment

'*** Clone de la classe
Public Function Clone() As Object _
Implements System.ICloneable.Clone

Me._NomDefaut = Me._Nom
Me._PrenomDefaut = Me._Prenom
Return Me.MemberwiseClone
End Function

Je m'en vais essayer de trouver une explication.
Cela fait quand même une semaine que je trime à trouver une solution et maintenant que j'en ai une, j'aimerais bien être sur que c'est fiable.

Si quelqu'un à une idée, je suis preneur...
cs_Kelpan Messages postés 70 Date d'inscription mercredi 24 avril 2002 Statut Membre Dernière intervention 17 septembre 2006
30 juin 2008 à 00:33
Attention dans le code précédent dans la méthode ConvertTo, la dernière ligne est :

=> MyBase
Return MyBase.ConvertTo(context, culture, value, destinationType)

et non

=> Me
Return Me.ConvertTo(context, culture, value, destinationType)

qui provoque une boucle récursive infinie !!
cs_Kelpan Messages postés 70 Date d'inscription mercredi 24 avril 2002 Statut Membre Dernière intervention 17 septembre 2006
30 juin 2008 à 00:20
Bonjour,
Comme je l'ai indiqué sur la source en c#, j'ai un problème de serialisation lorsqu'on hérite d'un écran sur lequel se trouve le control qui contient ce genre de propriété.
Je n'ai toujours pas trouvé de solution à mon problème

Cependant, je peux apporter ma contribution à ce source en ce qui concerne la classe Converter.
il y avait quelques erreurs ...

If Not destinationType.GetType().Equals(New System.ComponentModel.Design.Serialization.InstanceDescriptor(Nothing, Nothing).GetType()
=> destinationType est déjà un type
=> Inutile de créer une instance de InstanceDescriptor pour obtenir le type
GetType(InstanceDescriptor suffit)

Dim ci As System.Reflection.ConstructorInfo GetType(Mon_ensemble_de_propriete).GetConstructor(Nothing)
> Dans getConstructor, il faut passer une liste de type, même si c'est vide
(New Type(){} = Tableau de type vide)

Return New System.ComponentModel.Design.Serialization.InstanceDescriptor(ci, Nothing, False)
=> Idem dans instance descriptor
(New Object(){} Tableau d'objet vide)
> Pourquoi False pour le dernier argument ?

N.B:
Si on a un constructeur avec en paramètre Nom et Prenom, on peut appeler ce constructeur

Dim ci As System.Reflection.ConstructorInfo = GetType(Mon_ensemble_de_propriete).GetConstructor(New Type(){GetType(String), GetType(String)})

With CType(value, Mon_ensemble_de_propriete)
Return New System.ComponentModel.Design.Serialization.InstanceDescriptor(ci, New Object(){.Nom, .Prenom)
End With

Voilà la classe corrigé :

Public Class Mon_ensemble_de_proprieteConverter
Inherits ExpandableObjectConverter

Public Overloads Overrides Function CanConvertTo( _
ByVal context As System.ComponentModel.ITypeDescriptorContext, _
ByVal destinationType As System.Type _
) As Boolean

If destinationType Is GetType(System.ComponentModel.Design.Serialization.InstanceDescriptor) Then
Return True
End If

Return MyBase.CanConvertTo(context, destinationType)
End Function

Public Overloads Overrides Function ConvertTo( _
ByVal context As System.ComponentModel.ITypeDescriptorContext, _
ByVal culture As System.Globalization.CultureInfo, _
ByVal value As Object, _
ByVal destinationType As System.Type _
) As Object

If _
destinationType Is GetType(String) AndAlso _
TypeOf value Is Mon_ensemble_de_propriete Then

' Permet d'affiche blanc sur le propertyGRid
Return ""
End If

If _
destinationType Is GetType(System.ComponentModel.Design.Serialization.InstanceDescriptor) AndAlso _
TypeOf value Is Mon_ensemble_de_propriete Then

Dim ci As System.Reflection.ConstructorInfo = GetType(Mon_ensemble_de_propriete).GetConstructor(New Type() {})
Return New System.ComponentModel.Design.Serialization.InstanceDescriptor(ci, New Object() {})
End If

Return Me.ConvertTo(context, culture, value, destinationType)
End Function
End Class
BXM44 Messages postés 2 Date d'inscription jeudi 17 août 2006 Statut Membre Dernière intervention 1 décembre 2007
1 déc. 2007 à 13:48
Et maintenant la totale avec des valeurs par défaut, y compris pour des types un peu plus compliqués comme les couleurs et les polices de caractères.
Bon courage à tous.

Imports System.ComponentModel


Public Class UserControl1

Private Arthenius As New Mon_ensemble_de_propriete()

<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public Property Mais_qui_est_Arthenius() As Mon_ensemble_de_propriete
Get
Return Arthenius
End Get
Set(ByVal value As Mon_ensemble_de_propriete)
Arthenius = value
End Set
End Property

End Class

' VOICI LA CLASSE QUI DOIT DEFINIR MES PROPRIETES DEVANT APPARAITRE DANS LA FENETRE PROPRIETE
' AVEC LE PETIT PLUS...

<TypeConverter(GetType(ExpandableObjectConverter))> _
Public Class Mon_ensemble_de_propriete
'
' objets privés initialisés avec les valeurs par défaut
'
Private _Nom As String = "Dupont"
Private _Prenom As String = "Robert"
Private _Couleur As Color = Color.Red
Private _Police As Font = New Font("Microsoft Sans Serif", 8.25!, FontStyle.Bold, GraphicsUnit.Point, CType(0, Byte))
'
' objet privé pour la comparaison par le designer dans ShouldSerialize...
'
Private _PoliceParDefaut As Font = New Font("Microsoft Sans Serif", 8.25!, FontStyle.Bold, GraphicsUnit.Point, CType(0, Byte))
'
' propriétés
'
' <summary> sera rangé dans le fichier XML créé avec la DLL
' un développeur ayant uniquement la DLL et le fichier XML aura à l'écran la description de la propriété
' dès qu'il entrera dans son code objet.propriété
'
' <Description> pour que la description s'affiche dans la fenêtre des propriétés en mode Design
'
' <DefaultValue> pour permettre au Designer de faire apparaître la valeur de la propriété en caractères normaux
' lorsque la valeur est celle par défaut
' pour les autres valeurs que la valeur par défaut, la valeur est affichée en gras dans la fenêtre des propriétés
' Ceci ne s'applique qu'aux types simples : string , boolean , integer , etc...
' Pour les objets compliqués commeles couleurs et les polices de caractères <DefaultValue> ne marche pas
' et doir être remplacé par une fonction ShouldSerialize, voir plus loin.


''' <summary>
''' Nom de l'individu
''' (Valeur par défaut : Dupont)
''' </summary>
<DefaultValue("Dupont")> _
<Description("Nom de l'individu")> _
Public Property Nom() As String
Get
Return _Nom
End Get
Set(ByVal value As String)
_Nom = value
End Set
End Property


''' <summary>
''' Prénom de l'individu
''' (Valeur par défaut : Robert)
''' </summary>
<DefaultValue("Robert")> _
<Description("Prénom de l'individu")> _
Public Property Prenom() As String
Get
Return _Prenom
End Get
Set(ByVal value As String)
_Prenom = value
End Set
End Property


''' <summary>
''' Couleur préférée
''' (Valeur par défaut : Color.Red)
''' </summary>
<Description("Couleur préférée")> _
Public Property Couleur() As Color
Get
Return _Couleur
End Get
Set(ByVal value As Color)
_Couleur = value
End Set
End Property

Private Function ShouldSerializeCouleur() As Boolean
Return Me.Couleur <> Color.Red
End Function


''' <summary>
''' Police préférée
''' (Valeur par défaut : Microsoft Sans Serif 8,25pt Bold)
''' </summary>
<Description("Police préférée")> _
Public Property Police() As Font
Get
Return _Police
End Get
Set(ByVal value As Font)
_Police = value
End Set
End Property

Private Function ShouldSerializePolice() As Boolean
Return Not Me.Police.Equals(_PoliceParDefaut)
End Function

End Class
TigerFab Messages postés 115 Date d'inscription samedi 15 février 2003 Statut Membre Dernière intervention 18 mai 2008
29 nov. 2007 à 18:45
Ok j'ai trouvé ! ouf !

l'auteur en code C# a fait quelque modifications, aller effectivement voir sur http://www.csharpfr.com/code.aspx?ID=25912

En fait vous devez laisser tomber la classe Mon_ensemble_de_propriete_Converter
C'est elle la source du problème.
Pour définir le type de Mon_ensemble_de_propriete, il suffit directement de convertir le type ExpandableObjectConverter : <TypeConverter(GetType(ExpandableObjectConverter
))>

et là plus de soucis !

A+
TigerFab Messages postés 115 Date d'inscription samedi 15 février 2003 Statut Membre Dernière intervention 18 mai 2008
29 nov. 2007 à 18:12
En effet ca plante dans le designer même en 2005

Si on définit son composant par le code pas de problème
Si on affiche pas le designer, pas de problème non plus. Pour preuve on peut compiler et l'exe fonctionnera
Mais dès qu'on affiche le mode design du formulaire contenant le composant à l'écran paf plantage visual studio
TigerFab Messages postés 115 Date d'inscription samedi 15 février 2003 Statut Membre Dernière intervention 18 mai 2008
29 nov. 2007 à 15:36
super !!! voilà ce que je recherchais depuis 1 semaine !

Je mets 10/10 car j'ai galéré pour trouver la solution sur le web....
BXM44 Messages postés 2 Date d'inscription jeudi 17 août 2006 Statut Membre Dernière intervention 1 décembre 2007
7 nov. 2007 à 06:49
Bonjour,
j'ai essayé de mettre le code dans un controle utilisateur
quand on insère le controle dans une forme, cela plante VB2005 express.
Ai-je oublié quelqu chose ?

Merci.

Imports System.ComponentModel

Public Class UserControl1
Private Arthenius As New Mon_ensemble_de_propriete()
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public Property Mais_qui_est_Arthenius() As Mon_ensemble_de_propriete
Get
Return Arthenius
End Get
Set(ByVal value As Mon_ensemble_de_propriete)
Arthenius = Value
End Set
End Property

End Class

'VOICI LA CLASSE QUI DOIT DEFINIR MES PROPRIETES DEVANT APPARAITRE DANS LA FENETRE PROPRIETE AVEC LE PETIT PLUS...

<TypeConverter(GetType(Mon_ensemble_de_propriete_Converter))> _
Public Class Mon_ensemble_de_propriete
Private _Nom As String
Private _Prenom As String
Public Property Nom() As String
Get
Return _Nom
End Get
Set(ByVal value As String)
_Nom = value
End Set
End Property
Public Property Prenom() As String
Get
Return _Prenom
End Get
Set(ByVal value As String)
_Prenom = value
End Set
End Property
End Class

'ICI LE CONVERTER PERMETTANT D'AFFICHER LE PLUS DANS LA FENETRE PROPRIETE

Public Class Mon_ensemble_de_propriete_Converter
Inherits ExpandableObjectConverter
Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
If Not destinationType.GetType().Equals(New System.ComponentModel.Design.Serialization.InstanceDescriptor(Nothing, Nothing).GetType()) Then
Return True
End If
End Function
Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
Dim instancedescripteur As New System.ComponentModel.Design.Serialization.InstanceDescriptor(Nothing, Nothing)
If Not destinationType.GetType() Is instancedescripteur.GetType() Then
Return Me.ConvertTo(context, culture, value, destinationType)
End If
Dim ci As System.Reflection.ConstructorInfo = GetType(Mon_ensemble_de_propriete).GetConstructor(Nothing)
Return New System.ComponentModel.Design.Serialization.InstanceDescriptor(ci, Nothing, False)
End Function
End Class
cs_claudetom Messages postés 115 Date d'inscription jeudi 11 octobre 2001 Statut Membre Dernière intervention 15 octobre 2012
14 janv. 2005 à 05:08
J'ai utilisé ce code pour un groupage, mais ça plante au design de la form un StackOverFlow

Voici ce que j'ai mis :

Class principale du compo :

Private Interpolation As New ProprieteInterpolation
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public Property Prop_Interpolation() As ProprieteInterpolation
Get
Return Interpolation
End Get
Set(ByVal value As ProprieteInterpolation)
Interpolation = value
If Me.DesignMode = True Then
Me.Invalidate()
End If
End Set
End Property

ensuite l'autre class

<TypeConverter(GetType(ProprietesInterpolation_Converter))> _
Public Class ProprieteInterpolation
Private _InterpoTxt As Boolean
Private _ColorBlendp As Single()
Private _ColorBlendc As Color()

Public Property interpolationTxt() As Boolean
Get
Return Me._InterpoTxt
End Get
Set(ByVal Value As Boolean)
Me._InterpoTxt = Value
End Set
End Property

Public Property Positions() As Single()
Get
Return Me._ColorBlendp
End Get
Set(ByVal Value As Single())
Me._ColorBlendp = Value
End Set
End Property

Public Property Colors() As System.Drawing.Color()
Get
Return Me._ColorBlendc
End Get
Set(ByVal Value As System.Drawing.Color())
Me._ColorBlendc = Value
End Set
End Property
End Class

'ICI LE CONVERTER PERMETTANT D'AFFICHER LE PLUS DANS LA FENETRE PROPRIETE
Public Class ProprietesInterpolation_Converter
Inherits ExpandableObjectConverter

Public Overloads Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean

If Not destinationType.GetType().Equals(New System.ComponentModel.Design.Serialization.InstanceDescriptor(Nothing, Nothing).GetType()) Then
Return True
End If

End Function

Public Overloads Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
Dim instancedescripteur As New System.ComponentModel.Design.Serialization.InstanceDescriptor(Nothing, Nothing)

If Not destinationType.GetType() Is instancedescripteur.GetType() Then
Return Me.ConvertTo(context, culture, value, destinationType)
End If

Dim ci As System.Reflection.ConstructorInfo = GetType(ProprieteInterpolation).GetConstructor(Nothing)
Return New System.ComponentModel.Design.Serialization.InstanceDescriptor(ci, Nothing, False)

End Function

End Class

Pourquoi ça plante sous VB v2003 ?
Merci