NumericUpDown backcolor无法按预期工作

我最近需要编写一个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); } } 

这是它的样子:

有趣的问题,它演示了重写虚拟成员如何产生意想不到的副作用。 核心问题是你的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; } 

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

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

使用私有成员oldBackColor。

现在它总是正确显示但不闪烁。

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

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

请参阅此文章: 已禁用元素的NumericUpDown背景颜色更改

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