gpt4 book ai didi

c# - 应用程序范围的控制默认值

转载 作者:太空宇宙 更新时间:2023-11-03 19:36:23 25 4
gpt4 key购买 nike

我正在寻找一种方法来为我的 C# .NET Windows 应用程序中的不同类型的控件设置我自己的默认属性值。默认属性值应该“覆盖”控件的现有默认值,但仍然可以通过在设计器中显式设置属性值来“覆盖”。

这是为了简化在客户(或我自己)第 10 次改变主意时更改控件的默认外观/行为的过程。这尤其与 DataGridView 或 3rd 方控件等控件相关,其中需要维护大量与布局相关的属性。

我知道创建继承控件和使用 DefaultValue 属性的能力,但这不是我正在寻找的解决方案,原因如下:

  • 必须继承我想为其指定自定义属性的每种类型的控件,更不用说覆盖/隐藏属性和设置 DefaultValue 属性了。
  • 我不能再使用标准的 .NET 控件,而必须使用继承的控件。
  • 继承控件的数量会随着时间的推移而增加,并使工具箱变得杂乱无章。
  • 我自己或项目中的其他开发人员在匆忙时忘记使用新的继承类型,导致控件的行为/外观不一致。

这就是我想象的它的工作方式:

  • 示例 1: DataGridView 默认具有背景色SystemColors.Window。我自己设置默认值为 Color.Blue(如何离谱!)。在设计器中,使用默认背景颜色,即背景颜色未设置明确地在 .designer.cs 文件中。运行应用程序时,执行了一部分代码,导致网格转动蓝色,由我指定。

  • 例2:同一个DataGridView的背景色设置为Color.Red 在设计器中。这覆盖我自己的默认蓝色值,显示红色背景在网格中,包括设计时和运行时。


解决方案

我的解决方案是使用反射来检查 DefaultValue 属性,正如 Daniel Brückner 所建议的那样.

我递归访问表单上的所有控件,为每个控件调用 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 做了一个通用包装控件的快速原型(prototype)。我对结果不满意。虽然您可能可以让它工作,但我相信一个新的 Page 或 Container 类可能是一个更简单的结果。我在测试中使用的源代码在我的 blog 上可用。 .

关于c# - 应用程序范围的控制默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1346855/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com