NumericUpDown backcolor无法按预期工作

时间:2012-05-17 07:49:47

标签: c# user-controls numericupdown

我最近需要编写一个Windows NumericUpDown控件的版本,它可以突出显示值是否是必需的。它需要通过更改控件的背面颜色来完成此操作。我认为这很简单,但是在尝试这样做时,我发现它有一个奇怪的副作用,就是不能完全控制所有控件。

使用下面的代码,我看到了:

当我在Windows窗体上放置一个控件,并将BackColor属性(即蓝色)更改为时,整个控件的编号部分会改变颜色。或者,如果我改变了我的“IsMandatory”属性,则不是所有的背面颜色都改变了(它留下了边框)。因此,如果我将BackColor更改为蓝色,然后将IsMandatory设置为True,我会得到一个带蓝色边框的LightBlue控件(强制颜色)

我不明白为什么会这样,因为他们都使用相同的代码。

非常接受的想法或解释。

   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:

3 个答案:

答案 0 :(得分:2)

有趣的问题,它演示了覆盖虚拟成员如何产生意外的副作用。核心问题是你的BackColor属性getter,它总是返回_backColor属性值,即使你用IsMandatory强制它到另一个值。 Winforms在需要绘制控件背景时也使用该属性getter。因此,您将返回Blue,这解释了为什么您在屏幕截图中看到蓝色。

但奇怪的是它仍适用于控件的文本部分。这是因为NumericUpdown由多个控件组成。你有一个设置外部边界的ContainerControl并且是基类,你要覆盖它的BackColor属性。但其中还有另外两个控件,一个显示文本的TextBox和一个显示向上/向下按钮的Control。您的BackColor属性覆盖覆盖其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;
}

答案 1 :(得分:0)

上述方法对我来说没有用。我的解决方法是:

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

使用私人成员oldBackColor。

现在它始终显示正确但不闪烁。

附录:我认为Control的某些部分根本没有被绘制(我认为它是一个bug),因为它周围的“错误画面”bos并不是均匀着色的,之前的窗口的somtimes痕迹可以是可见

答案 2 :(得分:0)

禁用时,Windows无法正确/完全重新绘制NumericUpDown控件。

请参阅此帖子:NumericUpDown background colour change for disabled element

显示控件后启用/禁用控件是一种解决方法。