zoukankan      html  css  js  c++  java
  • 【.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。

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

  • 相关阅读:
    C#利用反射动态调用类及方法
    系统程序监控软件
    SQL server 2008 安装和远程访问的问题
    sql server 创建临时表
    IIS 时间问题
    windows 2008 安装 sql server 2008
    sql server xml nodes 的使用
    Window 7sp1 安装vs2010 sp1 打开xaml文件崩溃
    CSS资源网址
    Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/7227861.html
Copyright © 2011-2022 走看看