引言
在发布有关我的
FAQ.Net应用程序
(Windows注释程序)的第一篇文章之后,出现了第一批希望进一步开发其注释程序的用户。
为了增加用户的兴趣,出现了通过调整颜色和字体来增加其吸引力的想法。
自定义应用程序外观的要求
- 在XML文件中存储和加载各个组件的属性
- 用户应该有一个用于自定义外观的简单工具
- 自定义组件列表应该非常简单地扩展(用一行代码)
- 更改属性值时,用户应立即在表单上看到更改
- 应该有一个取消按钮,使您可以还原所有更改
工作成果
外观窗口:

外观设置前后:

为了解决这个问题,有必要
- 使用PropertyGridEx组件显示和更改组件属性
- 创建一个CustomDesignControl类,以便于以XML存储属性
- 创建一个MainForm表单,在该表单上我们将更改外观
- 创建一个AppSettingsForm表单,在该表单上我们将自定义MainForm的外观
- 创建SettingsXml类,以便于使用XML
消除外观变化的功能
为了取消外观上的更改(要求的第5条),我决定找到一种通用的方法来克隆将在内存中创建的组件的属性,并替换显示的组件。
克隆对象:
public static class ControlExtensions { public static T Clone<T>(T controlToClone) where T : Control { PropertyInfo[] controlProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); T instance = Activator.CreateInstance<T>(); RichTextBox rtb = new RichTextBox(); foreach (PropertyInfo propInfo in controlProperties) { if (propInfo.Name == "Parent") continue; if (propInfo.CanWrite) { if (propInfo.Name != "WindowTarget") { propInfo.SetValue(instance, propInfo.GetValue(controlToClone, null), null); } } } return instance; }
我复制了代码,删除了不需要保存的不必要属性,保留了颜色和字体。
检查代码后,立即发现了此方法的缺点:
- 使用任何将控件强制转换为Control类的方式,这意味着一半的属性可能会丢失(例如,DataGridView组件是从Control类继承的,但是具有自己的其他属性集)
- 克隆组件时,不会克隆某些属性(例如:DataGridView单元格内的字体颜色),而是创建指向克隆的组件的链接(可能是因为该属性与其内部属性一起使用,并且需要以不同的方式进行处理)。
他开始对第二点进行实验,以实现克隆特性。
为此,请使用new运算符创建所需类型的对象。
DataGridView dgvClone = new DataGridView();
无济于事,该组件无法还原所做的更改。
然后,我尝试使用new运算符创建属性本身,并使用SetValue方法为其设置值:
propInfo.SetValue(_controls[i], propInfo.GetValue(_controlsBeforeChange[i], null), null);
而且这种方法没有给出结果。 当一个组件中的属性值更改时,它会在克隆的组件中自动更新。
我不再寻找其他方法了,只需重新启动应用程序即可保存更改文档或取消重新启动,从而使更改返回。 由于不必创建对象的克隆,因此可以大大节省应用程序的内存。
具有外观自定义的示例应用程序
为了以防万一,我准备了一个
现成的代码 ,每个人都可以检查并可能修改取消外观更改的功能,而无需重新启动应用程序,并在注释中告诉我们有关问题的信息。
必须确保当您单击“自动测试”按钮时,DataGridView组件具有灰色背景并且单元格的字体很小。

下载Windows应用程序FAQ.Net(免费):
(x64)
yadi.sk/d/sq3g4NOD3Zt7ZY(x86)
yadi.sk/d/NKXeyUWH3Zt8PQVK集团源代码FAQ.Net结论
我希望在许多WinForms应用程序中,由于这篇文章的帮助,最终用户将有机会根据自己的喜好和颜色自定义界面。