Wizard Framework:一個自己開發的基於Windows Forms的嚮導開發架構

來源:互聯網
上載者:User

標籤:

最近因項目需要,我自己設計開發了一個基於Windows Forms的嚮導開發架構,目前我已經將其開源,並發布了一個NuGet安裝包。比較囧的一件事是,當我發布了NuGet安裝包以後,發現原來已經有一個.NET的嚮導開發架構了,它叫Microsoft Visual Studio 2013 Wizard Framework。我並沒有對其進行深入研究,單從名稱上看,該架構是否只能在Visual Studio 2013下使用?上網搜尋過,也沒發現微軟有比較詳細的官方資料介紹這個架構。不過無論如何,我還是在此向大家介紹一下我自己開發的這個嚮導架構,也算是讓大家瞭解一下我的設計思路,以及使大家能夠方便地從該架構獲益,快捷地在自己的項目中也用上這個嚮導架構。

有圖有真相

話不多說,請先看。為了示範這個架構,我依賴它開發了一個類比軟體安裝過程的嚮導程式。用過類似Install Shield的安裝程式的使用者,應該對下面的這些對話方塊比較熟悉吧:

怎麼樣?看上去還算專業吧?它就是用Wizard Framework開發的。1.0.0版本支援以下功能:

  • 嚮導對話方塊可以定製,比如可以自訂對話方塊的尺寸、Icon、是否支援線上協助等等
  • 由Windows Forms設計器支援的嚮導頁面設計,開發人員可以像開發一個使用者控制項一樣,直接在Visual Studio中使用拖拽的方式,設計每個頁面的介面
  • 每個頁面都可以通過CanGoPreviousPage、CanGoNextPage、CanGoFinishPage以及CanGoCancel四個屬性,直接設定嚮導對話方塊中“上一步”、“下一步”、“完成”和“取消”按鈕的狀態
  • 每個頁面都可以讀取其它任何頁面所儲存的嚮導模型(WizardModel),通過嚮導模型擷取各個頁面的設定參數(比如上面“安裝資訊匯總”頁面中就讀取了“軟體功能選擇”頁面的資料並顯示出來)
  • 每個頁面都可以直接設定其它頁面是否在上一步或者下一步可見,比如,在有些情況下,噹噹前頁的某個參數被設定後,我們希望在點“下一步”的時候,能夠跳過下一頁,而直接進入下下頁
  • 每個頁面都可以設定自己的Logo
  • 對C# 5.0中async/await的支援,使得面向嚮導的非同步開發模型變得異常簡單
  • 支援中文和英文

那麼,我該如何獲得原始碼或者開發包呢?

原始碼與NuGet安裝包

你可以直接存取Wizard Framework的首頁:https://github.com/daxnet/wizard-framework。如果你裝有Git用戶端的話,可以將本項目複製到本地:

git clone https://github.com/daxnet/wizard-framework

等複製結束後,直接在Visual Studio 2013中開啟WizardFramework.sln即可(目前Wizard Framework基於.NET Framework 4.5.1開發,所以建議還是用Visual Studio 2013開啟)。此時,你可以看到該方案套件含兩個項目:

WizardFramework項目就是該架構的原始碼,而InstallerSample是一個Windows Forms應用程式,它使用了WizardFramework開發了一個類比軟體安裝過程的嚮導介面,也就是上面你所看到的介面效果了。你可以修改Program.cs中Main函數的第一條語句,將本地化資訊設定為zh-CN或者en-US,來體驗該類比程式在不同地區語言下的介面效果。

如果你希望在自己的Windows Forms項目中使用Wizard Framework,你可以在項目上單擊滑鼠右鍵,選擇Manage NuGet Packages功能表項目,在彈出的對話方塊中搜尋WizardFramework關鍵字即可:

選中之後,單擊“安裝”按鈕,即可將本嚮導開發架構添加到你的項目中(注意:建議應用程式是基於.NET Framework 4.5.1開發的)。

使用方法

通過NuGet Package Manager添加了Wizard Framework的引用之後,就可以開始開發嚮導應用了。基本上可以分三個步驟:開發嚮導頁、開發嚮導對話方塊,以及將嚮導頁添加到嚮導對話方塊。

開發嚮導頁

要開發一個嚮導頁,只需在Visual Studio的Windows Forms項目上,添加一個使用者控制項(UserControl),然後使其繼承於WizardFramework.WizardPage類即可。此時,Visual Studio編輯器會提示建構函式錯誤,因為WizardPage類型沒有可訪問的預設建構函式,這就需要通過自訂的嚮導頁類的建構函式向基類傳入參數。以下是WizardPage建構函式的重載,以及各重載建構函式的參數描述。

  • WizardPage(string title, string description, Wizard wizard, IWizardModel model = null)
    • title:用於顯示在每個嚮導頁上方黑體標題部分的標題資訊
    • description:用於顯示在每個嚮導頁上方的嚮導頁描述資訊
    • wizard:當前嚮導頁所在的嚮導對象,一般通過嚮導頁的建構函式參數傳入
    • model:當前嚮導頁所使用的資料物件模型
  • WizardPage(string title, string description, Wizard wizard, WizardPageType type)
    • title:用於顯示在每個嚮導頁上方黑體標題部分的標題資訊
    • description:用於顯示在每個嚮導頁上方的嚮導頁描述資訊
    • wizard:當前嚮導頁所在的嚮導對象,一般通過嚮導頁的建構函式參數傳入
    • type:當前嚮導頁的類型。分為兩種類型:Standard和Expanded。Standard類型的意思是,當顯示該嚮導頁時,會在嚮導對話方塊的上方顯示title和description資訊;而對於Expanded類型,則這部分資訊不會顯示出來,整個頁面的設計完全由開發人員自己控制。顯然,在上面的樣本中,2、3、4、5頁都是屬於Standard類型的嚮導頁,而1和6頁則屬於Expanded類型
  • WizardPage(string title, string description, Wizard wizard, IWizardModel model, WizardPageType type)
    • title:用於顯示在每個嚮導頁上方黑體標題部分的標題資訊
    • description:用於顯示在每個嚮導頁上方的嚮導頁描述資訊
    • wizard:當前嚮導頁所在的嚮導對象,一般通過嚮導頁的建構函式參數傳入
    • model:當前嚮導頁所使用的資料物件模型
    • type:當前嚮導頁的類型。分為兩種類型:Standard和Expanded。Standard類型的意思是,當顯示該嚮導頁時,會在嚮導對話方塊的上方顯示title和description資訊;而對於Expanded類型,則這部分資訊不會顯示出來,整個頁面的設計完全由開發人員自己控制。顯然,在上面的樣本中,2、3、4、5頁都是屬於Standard類型的嚮導頁,而1和6頁則屬於Expanded類型

以下是一個嚮導頁的類定義以及建構函式的實現例子:

public partial class FirstPage : WizardPage{    public FirstPage(Wizard wizard)        :base("First Page", "This is the first page.", wizard)    {        InitializeComponent();    }}

需要注意的是,嚮導頁的建構函式必須是公有(public)的,而且有且只有一個Wizard類型的參數。

嚮導頁中的幾個回呼函數

在WizardFramework.WizardPage基類中,定義了一些可供Wizard對象調用的回呼函數,這些函數將在適當的時候被調用,因此,開發人員可以在這些回呼函數中處理自己的邏輯,比如設定是否允許使用者點擊“下一頁”等導覽按鈕。

  • 【方法】Task ExecuteShowAsync(IWizardPage fromPage)
    • 當Wizard準備顯示當前嚮導頁時,調用此方法。該方法以非同步方式調用
    • fromPage參數:表示是從哪個嚮導頁導航過來的。比如,當使用者點擊“下一頁”按鈕後,下一個嚮導頁將會顯示在嚮導對話方塊中,通常情況下,fromPage參數是所顯示的嚮導頁的上一頁
  • 【方法】Task<bool> ExecuteBeforeGoingPreviousAsync()
    • 當使用者點擊“上一頁”按鈕後,嚮導對話方塊準備進入上一嚮導頁時,調用此方法。該方法以非同步方式調用
    • 傳回值:返回一個能夠返回布爾值的任務對象,此布爾值表示是否真的允許嚮導對話方塊進入上一頁(True=允許;False=不允許)
  • 【方法】Task<bool> ExecuteBeforeGoingNextAsync()
    • 當使用者點擊“下一頁”按鈕後,嚮導對話方塊準備進入下一嚮導頁時,調用此方法。該方法以非同步方式調用
    • 傳回值:返回一個能夠返回布爾值的任務對象,此布爾值表示是否真的允許嚮導對話方塊進入下一頁(True=允許;False=不允許)
  • 【方法】Task<bool> ExecuteBeforeGoingFinishAsync()
    • 當使用者點擊“完成”按鈕後,嚮導對話方塊準備進入“完成”嚮導頁時,調用此方法。該方法以非同步方式調用
    • 傳回值:返回一個能夠返回布爾值的任務對象,此布爾值表示是否真的允許嚮導對話方塊結束,並向調用方返回DialogResult.OK值(True=允許;False=不允許)
  • 【方法】void PersistValuesToModel()
    • 當嚮導對話方塊準備進入其它嚮導頁時,會調用此方法,將當前已顯示的嚮導頁介面上的使用者佈建儲存到嚮導資料模型對象中,下一節將詳細介紹這部分內容
  • 【屬性】System.Windows.Forms.Control FocusingControl
    • 設定在開啟當前嚮導頁時,焦點(Focus)所在的介面控制項(即焦點預設應該在哪個控制項上)
  • 【屬性】System.Drawing.Image Logo
    • 設定當前嚮導頁需要顯示在嚮導對話方塊右上方的表徵圖

開發人員在自訂自己的嚮導頁面時,可以在子類中重載以上方法或屬性,以在不同的時機處理不同的邏輯。詳細使用方法,可以參考WizardFramework原始碼庫內建的InstallerSample樣本項目。

嚮導資料模型

在WizardFramework中,通過引入嚮導資料模型的概念,來儲存每個嚮導頁的使用者佈建。比如,在InstallerSample樣本項目的FeaturePage嚮導頁中,使用者可以在介面上選擇安裝的類型(最小安裝、標準安裝和完整安裝),還可以指定安裝路徑。這些使用者設定都被儲存在該嚮導頁的資料模型中,以便其它嚮導頁或者嚮導對話方塊讀取使用。嚮導資料模型類的定義,需要實現IWizardModel介面,如下:

public sealed new class Model : IWizardModel{    #region Public Properties    public string SelectedFeature { get; set; }    public string SelectedFolder { get; set; }    #endregion Public Properties    #region Public Methods    public override string ToString()    {        var sb = new StringBuilder();        sb.AppendLine(string.Format(Resources.SelectedFeaturePattern, SelectedFeature));        sb.AppendLine(string.Format(Resources.InstallationFolderPattern, SelectedFolder));        return sb.ToString();    }    #endregion Public Methods}

在資料模型對象中,只需要編寫一些與介面控制項取值相對應的屬性即可。一種推薦的做法是,將嚮導資料模型類定義在每個嚮導頁的類定義中,也就是作為嚮導頁類的一個內嵌類來定義,類名就簡單地使用Model作為類名就行了,為了繞過編譯器警告,在聲明類的時候加上new關鍵字。這樣做的好處是,今後在其它嚮導頁面或者嚮導對話方塊中擷取嚮導模型對象時,有助於提高代碼的可讀性。

如果嚮導頁需要使用嚮導資料模型,則需要在建構函式中初始化資料模型對象,如下(注意base建構函式調用的最後一個參數):

public FeaturePage(Wizard wizard)    : base(Resources.FeaturePageTitle, Resources.FeaturePageDescription, wizard, new Model()){    InitializeComponent();}

並且,需要重載PersistValuesToModel方法,以便將介面控制項的值儲存到資料模型中:

protected override void PersistValuesToModel(){    var selectedFeature = string.Empty;    if (rbMinimal.Checked)        selectedFeature = rbMinimal.Text;    else if (rbStandard.Checked)        selectedFeature = rbStandard.Text;    else if (rbFull.Checked)        selectedFeature = rbFull.Text;    ModelAs<Model>().SelectedFeature = selectedFeature;    ModelAs<Model>().SelectedFolder = txtInstPath.Text;}

當需要在其它頁面中,或者通過嚮導對話方塊擷取嚮導頁的資料模型對象時,可以使用下面的方法:

var model = Wizard.GetWizardModel<FeaturePage.Model>();

此處,通過Wizard對象的GetWizardModel泛型方法,即可得到FeaturePage.Model資料模型對象。

控制嚮導的導航

在有些情境下,需要根據當前頁的某些介面設定,來決定下一頁應該導航到哪個嚮導頁。比如,在嚮導頁1中,如果使用者點擊了某個複選框,那麼當使用者再點“下一步”按鈕時,則跳過頁面2,直接進入頁面3,否則,則需要跳到頁面2。此時,可以調用Wizard對象的SetPageDisplay方法即可。該方法有兩個重載:

  • void SetPageDisplay(int pageIndex, WizardPageDisplay display)
    • pageIndex:根據嚮導頁加入到嚮導對話方塊的順序,所對應的嚮導頁索引號
    • display:指定該頁是顯示(WizardPageDisplay.Show)還是不顯示(WizardPageDisplay.Hide)
  • void SetPageDisplay<T>(WizardPageDisplay display)
    • 泛型型別T:指定需要設定顯示行為的嚮導頁類型
    • display:指定該頁是顯示(WizardPageDisplay.Show)還是不顯示(WizardPageDisplay.Hide)
開發嚮導對話方塊

嚮導對話方塊的開發非常簡單,只需要建立一個System.Windows.Forms.Form類型,然後使其繼承於WizardFramework.Wizard類即可,無需再寫更多的代碼。當然,如果需要設定一些額外的屬性,也可以直接在Visual Studio的屬性頁面中進行設定即可。

初始化嚮導頁,並將嚮導頁添加到嚮導對話方塊中

下面的代碼展示了嚮導頁初始化並添加到嚮導對話方塊的做法,還是非常簡單的:

var installer = new FrmInstaller();installer.Add(installer.CreatePage<WelcomePage>());installer.Add(installer.CreatePage<LicensePage>());installer.Add(installer.CreatePage<FeaturePage>());installer.Add(installer.CreatePage<SummaryPage>());installer.Add(installer.CreatePage<InstallingPage>());installer.Add(installer.CreatePage<FinishPage>());
總結

本文介紹了我自己開發的一個嚮導架構,並介紹了架構的使用。或許,在某些情況下,該架構還是不能滿足需求,此時,可以直接把WizardFramework的原始碼拉下來進行定製。

Wizard Framework:一個自己開發的基於Windows Forms的嚮導開發架構

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.