【.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%\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。

 

示例源代碼下載地址:請點擊▶這里◀

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM