【发布时间】:2010-11-23 17:29:28
【问题描述】:
我正在寻找一种方法来为我的 C# .NET windows 应用程序中的不同类型的控件设置我自己的默认属性值。默认属性值应“覆盖”控件的现有默认值,但仍可通过在设计器中显式设置属性值来“覆盖”。
这是为了简化在客户(或我自己)第 10 次改变主意时更改控件默认外观/行为的过程。这尤其涉及到像 DataGridView 这样的控件或需要维护大量与布局相关的属性的第 3 方控件。
我知道创建继承控件和使用 DefaultValue 属性的能力,但这不是我正在寻找的解决方案,原因如下:
- 必须继承我想要为其指定自定义属性的每种类型的控件很麻烦,更不用说覆盖/隐藏属性和设置 DefaultValue 属性了。
- 我不能再使用标准的 .NET 控件,而必须使用继承的控件。
- 继承的控件数量会随着时间的推移而增加,从而使工具箱变得杂乱无章。
- 我自己或项目中的其他开发人员在匆忙时忘记使用新的继承类型,导致控件的行为/外观不一致。
这就是我想象中的工作方式:
示例 1: 默认情况下,
DataGridView具有背景颜色SystemColors.Window。我自己设置 默认值为Color.Blue(如何 离谱!)。在设计师中, 使用默认背景颜色, 即未设置背景颜色 在 .designer.cs 文件中明确显示。 运行应用程序时,会执行一部分代码,导致网格转动 蓝色,由我指定。示例2:同一
DataGridView的背景色设置为Color.Red在设计器中。这 覆盖我自己的默认值蓝色,显示红色背景 在网格中,在设计时和运行时。
解决方案
按照Daniel Brückner 的建议,我的解决方案是使用反射来检查DefaultValue 属性。
我递归遍历表单上的所有控件,为每个控件调用SetDefaultValues。对于要设置的每个属性值,我调用SetValue 方法,该方法确保仅设置未更改其默认值的属性。
不过,这种方法存在一个缺陷。已在设计器中显式设置但与其默认值没有区别的属性将被SetValue 方法覆盖。
void SetDefaultValues(Control control)
{
if (control is DataGridView)
{
SetValue(control, "BackColor", Color.Blue);
}
else if (control is TextBox)
{
// etc.
}
}
private static void SetValue(object control, string propertyName, object newValue)
{
System.Reflection.PropertyInfo prop = control.GetType().GetProperty(propertyName);
if (prop == null)
{
throw new ArgumentException(string.Format(
"Specified property \"{0}\" does not exist on type \"{1}\".", prop.Name, control.GetType().FullName),
"propertyName");
}
bool defaultValueFound = false;
object defaultValue = null;
foreach (object attr in prop.GetCustomAttributes(true))
{
if (attr is DefaultValueAttribute)
{
defaultValue = ((DefaultValueAttribute)attr).Value;
defaultValueFound = true;
break;
}
}
if (!defaultValueFound && prop.PropertyType.IsValueType)
{
// Get default value for value types if no default value was specified by attributes:
defaultValue = Activator.CreateInstance(prop.PropertyType);
}
if (defaultValue == null || defaultValue.Equals(prop.GetValue(control, null)))
{
// If default value matches current value, set new value:
prop.SetValue(control, newValue, null);
}
}
【问题讨论】:
-
这就是能够在设计师中使用泛型将很棒的地方
标签: c# .net winforms default-value