控制在设计时启用外观?

时间:2014-08-06 13:54:22

标签: vb.net winforms button design-time appearance

我定义了一个自定义按钮类,它在启用/禁用按钮时设置背景颜色。

在运行时启用外观(A):

enter image description here

运行时禁用外观(B):

enter image description here

设计时间外观始终为(A),与Enabled属性的值无关。

我希望我的控件能够完全按照运行时出现的方式出现在设计器中。是否有可能,如果是的话,怎么做呢?

这是我尝试过的(只是代码的相关部分):

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

2 个答案:

答案 0 :(得分:6)

我将解释为什么它会这样做。控件在设计时的行为与在运行时的行为相同。它在Winforms设计器中提供了强大的WYSIWYG支持。但是某些属性在设计时非常笨拙,你实际上并不希望Visible属性生效。非常重要的是,即使在属性窗口中将Visible设置为 False ,控件仍然可见。

这是控件的设计器的核心角色。它拦截了这些困难的属性并模仿它们。在属性网格中显示预期的值,但实际上没有将它们传递给控件的属性设置器。

已启用属性适合此类别。如果没有截获,则无法再选择控件。其他的是ContextMenu,AllowDrop,UserControl的位置和Form,等等。你的阴影替换并没有欺骗设计师,它使用反射来按名称查找属性。所以你的财产没有任何影响,你的财产制定者根本就不会被召唤。

您只能通过覆盖控件的OnPaint()来实现此目的,这样您就可以在设计时显示不同的颜色。一个定制设计师来戳它。然而,一个重要的问题是,替换按钮的渲染器并不简单,该按钮是实现OnPaint()方法的按钮。微软决定让渲染器内部,你无法覆盖它们。

太麻烦了,我建议你把它传递出去。

答案 1 :(得分:1)

shadowed属性在运行时设计工作,而不是在IDE中。您不希望松开Visible = False的控件,并且即使在Enabled = False时也希望钻取Button事件。由于IDE无意绘制禁用的控件,因此在更改属性时没有理由调用Invalidate。

由于它在运行时工作,因此在设计器中欺骗它以使用另一个看起来像原始属性的属性:

<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

一个新属性,具有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

可悲的是,EnabledneoEnabled都将由Intellisense在代码中提供,但由于它们都做同样的事情,所以它不是什么大问题。测试代码:

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

你可能更多地与我搏斗,并提出更清洁的实施方案。


这会持续与neoEnabled状态关联的BackColor:

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

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