1. 程式人生 > >【.net 深呼吸】自己動手來寫應用程序設置類

【.net 深呼吸】自己動手來寫應用程序設置類

title bsp dem () 著名 ssi demo 好玩 目的

在開始裝逼之前,老周先說明一件事。有人說老周寫的東西太簡單了,能不能寫點復雜點。這問題就來了,要寫什麽東西才叫“復雜”?最重要的是,寫得太復雜了,一方面很多朋友看不懂,另一方面,連老周自己也不知道怎麽表述。

而且,老周也不能把以前在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%\AppData\Local,然後回車,就會進入當前用戶文件夾下的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。

示例源代碼下載地址:請點擊?這裏?

【.net 深呼吸】自己動手來寫應用程序設置類