• 艾伟:WM有约(二):配置信息 狼人:



    Written by Allen Lee

    添加配置文件

    首先,向项目添加一个Options.xml文件,这个文件将会用来储存应用程序的配置信息:

    图 1

    接着,把Options.xml的Copy to Output Directory属性的值改为Copy if newer:

    图 2

    然后,就是为Options.xml添加配置信息了:

    代码 1

    那么,我们如何使用这个文件呢?关于这个问题,我首先想到的是为它创建一个OptionManager类,在我的想象里,它应该是这样使用的:

    代码 2

    在继续之前,我想请你思考一个问题:你会如何实现OptionManager的Options成员呢?下面是我的做法,使用了单例模式和索引器:

    代码 3

    当然,你也可以学ConfigurationManager类那样,通过AppSettings静态属性返回一个NameValueCollection对象。接下来的问题是,如何访问Options.xml呢?由于Options.xml上面的配置信息实际上只是一组键/值对,于是你可以考虑在OptionManager的构造函数里把它们全部读到一个内部的Dictionary对象里:

    代码 4

    LoadOptions方法使用了LINQ to XML来读取Options.xml里的配置信息,并以Dictionary的形式返回:

    代码 5

    这里使用了GetXmlPath方法来获取Options.xml的路径:

    代码 6

    OptionManager提供了一个Save方法,用于保存配置信息:

    代码 7

    其中,SaveOptions方法也使用了LINQ to XML来构建并保存配置信息:

    代码 8

    最后就是OptionManager的索引器了:

    代码 9

    设计选项窗体

    说到选项窗体,你会如何设计?我想象中的选项窗体大致像这样:

    图 3

    我用了一个NumericUpDown控件来收集MaxSelectionCount的配置信息,另外用了两个DateTimePicker控件分别收集MinDate和MaxDate的配置信息。

    接着,我们来看看底下两个菜单项。Cancel菜单项比较简单,仅仅把窗体的DialogResult设为Cancel:

    代码 10

    而OK菜单项的任务就多一点,它要保存用户的配置信息:

    代码 11

    接着就是修改一下主窗体的菜单:

    图 4

    Save菜单项和以前一样,而Options菜单项将会打开选项窗体:

    代码 12

    现在,我们来运行一下这个应用程序:

    图 5

    图 6

    有问题!选项窗体打开的时候,上面的控件没有反映配置文件里面的信息,这是因为我没有实现这样的逻辑,同样地,这个问题也会发生在主窗体身上,这意味着无论我们如何修改配置文件,重新启动应用程序之后,主窗体将会恢复默认配置,何等严重!

    首先是选项窗体打开的时候需要读取配置信息到对应的控件上:

    代码 13

    代码 14

    由于读取配置信息的代码和代码12里的那部分是相同的,所以我把它提取出来,放在SetupOptions方法里,这样,代码12就简化为:

    代码 15

    再次运行应用程序:

    图 7

    这次正常了。不过还有一个小问题,选项窗体里保存配置信息的代码属于OK菜单项而不是选项窗体的,当用户单击窗体右上角的OK按钮时,虽然窗体的DialogResult属性返回OK,但实质上没有执行任何保存配置信息的操作,这就导致了窗体行为的不一致。解决这个问题的办法有两个,一个是去掉窗体右上角的OK按钮,另一个是把OK菜单项里保存配置信息的代码放到窗体层面上做。前一种做法很简单,只需要把选项窗体的ControlBox属性设为false就行了。至于后一种做法,在继续讨论之前,我想先考一考你,我应该选择Deactivate事件还是Closing事件呢?答案是两个都可以,因为选项窗体是通过ShowDialog方法打开的,关闭这样的窗体是真的关闭了而不是像主窗体那样最小化到后台,所以我们可以放胆使用Closing事件:

    代码 16

    还有一个不是问题的问题,就是当你关闭选项窗体时,你会发现画面突然停顿,你知道这个时候OptionManager在保存配置信息,但用户并不知道,这可能会给用户留下不好的印象/感受,要让用户知道后台正在执行任务,最简单的办法就是在屏幕正中显示等待指针,当然,任务完成之后记得去掉等待指针,否则……

    你还想要什么?

    下一集,除了上一集剩下的两个需求之外,我们还会探讨两个新的需求:

    • 支持日期的包含,比如说2009年2月14日被指定为届时要选的日期。
    • 如果指定一个周期,应用程序将会综合排除逻辑、包含逻辑和这个周期计算下一个将要被选中的日期,并显示在主界面上。

    相关文章:WM有约(一):你好,CF

  • 相关阅读:
    解决使用gomod后goland导包报红问题
    Golang写文件的坑
    Golang去除字符串前后空格
    Golang通过结构体解析和封装XML
    Golang获取CPU、内存、硬盘使用率
    Golang数组和切片的区别
    Golang修改操作系统时间
    Golang中GBK和UTF8编码格式互转
    Golang中的各种时间操作
    Golang十六进制字符串和byte数组互转
  • 原文地址:https://www.cnblogs.com/waw/p/2156899.html
Copyright © 2020-2023  润新知