NumericUpDown backcolor not working as expected

时间秒杀一切 提交于 2019-12-20 03:23:35

问题


I recently had the need to write a version of the Windows NumericUpDown control which could highlight whether a value was mandatory. It needed to do this by changing the back colour of the control. I thought this would be simple enough, but in trying to do so, I find that it has a wierd side-effect of not quite drawing all the control.

Using the code below, I am seeing this:

When I drop a control on a Windows form, and change the BackColor property (ie. to Blue), the whole of the control's number part changes colour. If, alternatively, I change my "IsMandatory" property, not quite all of the back colour changes (it leaves a border). So, if I change the BackColor to Blue, and then set IsMandatory to True, I get a LightBlue control (the mandatory colour) with a Blue border.

I cannot see why that should be, given that they both use the same code.

Ideas or explanations greatfully received.

   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);
      }
   }


回答1:


Interesting question, it demonstrates how overriding virtual members can have unexpected side-effects. The core problem is your BackColor property getter, it always returns the _backColor property value, even if you forced it to a different value with IsMandatory. That property getter is also used by Winforms when it needs to draw the control background. So you'll return Blue which explains why you see blue in your screenshot.

But oddly it still works for the text portion of the control. That's because NumericUpdown is made up of multiple controls. You've got a ContainerControl that sets the outer bounds and is the base class, you are overriding its BackColor property. But inside of it are two other controls, a TextBox that displays the text and a Control that displays the up/down buttons. Your BackColor property override does not override their BackColor properties. So the textbox portion will draw with the color you assigned to Base.BackColor

To fix this, you are going to have to stop fibbing about the BackColor. With the extra constraint that you need to make sure that this still works at design time so that the actual BackColor gets serialized and not the 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;
}



回答2:


The above method did not work out for me. My workaround was:

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

With a private member oldBackColor.

Now it always shows correctly but does not flicker.

Addendum: I think some part of the Control doesn't get painted at all (I consider it a bug) as the "mispainted" bos around it is not uniformly colored an somtimes traces of the window that was there before can be seen.




回答3:


Windows does not properly/completely repaint the NumericUpDown control when it is disabled.

See this post: NumericUpDown background colour change for disabled element

Enabling / disabling the control after it is displayed is a work-around.



来源:https://stackoverflow.com/questions/10631788/numericupdown-backcolor-not-working-as-expected

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