網站導航(多視圖頁面:MultiView 和 Wizard 控件)


       導航組件是所有網站的基本組件。雖然把用戶從一個網頁轉換到另一個網頁非常的容易,但創建一個整個網站適用的統一的導航系統就不那么簡單了。雖然可以通過少量的鏈接(大量的工作)建立自己的導航系統,但何不使用 ASP.NET 已經有的內建導航系統?

       本章涉及 3 個主要概念:

  • MultiView 控件和 Wizard 控件。它們可以把若干個步驟濃縮到一個頁面里,把幾頁的工作組合在一起簡化導航。
  • 站點地圖模型。它允許定義網站的導航結構並直接綁定到富控件。
  • 富導航控件。這類控件包括 TreeView 和 Menu。雖然它們並不僅僅限於導航,但它們非常適合用於導航。

 

ASP.NET 4 中導航的變化

  • 路由。它最初被作為 ASP.NET MVC 的一部分引入,但現在也可以用於處理 URL 並把請求重定向到合適的 Web 表單。路由的主要優點是支持更清晰、更合乎邏輯的 URL 系統,它能夠讓搜索引擎更輕易的發現和索引網站的內容。
  • 更靈活的向導。Wizard 控件現在支持一個全新的 LayoutTemplate,如果要用我們自己設計的布局代替內置的布局,那么它能夠帶給你更多的支持。
  • 更標准的菜單。Menu 控件不再使用 HTML 表,而是通過一組合理設置的 CSS 樣式創建自己的布局。

 

 

多視圖頁面

       大多數網站把任務分解到幾個頁面里。例如,在一個電子商務網站里,如果往購物車里添加一個項並把它帶到結賬處,就需要從一個頁面跳轉到另一個頁面。這是最簡單的方式,同時也容易通過編程實現(只要通過某種狀態管理技術把信息從一個頁面傳送到另一個頁面)。

       在其他一些情形下,你可能會希望把原本在幾個不同頁面里的代碼放到同一個頁面。例如,你希望提供同一數據的不同視圖,用戶可以切換視圖而不必離開當前頁面;或者,你可能需要處理一個多步驟的小任務(好比注冊賬號的流程)而不希望為如何在頁面間傳送相關信息傷腦筋。

 

       使用多個頁面還是在一個頁面中提供多個視圖,從用戶的角度來說可能沒什么區別。在一個設計良好的網站里,用戶看到的只是采用多個視圖的方式保持 URL 不變。主要的差別在於編程模型。

       使用多個頁面,代碼能更好的分離,但需要花更多精力處理頁面如何交互(它們共享或傳送信息的方式)。

       使用多個視圖,你會失去代碼分離的好處,但更容易為不可分解的細小任務編碼。

 

       在 ASP.NET 1.x 里,在一個頁面中建立多個視圖的唯一辦法是在頁面中添加若干個 Panel 控件,每個面板可以代表一個視圖或一個步驟,然后使用 Visible 屬性進行控制。你不得不在頁面里添加管理面板的額外代碼,此外,它不是很健壯,一些微小的錯誤可能導致同時顯示兩個面板。

       有了 ASP.NET 4,你不必再從零開始設計自己的多視圖系統,而是可以使用兩個更高級的控件來幫助簡化設計:MultiView 和 Wizard 。

 

 

MultiView 控件

       MultiView 是兩個多視圖控件中較簡單的一個。就本質而言,MultiView 提供了一個聲明多個視圖但每次只顯示其中一個的方式。MultiView  沒有默認的用戶界面,它和前面介紹的自定義面板的方式等效。

       創建 MultiView 的過程非常的直觀,看下面示例即能明白:

<asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
    <asp:View ID="View1" runat="server">
        <b>Showing View #1<br /><br /><asp:Image ID="Image1" runat="server" ImageUrl="../images/cookies.jpg" /></b>
    </asp:View>
 
    <asp:View ID="View2" runat="server">
        <b>Showing View #2</b><br /><br />Text Content.
    </asp:View>
 
    <asp:View ID="View3" runat="server">
        <b>Showing View #3</b><br /><br /><asp:Calendar ID="Calendar1" runat="server"></asp:Calendar>
    </asp:View>
</asp:MultiView>

       另外,也可以通過編程添加視圖,實例化一個新的視圖對象通過 Views 集合的 Add()或 AddAt()把它加入到 MultiView

 

       添加一些控件對 MultiView 進行測試:

image

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        DropDownList1.DataSource = MultiView1.Views;
        DropDownList1.DataTextField = "ID";
        DropDownList1.DataBind();
    }
}
 
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
    MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
}
 
protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)
{
    DropDownList1.SelectedIndex = MultiView1.ActiveViewIndex;
}

       所有按鈕(Button、ImageButton、LinkButton)觸發的代碼邏輯當然可以手工實現,不過 ASP.NET 也提供了智能響應,只要依照下表對按鈕的 CommandName 屬性正確設置即可:

命令名稱

MultiView 字段

描    述

PreView PreviousViewCommandName 移動到前一視圖
NextView NextViewCommandName 移動到后一視圖
SwitchViewByID SwitchViewByIDCommandName 移動到具有特定 ID 的視圖,這個 ID 從按鈕控件的 CommandArgument 屬性獲得
SwitchViewByIndex SwitchViewByIndexCommandName 移動到特定數字序號的視圖。這個序號從按鈕控件的 CommandArgument 屬性獲得

 

性能問題

       關於 MultiView 要知道的最重要的細節是:

  • 它和富數據控件(GridView、FormView 等)不同,MultiView 不是命名容器,簡單地說,MultiView 中不能存在相同名稱的控件,如,兩個叫 textBox1 的文本框。
  • 視圖里引發的事件可以很方便的配置其他視圖里的控件。
  • 加入視圖里的控件,和頁面其他部分的控件沒有什么區別。

       由於這些原因,用 MultiView 創建的頁面比普通頁面的負載大,這是因為整個控件模型(包括所有視圖上的控件),都在每次回發時創建並持久化到視圖狀態里

       多數情況下,它們對性能不會有太大的影響。除非你正在通過編程處理大量的控件(此時你可能需要設置這些控件的 EnableViewState 為 false);或者你正在使用多個數據源,每次回發時所有的數據源都執行自己的查詢,所有的視圖都會被重新綁定(包括那些不顯示的視圖),為了避免這個情況可以默認控件不綁定,而通過編程來綁定,或者取消當前不可見的視圖的綁定過程。

       當然,不是所有的 MultiView 都會涉及數據綁定。應用 MultiView 的理想場景是處理一組擴展的輸入控件。例如,把一個調查問卷窗體分解成幾個視圖,這樣用戶不需要頻繁使用滾動條了。這個場景 MultiView 會取得很好的效果,調查結束后可以讀取所有視圖中控件的數據。

 

 

Wizard 控件

       Wizard 控件遠比 MultiView 控件更富魅力。它還支持每次顯示幾個視圖中的一個,且還包含一系列自定義的內建行為,包括導航按鈕、帶有分步鏈接的側欄、樣式和模板。

       Wizard 控件提供導航按鈕並在左邊提供一個帶有每個步驟鏈接的側欄,設置 Wizard.DisplaySideBar 可 顯示 / 隱藏 側欄。

 

1. 向導步驟

屬性

描    述

Title 用在側欄作為鏈接顯示的文字
StepType 它的值來自 WizardStepType 枚舉。這個值確定步驟顯示導航按鈕的類型。
AllowReturn 表示用戶是否可以回到這一步。如果設為 false,一旦完成這一步就再也不能返回這里。側欄的鏈接對這個步驟不起作用,它的下一步驟的 Previous 按鈕要么跳過這一步,要么徹底隱藏(取決於先前一個步驟的 AllowReturn 值)

 

       下面的向導包括 4 個步驟,它們一起組成一個問卷。問卷結束時添加了 Complete 步驟,它顯示一些匯總信息。導航按鈕和側欄是自動加入的:

<asp:Wizard ID="Wizard1" runat="server" Width="448px" BackColor="#EFF3FB" BorderColor="#B5C7DE"
    BorderWidth="1px" Font-Names="Verdana" CellPadding="5" ActiveStepIndex="0" Font-Size="Small"
    OnFinishButtonClick="Wizard1_FinishButtonClick">
    <WizardSteps>
        <asp:WizardStep ID="WizardStep1" runat="server" Title="Personal">
            <h3>
                Personal Profile</h3>
            Preferred Programming Language:
            <asp:DropDownList ID="lstLanguage" runat="server">
                <asp:ListItem>C#</asp:ListItem>
                <asp:ListItem>VB</asp:ListItem>
                <asp:ListItem>J#</asp:ListItem>
                <asp:ListItem>Java</asp:ListItem>
                <asp:ListItem>C++</asp:ListItem>
                <asp:ListItem>C</asp:ListItem>
            </asp:DropDownList>
            <br />
        </asp:WizardStep>
        <asp:WizardStep ID="WizardStep2" runat="server" Title="Company">
            <h3>
                Company Profile</h3>
            Number of Employees:
            <asp:TextBox ID="txtEmpCount" runat="server"></asp:TextBox><br />
            Number of Locations: &nbsp;<asp:TextBox ID="txtLocCount" runat="server"></asp:TextBox>
        </asp:WizardStep>
        <asp:WizardStep ID="WizardStep3" runat="server" Title="Software">
            <h3>
                Software Profile</h3>
            Licenses Required:
            <asp:CheckBoxList ID="lstTools" runat="server">
                <asp:ListItem>Visual Studio 2008</asp:ListItem>
                <asp:ListItem>Office 2007</asp:ListItem>
                <asp:ListItem>Windows Server 2008</asp:ListItem>
                <asp:ListItem>SQL Server 2008</asp:ListItem>
            </asp:CheckBoxList>
        </asp:WizardStep>
        <asp:WizardStep ID="Complete" runat="server" Title="Complete " StepType="Complete">
            <br />
            <asp:Label ID="lblSummary" runat="server" Text="Label"></asp:Label>
            <br />
            <br />
            Thank you for completing this survey.<br />
            Your products will be delivered shortly.<br />
            <br />
        </asp:WizardStep>
    </WizardSteps>
    <SideBarStyle VerticalAlign="Top" />
</asp:Wizard>

image

image

image

image

 

2. 向導事件

       可以編寫響應幾個事件的代碼來增強向導,如下表:

ActiveStepChanged 控件每次切換步驟時發生。(用戶點擊了導航按鈕 or 代碼修改了 ActiveStepIndex 屬性
CancelButtonClick 默認情況不會顯示此按鈕。設置 Wizard.DisplayCancelButton 屬性可把它添加到每個步驟。通常,單擊 Cancel 按鈕會退出向導。如果不需要執行任何清理代碼,只要設置 CancelDestinationPageUrl 屬性就會自動重定向。
FinishButtonClick 不解釋
NextButtonClick 不解釋
PreviousButtonClick 不解釋
SideBarButtonClick 不解釋

 

       總體而言,有兩種編程類型的向導編程模型:

  • 逐步提交如果每個步驟包括一個不可回撤的原子操作,應采取這種方式。例如,如果處理的訂單信息涉及信用卡授權,在這之后是最終的購買,你就不能允許用戶回退到上一步重新編輯信用卡號。要支持這種模型,就需要把某些或所有步驟的 AllowReturn 屬性設為 false,並且響應 ActiveStepChanged 事件為每個步驟提交變更。
  • 最后提交。如果每個步驟都是為最后要執行的操作收集數據,應使用這種方式。例如,收集用戶信息進行注冊。最后可以響應 FinishButtonClick 事件。

       上一示例,響應了 FinishButtonClick 事件,最后呈現了一個信息的匯總:

protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
{
    StringBuilder sb = new StringBuilder();
    sb.Append("<b>You chose: <br />");
    sb.Append("Programming Language: ");
    sb.Append(lstLanguage.Text);
    sb.Append("<br />Total Employees: ");
    sb.Append(txtEmpCount.Text);
    sb.Append("<br />Total Locations: ");
    sb.Append(txtLocCount.Text);
    sb.Append("<br />Licenses Required: ");
    foreach (ListItem item in lstTools.Items)
    {
        if (item.Selected)
        {
            sb.Append(item.Text);
            sb.Append(" ");
        }
    }
    sb.Append("</b>");
    lblSummary.Text = sb.ToString();
}

 

       如果希望知道用戶在向導里執行的是哪一步驟,可以使用 Wizard.GetHistory()方法。它返回目前已經被訪問的 WizardStepBase 對象集合,按時間反向排序。也就是說,集合的第一項代表前一個步驟,以此類推。

 

3. 向導樣式、模板、布局

       毫無疑問,Wizard 控件最強大的功能是允許定制外觀,根據希望對外觀修改程度的不同,你有不同的選擇。對於不大的修改,可以設置各種最上層的屬性。例如,和其他 ASP.NET 控件一樣,可以控制顏色、字體、空格、邊框樣式等。

       利用樣式可以獲得更多控制。和其他基於樣式的控件一樣,樣式沖突時,較具體的樣式(如 SideBarStyle、StartNextButtonStyle)會覆蓋(ControlStyle、NavigationButtonStyle)。

ControlStyle 作用於 Wizard 控件的所有區域
HeaderStyle 作用於 Wizard 控件的所有區域,它只在設置了 HeaderText 屬性后可見
SideBarStyle 作用於 Wizard 控件的所有區域
SideBarButtonStyle 只作用於側欄里的按鈕
StepStyle 作用於控件中定義步驟內容的區域
NavigationStyle 作用於控件底部顯示的導航按鈕的區域
NavigationButtonStyle 只作用於導航區域的導航按鈕
StartNextButtonStyle 作用於第一個步驟里的“下一步”導航按鈕(StepType 為 Start 時)
StepNextButtonStyle 作用於中間步驟的“下一步”導航按鈕(StepType 為 Step 時)
StepPreviousButtonStyle 作用於中間步驟的“上一步”導航按鈕(StepType 為 Step 時)
FinishPreviousButtonStyle 作用於最后一個步驟里的“上一步”導航按鈕(StepType 為 Finish 時)
CancelButtonStyle 如果把 Wizard.DisplayCancelButton 設為 true,它作用於“取消”按鈕

 

 

       如果不能通過屬性和樣式表達到期望的自定義級別,還可以借助模板完全定義 Wizard 控件的外觀。如標題、側欄、按鈕等。所有的模板都是獨立於步驟內容而聲明的。下表顯示模板的完整列表:

HeaderTemplate 定義標題區域的內容
SideBarTemplate 定義側欄,通常它包含每個步驟的導航鏈接
StartNavigationTemplate 定義第一個步驟的導航按鈕
StepNavigationTemplate 定義中間步驟的導航按鈕
FinishNavigationTemplate 定義最后一個步驟的導航按鈕
LayoutTemplate 定義標題、側欄、步驟區域、導航按鈕的總體布置

 

       下面這個標題模板使用數據綁定表達式顯示當前步驟的標題:

</WizardSteps>
    ...
</WizardSteps>
 
<HeaderTemplate>
    <i>Header Template</i> - <b><%= Wizard1.ActiveStep.Title %></b><br /><br />
</HeaderTemplate>

 

       還可以加入下列模版來定制導航按鈕。這個示例保留了標准按鈕(通過顯式聲明)並加入了一些斜體文字,這樣你可以看到每個模板什么時候在使用:

<StartNavigationTemplate>
    <i>StartNavigationTemplate</i><br />
    <asp:Button ID="StartNextButton" runat="server" CommandName="MoveNext" Text="Next" />
</StartNavigationTemplate>
<StepNavigationTemplate>
    <i>StepNavigationTemplate</i><br />
    <asp:Button ID="StepPreviousButton" runat="server" CausesValidation="False" CommandName="MovePrevious"
        Text="Previous" />
    <asp:Button ID="StepNextButton" runat="server" CommandName="MoveNext" Text="Next" />
</StepNavigationTemplate>
<FinishNavigationTemplate>
    <i>FinishNavigationTemplate</i><br />
    <asp:Button ID="FinishPreviousButton" runat="server" CausesValidation="False" CommandName="MovePrevious"
        Text="Previous" />
    <asp:Button ID="FinishButton" runat="server" CommandName="MoveComplete" Text="Finish" />
</FinishNavigationTemplate>

       使用模板的秘訣在於確保使用正確的命令名,這樣 Wizard 控件可以關聯到標准邏輯(否則,你將不得不自己實現導航和排序的代碼,它們冗長且易出錯)。如果你不太確定要使用什么樣的命令名,可以利用智能標簽中的轉換模板來看一看。

 

       驗證控件也可以毫無問題的在 Wizard 里使用。如果驗證控件發現了無效數據,它會阻止用戶單擊側欄的所有鏈接並防止用戶單擊“下一步”繼續操作

      

       最后,你可以使用 LayoutTemplate 模板來突破目前所見到的所有的基於表格的結構。從本質上,通過 LayoutTemplate 可以告訴 ASP.NET 如何對各個模板進行相對定位。借助正確的 PlaceHolder 控件插入各個模板:

<LayoutTemplate>
    <asp:PlaceHolder ID="navigationPlaceHolder" runat="server" />
    <asp:PlaceHolder ID="sideBarPlaceHolder" runat="server" />
    <asp:PlaceHolder ID="WizardStepPlaceHolder" runat="server" />
    <asp:PlaceHolder ID="headerPlaceHolder" runat="server" />
</LayoutTemplate>

       為了獲得更理想的布局,還需要把各個 PlaceHolder 對象放到表格的單元格里或者放到通過 CSS 樣式屬性定位的 <div> 元素里。


免責聲明!

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



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