Внешний вид Control Enabled во время разработки?

Я определил собственный класс кнопки, который устанавливает цвет фона, когда кнопка включена/отключена.

Включенный внешний вид во время выполнения (A):

введите здесь описание изображения

Отключенный внешний вид во время выполнения (B):

введите здесь описание изображения

Внешний вид во время разработки всегда (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

person Neolisk    schedule 06.08.2014    source источник
comment
вы упустили лучшую часть ... установленный включенный/отключенный процесс должен в конечном итоге вызывать Paint обычно через Invalidate   -  person Ňɏssa Pøngjǣrdenlarp    schedule 06.08.2014
comment
@Plutonix: я пытался позвонить Me.Invalidate() в конце UpdateVisualStyle, а также пробовал Me.Refresh(). Тем не менее, никаких изменений в поведении во время разработки. Любые другие идеи?   -  person Neolisk    schedule 06.08.2014
comment
Элементы управления всегда включены в дизайнере. Точно так же, как установка для Visible значения False на самом деле не скрывает элемент управления от US, включенное состояние не изменяется. Они также не работают glow при включении стилей VisualStyle при наведении на них указателя мыши. Некоторые реквизиты доступны только для RT. Возможно, вам также придется изменить UseVisualStyleBackColor, если VisualStyles активны. (установщик реквизита не вызывается в IDE - используйте OnEnableChanged, чтобы увидеть)   -  person Ňɏssa Pøngjǣrdenlarp    schedule 06.08.2014
comment
@Plutonix: я знаю это. Вот почему я создал собственное свойство Enabled, которое затеняет исходное свойство Enabled. Таким образом, теоретически дизайнер должен начать использовать новое свойство, правильно отображая внешний вид Enabled и Disabled.   -  person Neolisk    schedule 06.08.2014
comment
измените имя на neoEnabled, и оно будет работать (с недействительным)   -  person Ňɏssa Pøngjǣrdenlarp    schedule 06.08.2014
comment
@Plutonix: теперь это работает - спасибо. Вы можете опубликовать это как ответ, а также, если вы знаете, почему это не сработало с затененным свойством, поделитесь своими знаниями. UseVisualStyleBackColor, по-видимому, назначается автоматически при установке BackColor, поэтому нет необходимости навязывать его.   -  person Neolisk    schedule 06.08.2014
comment
Я пытался что-то сделать с VisualStyles, но, похоже, в IDE ничего не работает... Думаю, наблюдатель не изменил свойства.   -  person Ňɏssa Pøngjǣrdenlarp    schedule 06.08.2014


Ответы (2)


Затененное свойство работает так, как задумано во время выполнения, но не в среде IDE. Вы бы не хотели потерять элементы управления, которые являются Visible = False, и вы хотели бы детализировать события Button, даже когда Enabled = False. Поскольку среда 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

К сожалению, и Enabled, и neoEnabled будут предлагаться 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

Вы, вероятно, боролись с этим больше, чем я, и придумали более чистую реализацию.


Это сохраняет BackColor, связанный с состоянием neoEnabled:

'
'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
person Ňɏssa Pøngjǣrdenlarp    schedule 06.08.2014
comment
Это не нормально, изменение, внесенное вами в BackColor, будет сохранено. Он всегда будет выглядеть отключенным во время выполнения. - person Hans Passant; 06.08.2014
comment
Я решил сохранить собственное имя свойства (EnabledCustom) и скрыть исходное Enabled. Таким образом, человек, ищущий Enabled, все равно найдет его и узнает, что это такое (пользовательская реализация свойства Enabled). +1 и принимаю. - person Neolisk; 06.08.2014
comment
он фактически уничтожает BackColor как независимое свойство, но сохраняется на основе нового свойства Enabled. neoEnabled был ироничен. - person Ňɏssa Pøngjǣrdenlarp; 06.08.2014
comment
@Plutonix: в моей реализации есть новое свойство BackColorEnabled, а также ForeColorEnabled, в то время как исходные свойства BackColor и ForeColor скрыты. Отключенный внешний вид жестко запрограммирован на серый на сером. Я думаю, что правильным решением было бы создание пользовательского класса дизайнера, который отображает элементы управления в их отключенном состоянии, но это выглядит слишком сложным для этой задачи (учитывая обходной путь). Я размещу здесь ссылку, если кому-то интересно: Как: расширить внешний вид и Поведение элементов управления в режиме конструктора. - person Neolisk; 06.08.2014

Я объясню, почему он так себя ведет. Элемент управления во многом ведет себя во время разработки так же, как и во время выполнения. Он обеспечивает надежную поддержку WYSIWYG в дизайнере Winforms. Но некоторые свойства очень неудобны во время разработки, например, вы бы не хотели, чтобы свойство Visible действовало. Очень важно, чтобы элемент управления оставался видимым, даже если для параметра «Видимость» установлено значение False в окне свойств.

Это основная роль дизайнера элемента управления. Он перехватывает такие сложные свойства и эмулирует их. Отображение предполагаемого значения в сетке свойств, но фактическая передача их в средство установки свойств элемента управления.

Свойство Enabled соответствует этой категории. Если бы он не был перехвачен, элемент управления больше не мог быть выбран. Другие — это ContextMenu, AllowDrop, Location for UserControl и Form и так далее. Ваша замена Shadows не обманет дизайнера, она использует Reflection для поиска свойств по имени. Таким образом, ваше свойство не имеет никакого эффекта, ваш установщик свойств просто никогда не вызывается.

Вы можете действительно получить это, только переопределив OnPaint() для элемента управления, чтобы вы могли отображать другой цвет во время разработки. И кастомный конструктор, чтобы тыкать в него. Однако существенным зависанием является то, что не так просто заменить средство визуализации кнопки, которое реализует метод OnPaint(). Microsoft решила сделать средства визуализации внутренними, их нельзя переопределить.

Слишком много проблем, я рекомендую вам пройти мимо.

person Hans Passant    schedule 06.08.2014
comment
+1. Спасибо Ганс, очень хорошее объяснение. Эта часть отвечает на мой вопрос: it uses Reflection to find properties by name. Хотя я бы предпочел, чтобы дизайнер показывал подсказку для отключенных элементов управления, а также для скрытых элементов управления (Visible = False). Это могла быть рамка какого-то особого цвета и/или узора, наложение со специальным фоном, непрозрачность 50% и т. д. Но я думаю, что Microsoft не видит этого так, как я. :) В моей текущей программе отключенная кнопка означает, что функция не реализована, но может быть реализована. Поскольку это инструмент для разработчиков, отключенное состояние служит точкой расширения. - person Neolisk; 06.08.2014