XML(數據綁定)


       和 SqlDataSource 以及 ObjectDataSource 相似,XmlDataSource 控件以聲明性的方式工作,不過也有兩個主要的不同點:

  • XmlDataSource 不是從數據庫或數據訪問類而是從 XML 文件獲取信息,它為其他控件的數據綁定提供一個 XmlDocument 對象。
  • XML 內容是分層的且可有無限多層。而 SqlDataSource 和 ObjectDataSource 返回的是平面數據表。

 

非層次化綁定

       處理 XML 數據固有的層次化的最簡單的辦法就是忽略它,直接把 XML 數據源綁定到普通的網格控件上:

<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceDVD">
</asp:GridView>
<asp:XmlDataSource ID="sourceDVD" runat="server" DataFile="DvdList.xml"></asp:XmlDataSource>

image

       XmaDataSource 從 DvdList.xml 文件抓取數據並作為 XmlDocument 對象提供給 GridView,然后調用 DataBind()。因為 XmlDocument 實現了 IEnumable 接口,因此 GridView 可以像遍歷 DataView 相似的方式來遍歷它的結構。GridView 遍歷了 XmlDocument.Nodes 集合並獲取了每個 XmlNode 的所有特性。

       (調用 XmlDataSource.GetXmlDocument()可讓它把內容返回為 XmlDocument 對象。)

 

       這里的缺陷非常明顯。XmlDocument 使用的 IEnumerable 實現沒考慮齊全,它只遍歷上層的 XmlNode 對象,這樣你只能見到最上層的節點。也就是說,如果你不定制 XML 數據綁定的過程,就只能綁定到最頂層的節點,並且只能顯示那個節點的特性。如果頂層節點有多種類型,綁定控件將使用第一個節點的架構。

      

       那么,如何顯示 XML 文檔中更深層次的內容?你有以下幾個選擇:

  • 可以用 XPath 過濾出重要的元素
  • 可以用 XSL 把 XML 轉換為你希望的扁平化結構
  • 可以把一個數據控件嵌套到另一個數據控件中
  • 可以使用支持層次數據的控件(.NET 唯一滿足這一需求的現成控件是 TreeView)

 

01. 使用 XPath

       綁定到 XmlNode 時,通常只會顯示特性值。不過,你可以使用 XPath 數據綁定表達式獲得嵌套元素的文本。實現這一目的最靈活的辦法是使用一個定義了 XPath 數據綁定表達式的模版。

       XPath 數據綁定表達式和 Eval()表達式基本類似,不過要基於當前節點提供 XPath 而不是再提供要顯示的字段名字。

<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceDVD" AutoGenerateColumns="false">
    <Columns>
        <asp:TemplateField HeaderText="DVD">
            <ItemTemplate>
                <b><%# XPath("Title") %></b><br />
                <%# XPath("Director") %><br />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

image

       遺憾的是,需要借助模版才能獲得編寫 XPath()表達式的能力。這限制了 XML 數據綁定場景中其他控件(如下拉列表框)的使用。

 

       還可以使用 XPath 過濾出初始的匹配集,例如,要顯示所有的演員名單:

<asp:XmlDataSource ID="sourceDVD" runat="server" DataFile="DvdList.xml" 
    XPath="/DvdList/DVD/Starring/Star">
</asp:XmlDataSource>
<asp:TemplateField HeaderText="DVD">
    <ItemTemplate>
        <%
   1: #XPath(".") 
%>
    </ItemTemplate>
</asp:TemplateField>

image

       還可以用 XPath 屬性創建一個簡單的記錄瀏覽器,只要讓用戶從另一個控件(如下拉列表框)選擇 ID,然后相應的設置 XPath 屬性即可:

<asp:DropDownList ID="DropDownList1" runat="server" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
    AutoPostBack="True" Width="119px">
    <asp:ListItem Value="1">a</asp:ListItem>
    <asp:ListItem Value="2">b</asp:ListItem>
    <asp:ListItem Value="3">c</asp:ListItem>
    <asp:ListItem Value="4">d</asp:ListItem>
    <asp:ListItem Value="5">e</asp:ListItem>
</asp:DropDownList>
<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceDVD" AutoGenerateColumns="false">
    <Columns>
        <asp:TemplateField HeaderText="DVD">
            <ItemTemplate>
                <%
   1: #XPath("Price") 
%>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:XmlDataSource ID="sourceDVD" runat="server" DataFile="DvdList.xml" XPath="/DvdList/DVD">
</asp:XmlDataSource>
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
    sourceDVD.XPath = "/DvdList/DVD[@ID=" + DropDownList1.SelectedValue + "]";
}

       這個記錄瀏覽器可以工作,是因為數據綁定只在頁面生命周期塊結束時才執行。

 

 

02. 嵌套的網格

       網格的嵌套可以讓你處理更加復雜的 XML 結構。ASP.NET 可以提供這一實現而不需要你編寫任何的代碼。

       首先,定義外層的網格,使用模版就可以顯示標題和導演的信息,在第一個 GridView 的模版內部定義第二個 GridView,技巧在於 DataSource 屬性,你可以用一個新的 XPathSelect()數據綁定語句來設置它。

<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceDVD" AutoGenerateColumns="false">
    <Columns>
        <asp:TemplateField HeaderText="DVD">
            <ItemTemplate>
                <b>
                    <%
   1: # XPath("Title") 
%></b><br />
                <%
   1: # XPath("Director") 
%><br />
                <br />
                <i>Starring...</i><br />
 
                <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="false" GridLines="None"
                    ShowHeader="false" DataSource='<%# XPathSelect("Starring/Star") %>'>
                    <Columns>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <%
   1: # XPath(".") 
%><br />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:XmlDataSource ID="sourceDVD" runat="server" DataFile="DvdList.xml"></asp:XmlDataSource>

image

 

 

03. 使用 TreeView 的層次綁定

       某些控件有內建的智能,可以直接顯示層次化的數據。最典型的就是 TreeView。把 TreeView 綁定到 XmlDataSource 時,它調用 XmlDataSource.GetHierarchicalView()方法並顯示 XML 文檔的完整結構

       這個默認顯示離我們所期望的還太遠,只顯示文檔結構(元素名稱),而不顯示文檔內容(元素文本),還忽略了特性。

       為了改善這一狀況必須進行調整。首先,把 TreeView.AutoGenerateDataBindings 設為 false,然后顯式地把 XML 文檔的不同部分映射到各節點。創建映射時,需要在<DataBindings>節內加入<asp:TreeNodeBinding />元素,必須從根元素開始,為你希望綁定的每一層添加綁定,不能跳過任何一層。每個<asp:TreeNodeBinding />必須明確它要綁定的節點名稱(DataMember)、它應顯式的文本(TextField),節點的隱藏值(ValueField)。遺憾的是,TextField 和 ValueField 都是設計用於綁定特性的,如果你要綁定到元素的內容,就只能通過比較笨的方式指定 #InnerText 代碼。

<asp:TreeView ID="TreeView1" runat="server" AutoGenerateDataBindings="false" DataSourceID="sourceDVD">
    <DataBindings>
        <asp:TreeNodeBinding DataMember="DvdList" Text="Root" Value="Root" />
        <asp:TreeNodeBinding DataMember="DVD" TextField="ID" />
        <asp:TreeNodeBinding DataMember="Title" TextField="#InnerText" />
        <asp:TreeNodeBinding DataMember="Director" TextField="#InnerText" />
        <asp:TreeNodeBinding DataMember="Price" TextField="#InnerText" />
        <asp:TreeNodeBinding DataMember="Starring" Text="Starring" />
        <asp:TreeNodeBinding DataMember="Star" TextField="#InnerText" />
    </DataBindings>
</asp:TreeView>
<asp:XmlDataSource ID="sourceDVD" runat="server" DataFile="DvdList.xml"></asp:XmlDataSource>

image

 

 

04. 使用 XSLT 轉換結構后綁定

        XmlDataSource 為 XSL 轉換提供了內建的支持。不同的是,你不是用樣式表把 XML 轉換為 HTML ,而是用它把源 XML 文檔轉換為便於數據綁定使用的 XML 結構。例如,可以生成一個恰好含有你需要的結果的 XML 文檔,並且生成為扁平化結構(把元素轉換為特性)以方便數據綁定。

       要指定樣式表,你可以把 XmlDataSource.TransformFile 指向一個含有 XSL 轉換的文件,或者使用 XmlDataSource.Transform 屬性把樣式表作為單個長字符串。還可以同時使用樣式表和XPath表達式,但總是優先使用樣式表。

       使用 XmlDataSource XSLT 功能的一個充分理由是,你必須把 XML 數據准備好供層次控件(TreeView)使用。

       例如,要創建一個按電影分組的演員列表,你也可以把所有的內容放到特性里,這樣便於綁定。以下是你需要的最終的 XML:

<Movies>
  <DVD ID="1" Title="The Matrix">
    <Star Name="Keanu Reeves" />
    <Star Name="Laurence Fishburne" />
  </DVD>
 
  <DVD ID="2" Title="Forrest Gump">
    <Star Name="Tom Hanks" />
    <Star Name="Robin Wright" />
  </DVD>
  ......
</Movies>

       可以用下面的 XSL 樣式表把原始的 XML 轉換成為這種標記:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
 
  <xsl:template match="/">
    <!-- Rename the root element -->
    <xsl:element name="Movies">
      <xsl:apply-templates select="DvdList/DVD"></xsl:apply-templates>
    </xsl:element>
  </xsl:template>
 
  <xsl:template match="DVD">
    <!-- Transform the <DVD> element into a new element with a different structure. -->
    <xsl:element name="DVD">
      <xsl:attribute name="ID">
        <xsl:value-of select="@ID"/>
      </xsl:attribute>
      <!-- Put the nested <Title> into an attribute. -->
      <xsl:attribute name="Title">
        <xsl:value-of select="Title/text()"/>
      </xsl:attribute>
      <xsl:apply-templates select="Starring/Star" />
    </xsl:element>
  </xsl:template>
 
  <xsl:template match="Star">
    <xsl:element name="Star">
      <xsl:attribute name="Name">
        <xsl:value-of select="text()"/>
      </xsl:attribute>
    </xsl:element>
  </xsl:template>
 
 
</xsl:stylesheet>

       現在就可以幫頂到 TreeView 上進行顯示了:

<asp:TreeView ID="TreeView1" runat="server" DataSourceID="sourceDVD" AutoGenerateDataBindings="false">
    <DataBindings>
        <asp:TreeNodeBinding DataMember="Movies" Text="Movies" />
        <asp:TreeNodeBinding DataMember="DVD" TextField="Title" />
        <asp:TreeNodeBinding DataMember="Star" TextField="Name" />
    </DataBindings>
</asp:TreeView>
<asp:XmlDataSource ID="sourceDVD" runat="server" DataFile="DvdList.xml" TransformFile="DvdList2.xslt">
</asp:XmlDataSource>

image

 

 

05. 綁定到來自其他源的 XML 內容

       到目前為止,所有示例都是幫頂到文件中的 XML,不過這並不是唯一可能遇到的情況。你還可以通過 XmlDataSource.Data 屬性提供一個 XML 字符串:

private void XmlDataBinding(string xmlContent)
{
    sourceDVD.Data = xmlContent;
}

 

      

通過 XmlDataSource 更新 XML

       XmlDataSource 不支持可編輯的綁定(綁定GridView,選擇編輯,視圖提交更新時會得到一個錯誤)。然而 XmlDataSource 確實提供了 Save()方法。這個方法調用當前的 XML 內容替代 DataFile 屬性指定的文件。雖然需要加入代碼才能調用 Save()方法,但有些開發人員已經用這項技術提供了可編輯的 XML 數據綁定。

       基本思路是這樣的:

  1. 用戶提交控件中的更新時,代碼調用 XmlDataSource.GetXmlDocument()方法以 XmlDocument 對象的形式獲得當前 XML 的內容
  2. 代碼找到相應的節點並用 XmlDocument 的功能實現變更(查找和編輯給定的節點、刪除節點和添加節點)
  3. 最后,代碼必須調用 XmlDataSource.Save()方法提交更新。

       雖然代碼這個方法可以工作的很出色,但它並不是設計網站的好辦法。如果確實需要修改 XML 的內容,那么用前面描述過的 XML 類在一個單獨的組件內實現邏輯通常會更好一些。


免責聲明!

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



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