Search code examples
vb.netwinformsbuttondesign-timeappearance

Control's Enabled appearance at design time?


I defined a custom button class, which sets background color when button is enabled/disabled.

Enabled appearance at runtime (A):

enter image description here

Disabled appearance at runtime (B):

enter image description here

Design time appearance is always (A), regardless of the value of Enabled property.

I would like my control to appear in designer exactly the way it would appear at run time. Is it possible and, if so, how can do it?

Here is what I tried (only relevant parts of the code):

Public Class StyledButton : Inherits Button      
  Private p_fEnabled As Boolean

  <DefaultValue(True)>
  Public Shadows Property Enabled As Boolean
    Get
      Return p_fEnabled
    End Get
    Set(value As Boolean)
      p_fEnabled = value
      MyBase.Enabled = value
      UpdateVisualStyle()
    End Set
  End Property

  Private Sub UpdateVisualStyle()
    If Me.Enabled Then
      'set enabled appearance
    Else
      'set disabled appearance
    End If
  End Sub

End Class

Solution

  • The shadowed property does work as designed at runtime, just not in the IDE. You would not want to loose controls which are Visible = False, and you would want to drill into Button events even when Enabled = False. Since the IDE has no intention of drawing a disabled control, there is no reason for it to invoke Invalidate when you change the property.

    Since it works at runtime, trick it in the designer to use another property which looks like the original:

    <Browsable(False), DebuggerBrowsable(DebuggerBrowsableState.Never),
              EditorBrowsable(False)>
    Public Shadows Property Enabled As Boolean
        Get
            Return neoEnabled
        End Get
        Set(value As Boolean)
            neoEnabled = value
        End Set
    End Property
    

    A new property, with the right name for the IDE.

    <DisplayName("Enabled")>
    Public Property neoEnabled As Boolean
        Get
            Return p_fEnabled
        End Get
        Set(value As Boolean)
    
            p_fEnabled = value
            UpdateVisualStyle()
            MyBase.Enabled = p_fEnabled
    
        End Set
    End Property
    

    Sadly, both Enabled and neoEnabled will be offered by Intellisense in code, but since they both do the same thing, its not a big deal. test code:

    Private Sub UpdateVisualStyle()
        If p_fEnabled Then
            ' other interesting stuff
            MyBase.BackColor = Color.Lime
        Else
            MyBase.BackColor = Color.LightGray
        End If
    
        MyBase.Invalidate()
    End Sub
    

    You have probably wrestled with it more that I, and come up with a cleaner implementation.


    This persists the BackColor associated with neoEnabled state:

    '
    'StyledButton1
    '
    Me.StyledButton1.BackColor = System.Drawing.Color.LightGray
    Me.StyledButton1.Enabled = False
    Me.StyledButton1.neoEnabled = False
    

    versus

    Me.StyledButton1.BackColor = System.Drawing.Color.Lime
    Me.StyledButton1.Enabled = False
    Me.StyledButton1.neoEnabled = True