我最近需要编写一个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);
}
}
答案 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
显示控件后启用/禁用控件是一种解决方法。