开发者

How to read an xml subnode into ASP.NET repeater

I am reading XML using xmlreader, and then binding the xml to a Repeater

Here's the code behind:

            XmlReaderSettings settings = new XmlReaderSettings();
        settings.ProhibitDtd = false;

        XmlReader xmlData = XmlReader.Create(webClient.OpenRead(requestUrl), settings);

        try
        {
            xmlData.ReadToFollowing("SearchResults");
            Label1.Text = xmlData.GetAttribute("TotalCount");
            int numberResults = Convert.ToInt32(xmlData.GetAttribute("TotalCount"));
            if (numberResults > 0)
            {
                DataSet ds = new DataSet();
                ds.ReadXml(xmlData);
                Repeater1.DataSource = ds.Tables[1];
                Repeater1.DataBind();
            }
            else
            {
                Repeater1.DataSource = null;
                Repeater1.DataBind();
            }
        }

Here's the repeater

        <asp:Repeater ID="Repeater1" runat="server">
    <HeaderTemplate><b>Results</b><br /><br /></HeaderTemplate>
    <ItemTemplate>
   <a href="<%#DataBinder.Eval(Container.DataItem, "Url")%>">
    <%#DataBinder.Eval(Container.DataItem, "Title")%></a><br />
    </ItemTemplate>
    </asp:Repeater>

And the xml looks like:

  <SearchResults PageSize="1" PageIndex="0" TotalCount="155">
<SearchResult>
  <ContentId>2458</ContentId>
  <Title>Component description</Title>
  <Url>http://whatever/19/p/1537/2458.aspx</Url>
  <Date>2009-06-10T09:34:00+01:00</Date>
  <ContentType>forum</ContentType>
  <Tags>
    <Tag>Component</Tag>
  </Tags>
  <Users>
    <User>
      <Id>2533</Id>
      <DisplayName>Haubent</DisplayName>
      <Username>Haubent</Username>
    </User>
  &l开发者_如何学编程t;/Users>
  <IndexedAt>2010-07-29T15:40:52.414+01:00</IndexedAt>
</SearchResult>

So far so good.

But - I want to be able to show the contents of the DisplayName node in my repeater item template.

I tried

<%#DataBinder.Eval(Container.DataItem, "DisplayName")%>

and

<%#DataBinder.Eval(Container.DataItem, "Users.User.DisplayName")%>

but I get an error:

System.Web.HttpException: DataBinding: 'System.Data.DataRowView' does not contain a property with the name 'Users'.

How to get at the DisplayName?


I think the best (and most natural) way to do this is by using Linq To XML. You can change your try block in this way:

try
{
    xmlData.ReadToFollowing("SearchResults");
    Label1.Text = xmlData.GetAttribute("TotalCount");
    int numberResults = Convert.ToInt32(xmlData.GetAttribute("TotalCount"));
    if (numberResults > 0)
    {
        XDocument xml = XDocument.Parse(xmlData.ReadOuterXml());

        Repeater1.DataSource = xml.Element("SearchResults").Elements("SearchResult");
        Repeater1.DataBind();
    }
    else
    {
        Repeater1.DataSource = null;
        Repeater1.DataBind();
    }
}
catch 
{
    // do some catch
}

passing an XElement collection to de repeater. Then you can declare an OnRepeaterDataBound method similar to this:

protected void Repeater1_OnItemDataBound(object sender, RepeaterItemEventArgs e) 
{
    if ((e.Item.ItemType == ListItemType.Item) || ((e.Item.ItemType == ListItemType.AlternatingItem))) 
    {
        XElement User = ((XElement)e.Item.DataItem).Element("Users").Element("User");

        HyperLink hlUrl = ((HyperLink)e.Item.FindControl("hlUrl"));

        hlUrl.NavigateUrl = ((XElement)e.Item.DataItem).Element("Url").Value;
        hlUrl.Text = User.Element("DisplayName").Value;
    }
}

Having the repeater as:

<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_OnItemDataBound">
    <HeaderTemplate>
        <b>Results</b><br />
        <br />
    </HeaderTemplate>
    <ItemTemplate>
        <asp:HyperLink ID="hlUrl" runat="server" />
    </ItemTemplate>
</asp:Repeater>

On the Repeater1_OnItemDataBound you will be able to parse your xml in the way you want.


If you inspect (by setting a breakpoint at ds.ReadXml(xmlData);) the dataset you'll see that the Users and User elements actually ends up as records in their own tables. The records have id columns that enables you to relate the rows back to the containing SearchResult row.

In your sample your are binding Tables[1], which is the SearchResult table, to the repeater. You should rather make a selection into the dataset joining the three tables together. LINQ should prove useful here.


You can use xml deserialization to helper class, that copies the structure of xml nodes and inside the repeater create another repeater for Users collection like this:

<asp:Repeater runat="server" DataSource='<%# Eval("Users") %>' >...
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜