Search code examples
c#asp.netxmltableexpando

How to display a table which is generated programmatically in a .aspx-Website


I've got a problem with displaying a table which is generated programmatically. Let me explain. I have a XML which is looking like this:

<?xml version="1.0" encoding="utf-8" ?>
<Fragebogen>
  <Header>Header</Header>
  <Tables>
    <Table>
      <Rows>
        <Row>
          <Cells>
            <Cell>Cell 1 Row 1</Cell>
          </Cells>
        </Row>
        <Row>
          <Cells>
            <Cell>Cell 1 Row 2</Cell>
          </Cells>
        </Row>
        <Row>
          <Cells>
            <Cell>Cell 1 Row 3</Cell>
            <Cell>Cell 2 Row 3</Cell>
            <Cell>Cell 3 Row 3</Cell>
          </Cells>
        </Row>
      </Rows>
    </Table>
  </Tables>
</Fragebogen>

This Method:

if (String.IsNullOrWhiteSpace(file) && node == null) return null;

// If a file is not empty then load the xml and overwrite node with the
// root element of the loaded document
node = !String.IsNullOrWhiteSpace(file) ? XDocument.Load(file).Root : node;

IDictionary<String, dynamic> result = new ExpandoObject();

// implement fix as suggested by [ndinges]
var pluralizationService =
    PluralizationService.CreateService(CultureInfo.CreateSpecificCulture("en-us"));

// use parallel as we dont really care of the order of our properties
node.Elements().AsParallel().ForAll(gn =>
{
    // Determine if node is a collection container
    var isCollection = gn.HasElements &&
        (
        // if multiple child elements and all the node names are the same
            gn.Elements().Count() > 1 &&
            gn.Elements().All(
                e => e.Name.LocalName.ToLower() == gn.Elements().First().Name.LocalName) ||

            // if there's only one child element then determine using the PluralizationService if
        // the pluralization of the child elements name matches the parent node. 
            gn.Name.LocalName.ToLower() == pluralizationService.Pluralize(
                gn.Elements().First().Name.LocalName).ToLower()
        );

    // If the current node is a container node then we want to skip adding
    // the container node itself, but instead we load the children elements
    // of the current node. If the current node has child elements then load
    // those child elements recursively
    var items = isCollection ? gn.Elements().ToList() : new List<XElement>() { gn };

    var values = new List<dynamic>();

    // use parallel as we dont really care of the order of our properties
    // and it will help processing larger XMLs
    items.AsParallel().ForAll(i => values.Add((i.HasElements) ?
       GetExpandoFromXml(null, i) : i.Value.Trim()));

    // Add the object name + value or value collection to the dictionary
    result[gn.Name.LocalName] = isCollection ? values : values.FirstOrDefault();
});
return result;

is getting the nodes into a Expando-Object. With this object I'd like to programmatically generate a table in a .aspx-Website. For generating I'm calling this method:

dynamic fragebogen = GetExpandoFromXml(SSG.Fragebogen.Properties.Settings.Default.ConfigPath);
var header = fragebogen.Header;
var tables = fragebogen.Tables;
Table t;
var rows = tables[0].Rows;
TableRow r;
dynamic cells = null;
for (int i = 0; i < rows.Count; i++)
{
    cells = rows[i].Cells;
}
TableCell c;

foreach (var table in tables)
{
    t = new Table();
    foreach (var row in rows)
    {
        r = new TableRow();
        t.Rows.Add(r);
        foreach (var cell in cells)
        {
            c = new TableCell();
            c.Text = cell;
            r.Cells.Add(c);
        }
    }
}

Everything is fine so far. The rows and cells are all added to the table with the right value and there are no exceptions or anything else, but the table isn't displayed in the website. I really don't know why there's nothing displayed, so I hope that you are able to help me.


Solution

  • To display this dynamic generated Table you also need to add it somewhere on Page. Place a PlaceHolder on your page as

    <asp:PlaceHolder runat="server" ID="phOnme"></asp:PlaceHolder>
    

    then on code behind place your table to that holder as:

    Table t;
    // generate the table...
    // add it to page.
    phOnme.Controls.Add(t);