0

I'm am trying to figure out how to access a subnode in serialized xml data using a repeater in my asp.net web form application. I can access all the xml element data on the first layer, but not on the second (Benefits).

My issue is that I cannot access Item.Benefits.BenefitImage or Item.Benefits.Benefit within the repeater.

Any pointer would be greatly appreciated.

Here is a snippet of my xml data:

<Category Key="acid" Rank="30">
  <Intro> ... </Intro>
  <Description> ... </Description>
  <Benefits>
    <Benefit Key="promote_texture">Promote smoother skin texture</Benefit>  
    <Benefit Key="promote_tone">Promote even skin tone</Benefit>
    <Benefit Key="enhance_radiance">Enhance skin radiance</Benefit>      
  </Benefits>
</Category>

Here is a snippet of the repeater in the .ASPX page:

<asp:Panel runat="server" CssClass="benefits-wrapper">
  <asp:Repeater ID="BenefitsList" runat="server" ItemType="OrdinarySite.Models.ProductCategory" SelectMethod="CategoryList_GetData">
    <ItemTemplate>
      <div class="benefits">                                 
        <div class="benefit">
           <asp:Image runat="server" CssClass="benefit-img" ImageUrl="<%# Item.Benefits.BenefitImage %>" />
           <asp:Label runat="server" CssClass="benefit-desc" Text="<%# Item.Benefits.Benefit %>"></asp:Label>
        </div>                                                               
      </div>
      <div class="benefits-copy">
        <asp:Label runat="server" CssClass="heading" Text="<%# Item.Name %>"></asp:Label>
        <p><%# Item.Description %></p>
      </div>
    </ItemTemplate>
  </asp:Repeater>
</asp:Panel>

Here is a snippet of the repeater in the .ASPX.CS page:

public partial class Category : BasePage
{
    public string categoryKey;

    protected void Page_Load(object sender, EventArgs e)
    {
        var key = (string)RouteData.Values["key"];

        categoryKey = key;

        if (categoryKey != null) {
            this.Title = categoryKey;
        } else {
            Response.Redirect("~/", true);
        }
    }

    public IEnumerable<ProductCategory> CategoryList_GetData() => CacheObject.Categories.Where(x => x.Key == categoryKey);        
}

Here is a snippet of the the class:

namespace Site.Models
{
[Serializable]
public class ProductCategory : IComparable<ProductCategory>
{
    [XmlAttribute]
    public string Key { get; set; }
    [XmlAttribute]
    public int Rank { get; set; }
    [XmlAttribute]
    public string Naming { get; set; }
    [XmlIgnore]
    public List<Product> Products { get; set; }
    public string Name => Resources.ProductCategory.ResourceManager.GetString(Key);
    public int CompareTo(ProductCategory other) => this.Rank - other.Rank;
    public static string XmlFileName => HostingEnvironment.MapPath("~/App_Data/categories.xml");
    public string Intro { get; set; }
    public string Description { get; set; }

    [XmlArray("Benefits"), XmlArrayItem("Benefit")]
    public List<BenefitsList> Benefits { get; set; }

    [Serializable]
    public class BenefitsList
    {

        [XmlAttribute]
        public string Key { get; set; }
        [XmlElement]
        public string Benefit { get; set; }

        public string BenefitImage => $"~/Images/category/benefits/{Key}.svg";
    }       

    public static List<ProductCategory> LoadXmlData( List<Product> products )
    {
        var cats = SerializerSupport.DeserializeList<ProductCategory>( XmlFileName );
        foreach( var c in cats )
        {
            c.Products = products
                .Where( x => x.Details != null && string.Equals( c.Key, x.Details.CategoryKey, StringComparison.OrdinalIgnoreCase ) )
                .OrderBy(x => x.Details.Title).ToList();
            c.Products.ForEach( x => x.Category = c );
        }

        cats.Sort();
        return cats;
    }
}
Selim Yildiz
  • 4,224
  • 6
  • 14
  • 25
mddev
  • 25
  • 4

1 Answers1

1

You need to use nested repeater to display Benefits within the repeater as follows. See: Nested repeater.

<asp:Panel runat="server" CssClass="benefits-wrapper">
  <asp:Repeater ID="BenefitsList" runat="server" ItemType="OrdinarySite.Models.ProductCategory" SelectMethod="CategoryList_GetData">
    <ItemTemplate>
      <div class="benefits">   
        <asp:Repeater runat="server" DataSource='<%# Eval("Item.Benefits") %>'>
            <div class="benefit">
               <asp:Image runat="server" CssClass="benefit-img" ImageUrl="<%# BenefitImage %>" />
               <asp:Label runat="server" CssClass="benefit-desc" Text="<%# Benefit %>"></asp:Label>
            </div>  
        </asp:Repeater>                                                           
      </div>
      <div class="benefits-copy">
        <asp:Label runat="server" CssClass="heading" Text="<%# Item.Name %>"></asp:Label>
        <p><%# Item.Description %></p>
      </div>
    </ItemTemplate>
  </asp:Repeater>
</asp:Panel>
Selim Yildiz
  • 4,224
  • 6
  • 14
  • 25
  • I've done thing numerous times but keep forgetting that that is what is needed for displaying subnodes. Thank you Selim for your help in helping me solve my problem. – mddev May 14 '20 at 16:15