Francesco Geri

Il blog di Francesco Geri
posts - 94, comments - 165, trackbacks - 2

lunedì 25 febbraio 2013

Come impostare il Default Value tramite attributo di una property

Se definiamo un controllo personalizzato, per esempio un pulsante MyButton, nel quale vogliamo impostare dei valori inziali di una proprietà Browsable ci potrebbe essere utile impostare il DefaultValue tramite attributo (DefaultValueAttribute).

Infatti se non lo facciamo si ha l’inconveniente che l’editor di Visual Studio valorizza esplicitamente nel file .Designer le proprietà che abbiamo inizializzato nel nostro controllo.

Consideriamo l’esempio di un pulsante con un certo Font ed un certo colore:

Imports System.ComponentModel
 
Public Class MyButton
    Inherits Button
 
    Public Sub New()
        'Inizializza le proprietà
        Dim fontConverter As New FontConverter()
        Me.Font = fontConverter.ConvertFromString(Nothing, Globalization.CultureInfo.InvariantCulture, DefaultSerializeFont)
        Dim colorConverter As New ColorConverter()
        Me.ForeColor = colorConverter.ConvertFromString(Nothing, Globalization.CultureInfo.InvariantCulture, DefaultSerializeForeColor)
 
        ' ==========================================
        ' Per ottenere il valore serializzato della proprietà si può usare il metodo
        ' ConvertToString di FontConverter, ColorConverter, etc.
        ' La seguente istruzione produce: serializedSegoeFont = "Segoe UI, 9.75pt"
        Dim serializedSegoeFont As String = fontConverter.ConvertToString(Nothing, Globalization.CultureInfo.InvariantCulture, Me.Font)
 
 
        ' ==========================================
        ' Il seguente codice di esempio stampa il valore del default attribute della proprietà Font
        Dim attributes As AttributeCollection = TypeDescriptor.GetProperties(Me)("Font").Attributes
        Dim myAttribute As DefaultValueAttribute = CType(attributes(GetType(DefaultValueAttribute)), DefaultValueAttribute)
        If myAttribute Is Nothing Then
            Console.WriteLine("The default value is not setted")
        Else
            Console.WriteLine("The default value is: " & myAttribute.Value.ToString())
        End If
    End Sub
 
 
    ' Serializzazione dei valori da usare per il default
    Const DefaultSerializeFont As String = "Segoe UI, 9.75pt"
    Const DefaultSerializeForeColor As String = "65, 65, 65"
 
    <DefaultValue(GetType(Color), DefaultSerializeForeColor)>
    Public Overrides Property ForeColor As Color
        Get
            Return MyBase.ForeColor
        End Get
        Set(value As Color)
            MyBase.ForeColor = value
        End Set
    End Property
 
    <DefaultValue(GetType(Font), DefaultSerializeFont)>
 Public Overrides Property Font As Font
        Get
            Return MyBase.Font
        End Get
        Set(value As Font)
            MyBase.Font = value
        End Set
    End Property
 
End Class

 

In questo modo quando mettiamo un MyButton nella form Visual Studio genere il seguente codice:

Me.MyButton1.Location = New System.Drawing.Point(57, 45)
Me.MyButton1.Name = "MyButton1"
Me.MyButton1.Size = New System.Drawing.Size(183, 56)
Me.MyButton1.TabIndex = 0
Me.MyButton1.Text = "MyButton1"
Me.MyButton1.UseVisualStyleBackColor = True

ovvero non inserisce le 2 righe:

Me.MyButton1.Font = New System.Drawing.Font("Segoe UI", 9.75!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.MyButton1.ForeColor = System.Drawing.Color.FromArgb(CType(CType(65, Byte), Integer), CType(CType(65, Byte), Integer), CType(CType(65, Byte), Integer))

Qual è il problema di quelle 2 righe?

Il problema è che se un giorno decidessimo di cambiare il colore o il font del nostro MyButton e andassimo a modificare la New dell’oggetto ci accorgeremmo che ricompilando i progetti che usavano MyButton questi non si aggiornano. Questo succede perché le 2 righe inserite da visual studio vengono eseguite dopo la new, per cui sovrascrivono i nuovi valori che abbiamo pensato per quelle proprietà.

Impostando invece il DefaultValue informiamo visual studio che quelli sono i valori di default per quelle proprietà e quindi VS non li inserisce esplicitamente se hanno quel valore.

 

Una alternativa che non fa uso di DefaultValueAttribute è quella di sfruttare i metodi ResetPPP e ShouldSerializePPP, dove PPP è la proprietà (vedi questo post).
Ecco esempio:

Private Shared _defaultFont As New System.Drawing.Font("Segoe UI", 9.7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 178, False)
Public Overrides Property Font() As System.Drawing.Font
    Get
        Return (MyBase.Font)
    End Get
    Set(value As System.Drawing.Font)
        If value Is Nothing Then
            MyBase.Font = _defaultFont
        Else
            If value Is System.Windows.Forms.Control.DefaultFont Then
                MyBase.Font = _defaultFont
            Else
                MyBase.Font = value
            End If
        End If
    End Set
End Property
 
Public Overrides Sub ResetFont()
    Font = Nothing
End Sub
 
Private Function ShouldSerializeFont() As Boolean
    Return (Not Font.Equals(_defaultFont))
End Function

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (0) |

Powered by:
Powered By Subtext Powered By ASP.NET