Control's Enabled appearance at design time?

谁都会走 提交于 2020-05-09 05:59:01

问题


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

回答1:


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



回答2:


I'll explain why it behaves this way. A control behaves a lot at design time as it does at runtime. It provides the strong WYSIWYG support in the Winforms designer. But certain properties are very awkward at design time, you would not actually want the Visible property to take effect for example. Pretty important that the control remains visible even though you set Visible to False in the Properties Window.

This is a core role of the designer for a control. It intercepts these kind of difficult properties and emulates them. Showing the intended value in the property grid but not actually passing them on to the control's property setter.

The Enabled property fits this category. If it weren't intercepted then the control couldn't be selected anymore. Other ones are ContextMenu, AllowDrop, Location for UserControl and Form, etcetera. Your Shadows replacement doesn't fool the designer, it uses Reflection to find properties by name. So your property doesn't have any effect, your property setter simply never gets called.

You can only truly get this by overriding OnPaint() for the control so you can display a different color at design time. And a custom designer to poke it. A significant hang-up however is that it isn't simple to replace the renderer for the button, the one that implements the OnPaint() method. Microsoft decided to make the renderers internal, you can't override them.

Way too much trouble, I recommend you pass this up.



来源:https://stackoverflow.com/questions/25162260/controls-enabled-appearance-at-design-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!