• 【.net 深呼吸】自己动手来写应用程序设置类


    在开始装逼之前,老周先说明一件事。有人说老周写的东西太简单了,能不能写点复杂点。这问题就来了,要写什么东西才叫“复杂”?最重要的是,写得太复杂了,一方面很多朋友看不懂,另一方面,连老周自己也不知道怎么表述。

    而且,老周也不能把以前在K公司、Z公司和T公司中做项目的东西写出来的,其实嘛,工作中的编程没什么可写的,无非就是 select、insert、delete、update,无非就是连接数据库,断开连接,同步一下数据,把数据变成XML或JSON再发给另一终端。无非就是读读你的网卡CPU硬盘序列号,组成个东东再加密,计算一下授权码,又或者生成个假冒伪劣证书给用户授授权。再不是就写几个API给别人调几下。让脑细胞死亡率大增的,就是要动态生成计算工资的公式,这个嘛,当时老周是选用 Code Dom 来生成的,代码生成这玩意儿,老周前些时间就写过好些博文了,相信大伙伴们也看过了。

    所以,你看,工作中用到的东西其实很片面很单一,所覆盖的面还不如老周平时闲着没事的时候写的小程序。故,还是写点简单的东西和谐一点,你懂我懂他也懂,岂不甚妙,人活着为啥老跟自己过不去呢,姜育恒大哥就曾经唱过:

    • 不管明天要面对多少伤痛和迷惑
    • 曾经在幽幽暗暗反反复复中追问
    • 才知道平平淡淡从从容容是最真

    平淡是福,简单是乐,谁谓不然?

    好了,上面的鬼话说完了,下面咱们开始说人话。

    我们都知道,VS 开发环境会为项目自动生成一个settings类,即用于访问应用程序设置的帮助类,数据是存到跟应用程序一起的 config 文件中,比如历史上著名的 App.config 文件。

    顺便提一下,VS 自动生成的应用设置类有一个特点:基于应用程序范围的设置项是只读的,基于用户范围的设置项是可读可写的。看不懂?没事,你可以动手调戏一下这个settings类的。

    在Properties节点下,你应该能看到一个 Settings 文件,然后打开它。

    这里你可以自己添加设置项,注意看“范围”这一列,它就两个选项,要么是基于应用范围,要么基于用户范围。好,我们为每个范围各添加一个设置项。

    随后,我们保存一下(必须,保存才会生成代码),接着打开代码,看看设计器生成的 Settings 类。

     代码选段。

            [global::System.Configuration.UserScopedSettingAttribute()]
            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
            [global::System.Configuration.DefaultSettingValueAttribute("0")]
            public byte TestV1 {
                get {
                    return ((byte)(this["TestV1"]));
                }
                set {
                    this["TestV1"] = value;
                }
            }
            
            [global::System.Configuration.ApplicationScopedSettingAttribute()]
            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
            [global::System.Configuration.DefaultSettingValueAttribute("0")]
            public int TestV2 {
                get {
                    return ((int)(this["TestV2"]));
                }
            }

    在属性上应用 ApplicationScopedSettingAttribute 表示该设置项是应用程序范围的,大伙看到,属性中只有 get 没有 set,说明它是只读的。而应用了 UserScopedSettingAttribute 的属性表示的是用户范围内的设置项,此时看到该属性同时有 get 和 set ,即可读可写。

    为什么应用程序范围的设置项相关属性会生成只读属性呢,后来一看MSDN就明白了,因为当调用相关方法保存设置时,应用程序范围内的设置是不会起作用的,但是不会报错。也就是说,要自己写可以直接保存的设置项,只能把属性定义为用户范围内的

    如果觉得生成的设置类不好玩,我们可以自己写的。

    编写这个类其实很简单,我们只需从 ApplicationSettingsBase 类派生即可,该类位于 System.Configuration 命名空间下,它是一个抽象类。在写自定义的应用设置类时,我们可以像普通类一样公开属性,这样读写设置项时也方便,而且,你还可以直接用于数据绑定。

    在包装属性时,是通过调用基类的索引器来存取内容的,它是一个字典模型,key是字符串类型,而value是Object类型,这样你可以设置各种类型的值。

    好,咱们写一个来表演一下。

        internal class AppSettings : ApplicationSettingsBase
        {
            #region 常量
            const string APP_TITLE = "appTitle";
            const string APP_USAGE = "appUsage";
            const string USER_NAME = "userName";
            const string USE_YEARS = "useYears";
            #endregion
    
            [UserScopedSetting]
            [DefaultSettingValue("my app")]
            public string AppTitle
            {
                set
                {
                    this[APP_TITLE] = value;
                }
                get { return (string)this[APP_TITLE]; }
            }
    
            [UserScopedSetting]
            [DefaultSettingValue("用于装X")]
            public string AppUsage
            {
                get { return (string)this[APP_USAGE]; }
                set { this[APP_USAGE] = value; }
            }
    
            [UserScopedSetting]
            [DefaultSettingValue("大傻冬")]
            public string UserName
            {
                get { return (string)this[USER_NAME]; }
                set { this[USER_NAME] = value; }
            }
    
            [UserScopedSetting]
            [DefaultSettingValue("3")]
            public int UseYears
            {
                get { return (int)this[USE_YEARS]; }
                set { this[USE_YEARS] = value; }
            }
        }

    由于属性实现中使用的key是字符串类型的,为了防止多次输入时出现错误,通常可以预先声明一组字符串常量。

            const string APP_TITLE = "appTitle";
            const string APP_USAGE = "appUsage";
            const string USER_NAME = "userName";
            const string USE_YEARS = "useYears";

    在类公开的属性上除了应用表示用户范围内的标识特性外,还应用了 DefaultSettingValue 特性,它用来设置项的默认值,值是以字符串形式表示的。

    这个示范的设置类包装了四个设置项,那么,怎么耍呢。耍起来也很简单,跟耍猴差不多。首先,你要new一个类实例,接着就可以通过我们刚才包装的那四个属性来读写设置项,最后,调用 Save 方法,就可以把修改后的数据保存到配置文件中。

    让设置类与用户界面交互,最简单最方便的方法是使用绑定,比如这样。

            <TextBox Grid.Column="1" Text="{Binding Path=AppTitle, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Path=AppUsage,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            <TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Path=UserName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            <TextBox Grid.Column="1" Grid.Row="3" Text="{Binding Path=UseYears,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>

    这个设置类是可以进行双向绑定的,因为基类 ApplicationSettingsBase 实现了 INotifyPropertyChanged 接口。通常我们可以在窗口关闭时保存配置。

            protected override void OnClosing(CancelEventArgs e)
            {
                base.OnClosing(e);
                settings.Save();
            }

    以前我们开发程序,都习惯在界面上放一个保存按钮,当用户点击后保存,不过现在好像流行了,因为用户修改完设置后还要点一按钮来保存,操作有点复杂,让窗口在关闭时自动保存设置,显得更友好。

    那么,这个破文件到底保存到哪里去了,在应用所在目录中的配置文件中并没有。应用目录中的配置文件存的应用程序级别的设置,用户级别的配置应该与当前用户的私人目录有关。

    打开文件管理器,在地址栏中输入:%UserProfile%AppDataLocal,然后回车,就会进入当前用户文件夹下的appData的Local子目录,然后,在这个目录下,你会看到一个以你的应用程序命名的文件夹,然后你继续进入子目录,直到看到一个名为 user.config 的文件。对,就是它了,不信你打开看看。

    <configuration>
        <configSections>
            <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
                <section name="DemoApp.AppSettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
            </sectionGroup>
        </configSections>
        <userSettings>
            <DemoApp.AppSettings>
                <setting name="UseYears" serializeAs="String">
                    <value>2</value>
                </setting>
                <setting name="UserName" serializeAs="String">
                    <value>矮冬瓜</value>
                </setting>
                <setting name="AppUsage" serializeAs="String">
                    <value>用于忽悠未成年人</value>
                </setting>
                <setting name="AppTitle" serializeAs="String">
                    <value>天国第一假货</value>
                </setting>
            </DemoApp.AppSettings>
        </userSettings>
    </configuration>

    另外,ApplicationSettingsBase 类有几个事件比较有用,必要时可以用上。当设置数加载后会发生 SettingsLoaded 事件,从名字中也能知道其用途;在设置项被修改之前,会发生 SettingChanging 事件,修改之后会发生 PropertyChanged 事件(实现了INotifyPropertyChanged接口);当调用 Save 方法保存之前,会引发 SettingsSaving 事件,事件参数会包含一个 Cancel 属性,如果想取消保存,可以将该属性设置为 true。

    示例源代码下载地址:请点击▶这里◀

  • 相关阅读:
    快逸报表调用存储过程(SqlServer)
    一个睡五分钟等于六个钟头的方法 (转)
    Windows Live Writer For Windows Server 2003
    设计模式装饰者模式
    SqlServerCUBE
    Android 70道面试题汇总不再愁面试
    说服力:让你的PPT会说话
    亮剑Java项目开发案例导航
    初入社会必知的88个潜规则
    android UI进阶之仿iphone的tab效果2
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/7227861.html
Copyright © 2020-2023  润新知