Цвет фона NumericUpDown не работает должным образом

Недавно у меня возникла необходимость написать версию элемента управления Windows NumericUpDown, в которой можно было бы указать, является ли значение обязательным. Это нужно было сделать, изменив задний цвет элемента управления. Я думал, что это будет достаточно просто, но, пытаясь это сделать, я обнаружил, что у него есть странный побочный эффект, заключающийся в том, что он не полностью контролирует ситуацию.

Используя код ниже, я вижу это:

Когда я удаляю элемент управления в форме Windows и изменяю свойство BackColor(ie. to Blue)вся часть номера элемента управления меняет цвет. Если, в качестве альтернативы, я изменю свой & quot; IsMandatory & quot; свойство, не совсем все изменения цвета спины(it leaves a border), Итак, если я изменю BackColor на Blue, а затем установлю IsMandatory на True, я получу элемент управления LightBlue(the mandatory colour) с синей каймой.

Я не могу понять, почему это должно быть, учитывая, что они оба используют один и тот же код.

Идеи или объяснения с благодарностью приняты.

   public partial class MyNumericUpDown : NumericUpDown
   {
      private Boolean _isMandatory = false;
      private Color _mandatoryBackColor = Color.LightBlue;
      private Color _backColor = Color.FromKnownColor(KnownColor.Window);

      [DefaultValue(typeof(Color), "Window"), Description("Overridden property")]
      override public Color BackColor
      {
         get { return _backColor; }
         set
         {
            _backColor = value;
            MyResetColors();
         }
      }

      [DefaultValue(typeof(Color), "LightBlue"), Category("Appearance")]
      public Color MandatoryBackColor
      {
         get {return _mandatoryBackColor;}
         set 
         {
            _mandatoryBackColor = value;
            MyResetColors();
         }
      }

      [DefaultValue(false), Category("Behavior")]
      public Boolean IsMandatory
      {
         get { return _isMandatory; }
         set
         {
            _isMandatory = value;
            MyResetColors();
         }
      }

      private void MyResetColors()
      {
         base.BackColor = (this.IsMandatory ? this.MandatoryBackColor : this.BackColor);
      }
   }

Here's what it looks like:

 Xan-Kun Clark-Davis08 окт. 2015 г., 13:38
Вы уверены, что это не просто проблема перерисовки / обновления? У меня была та же проблема, и когда я принудительно перерисовывал (выводил другое окно на передний план или изменял размеры формы, пока соответствующий элемент управления больше не был виден), он перекрашивал элемент управления с правильными цветами и без дополнительной «границы».

Ответы на вопрос(3)

Решение Вопроса

Интересный вопрос, он демонстрирует, как переопределение виртуальных членов может иметь неожиданные побочные эффекты. Основной проблемой является ваш метод получения свойства BackColor, он всегда возвращает значение свойства _backColor, даже если вы принудительно присвоили ему другое значение с помощью IsMandatory. Это свойство get также используется Winforms, когда ему нужно нарисовать фон элемента управления. Таким образом, вы вернете синий, который объясняет, почему вы видите синий на скриншоте.

Но, как ни странно, это все еще работает для текстовой части элемента управления. Это потому, что NumericUpdown состоит из нескольких элементов управления. У вас есть ContainerControl, который устанавливает внешние границы и является базовым классом, вы переопределяете его свойство BackColor. Но внутри него есть два других элемента управления: TextBox, который отображает текст, и элемент управления, который отображает кнопки вверх / вниз. Ваше переопределение свойства BackColor делаетnot переопределить их свойства BackColor. Таким образом, часть текстового поля будет отображаться с цветом, назначенным для Base.BackColor

Чтобы это исправить, вам придется прекратить ворчать о BackColor. С дополнительным ограничением, которое вам необходимо убедиться, что это все еще работает во время разработки, чтобы фактический BackColor был сериализован, а не MandatoryColor:

[DefaultValue(typeof(Color), "Window"), Description("Overridden property")]
override public Color BackColor {
    get {
        return base.BackColor;
    }
    set {
        _backColor = value;
        MyResetColors();
    }
}

private void MyResetColors() {
    base.BackColor = this.IsMandatory && !DesignMode ? this.MandatoryBackColor : _backColor;
}
 Black Light18 мая 2012 г., 08:51
Спасибо, Ганс. Да, это имеет смысл повторно. базовый элемент управления, желающий узнать свой BackColor и использующий мой переопределенный метод получения свойств, - я не думал об этом. Как ни странно (хотя это не появлялось в этом простом тесте), в «реальном» В версии этого кода оказалось, что элемент управления в некоторых случаях не заполняет фон вообще. Вы могли видеть фрагменты текста и тому подобное между внутренним элементом управления textbox и границей элемента управления UpDown. Самое странное. В конце концов, я только что создал «OptionalBackColor». собственность и оставил BackColor в покое. Еще раз спасибо, Росс.

Вышеуказанный метод не сработал для меня. Мой обходной путь был:

    private void smartRefresh()
    {
        if (oldBackColor != BackColor) {
            oldBackColor = BackColor;
            Hide();
            Application.DoEvents();
            Show();
            Application.DoEvents();
        }
    }

С приватным членом oldBackColor.

Теперь он всегда показывает правильно, но не мерцает.

Приложение. Я думаю, что какая-то часть элемента управления вообще не окрашивается (я считаю это ошибкой) как "неправильно окрашенная". Босс вокруг него не одинаково окрашен, и иногда можно увидеть следы окна, которое было там прежде.

Windows не полностью / правильно перерисовывает элемент управления NumericUpDown, когда он отключен.

Смотрите этот пост:Изменение цвета фона NumericUpDown для отключенного элемента

Включение / отключение элемента управления после его отображения - это обходной путь.

Ваш ответ на вопрос