[英]Application-wide control defaults
我正在寻找一种在C#.NET Windows应用程序中为不同类型的控件设置自己的默认属性值的方法。 默认属性值应“覆盖”控件的现有默认值,但仍可以通过在设计器中显式设置属性值来“覆盖”。
这是为了简化客户端(或我本人)第十次改变主意时更改默认外观/控件行为的过程。 这尤其涉及到诸如DataGridView
或第3方控件之类的控件,其中需要维护大量与布局相关的属性。
我知道创建继承的控件并使用DefaultValue
属性的能力,但这不是我正在寻找的解决方案 ,原因有两个:
这是我想象的它将起作用的方式:
示例1:默认情况下, DataGridView
的背景色为SystemColors.Window
。 我将自己的默认值设置为Color.Blue
( Color.Blue
离谱了!)。 在设计器中,使用默认的背景色,即未在.designer.cs文件中明确设置背景色。 运行应用程序时,将执行一部分代码,从而使网格变成蓝色,这是我指定的。
示例2:在设计器中,同一DataGridView
的背景色设置为Color.Red
。 这将覆盖我自己的默认值blue,即在设计时和运行时都在网格中显示红色背景。
对我来说,解决方案是使用反射来检查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);
}
}
虽然不如泛型那么漂亮,但您也许可以通过Control Builders进行一些操作以实现这一目标。
编辑:
昨晚,我使用ControlBuilder对通用包装控件进行了快速原型设计。 我对结果不满意。 虽然您可能可以使它工作,但我相信一个新的Page或Container类可能会更简单。 我在测试中使用的源代码可在我的博客上找到 。
我已经使用或可以想到几种解决方案。
您可以改为覆盖页面,并循环浏览所有控件,例如
foreach (Control c in Page.Controls)
{
if (c is Textbox)
{
(Textbox)c.Color.blah.blah.blah ;)
}
///etc
Recurse through (c.Controls);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.