locked
Dynamic Web Page Creation with xml data source RRS feed

  • Question

  • User340887899 posted
    Hi,
    I am looking for a generic solution for dynamically creating a web page. Currently I have a xml(Sample.xml) which contains the definition of the controls and their properties. This xml is dynamically generated at runtime based on some conditions. I have an ascx file which is as defined below. The data source is set as my Sample.xml. Is there a way that I can use a repeater control and templates to achieve a binding so that this data can be rendered on the web UI? The objective is to write as little code in the code behind file to make a decision on the template to choose based on the type of control. Please read the comments in the SampleTest.ascx to understand what I want to bind at each template. I have so far not found a way to do this. If you have any inputs on how this can be achieved it will help.

    SampleTest.ascx
    -----------------
    <%@ Control
    Language="C#"
    AutoEventWireup="true"
    CodeBehind="SampleTest.ascx.cs"
    Inherits="SampleTest" %>

    <ItemTemplate ID="PageLayout" runat="server" Height="100%" Width="100%">
    <Items>
    <HeaderTemplate>
    <TemplateReference TemplateID="HEADER" runat="server" /> <%-- Bind to this template based on xml if the name of the node is header --%>
    </HeaderTemplate>

    <ContentTemplate >
    <TemplateReference TemplateID="CONTROLS" runat="server" /> <%-- Bind to this template based on xml if the name of the node is controls --%>
    </ContentTemplate>
    </Items>
    </ItemTemplate>

    <ItemTemplate ID="HEADER" runat="server" Width="100%" Height="5%">
    <Items>
    <%-- This template will contain label bound to the headertext of the xml --%>
    <asp:label ID="Heading" runat="server" Text=";headertext" />
    </Items>
    </ItemTemplate>

    <ItemTemplate ID="CONTROLS" runat="server" Width="100%" Height="70%">
    <Items>
    <%-- The repeater control should repeate itself as many times as there are controls --%>
    <%-- Based on the control it finds in the xml it then uses the appropriate template --%>
    <asp:Repeater runat="server" BindingType="NAME" BindingExpression="controls" BackColor="Black">
    <ItemTemplate>
    <TemplateReference runat="server" TemplateID="TEXTBOX"/><%-- Bind this template based on xml if the control is textbox --%>
    <TemplateReference runat="server" TemplateID="CHECKBOX"/><%-- Bind this template based on xml if the control is checkbox --%>
    </ItemTemplate>
    </asp:Repeater>
    </Items>
    </ItemTemplate>

    <ItemTemplate ID="TEXTBOX" runat="server" Width="100%" Height="70%">
    <%-- This template will contain text box control with the properties set appropriately and data bound to the value--%>
    </ItemTemplate>

    <ItemTemplate ID="CHECKBOX" runat="server" Width="100%" Height="70%">
    <%-- This template will contain checkbox controls with the properties set appropriately --%>
    </ItemTemplate>


    Sample XML below
    ---------------------
    <?xml version="1.0"?>
    <page>
    <header>
    <headertext> Temperature Convertor </headertext>
    </header>
    <controls>
    <textbox>
    <enabled>true</enabled>
    <hasdependants>false</hasdependants>
    <visible>true</visible>
    <name>Centigrade</name>
    <value>0</value>
    <row>1</row>
    <column>1</column>
    </textbox>
    <checkbox>
    <enabled>true</enabled>
    <visible>true</visible>
    <hasdependants>false</hasdependants>
    <name>CheckBox</name>
    <row>2</row>
    <column>1</column>
    </checkbox>
    <textbox>
    <enabled>true</enabled>
    <hasdependants>false</hasdependants>
    <visible>true</visible>
    <name>Fahrenheit</name>
    <value>0</value>
    <row>3</row>
    <column>1</column>
    </textbox>
    </controls>
    </page>
    Wednesday, July 29, 2015 1:01 AM

Answers

  • User-84896714 posted

    Hi tfran,

    Welcome to ASP.NET forum. TemplateReference is used to dynamic create visual studio project/file. It can't used in ASP.NET User Control. If you want to show xml element as webforms control, I suggest you read xml first, and dynamic create control use C# in code behind.  I wrote demo for you reference.
    Convert xml to object, you could use XmlSerializer.

        [XmlRoot("page")]
        public class DynamicPage
        {
            [XmlElement("header")]
            public DynamicPageHeader Header { get; set; }
            [XmlArray("controls")]
            [XmlArrayItem("textbox", typeof(DynamicTextBox))]
            [XmlArrayItem("checkbox", typeof(DynamicCheckBox))]
            public List<DynamicControl> Controls { get; set; }
            //Row count
            public int MaxRow
            {
                get { return Controls.Max(s => s.Row); }
            }
            //Column Count
            public int MaxColumn
            { 
                get { return Controls.Max(s => s.Column); } 
            }
        }
        [XmlRoot("header")]
        public class DynamicPageHeader
        {
            [XmlElement("headertext")]
            public string HeaderText { get; set; }
        }
        public abstract class DynamicControl
        {
            [XmlElement("enabled")]
            public bool Enabled { get; set; }
            [XmlElement("visible")]
            public bool Visible { get; set; }
            [XmlElement("hasdependants")]
            public bool Hasdependants { get; set; }
            [XmlElement("name")]
            public string Name { get; set; }
            [XmlElement("value")]
            public string Value { get; set; }
            [XmlElement("row")]
            public int Row { get; set; }
            [XmlElement("column")]
            public int Column { get; set; }
    
            public abstract Control GetControl();
        }
        [XmlRoot("textbox")]
        public class DynamicTextBox:DynamicControl
        {
            //Get webform control
            public override Control GetControl()
            {
                return new TextBox() { ID = Name, Text = Value, Visible = Visible, Enabled = Enabled };
            }
        }
        [XmlRoot("checkbox")]
        public class DynamicCheckBox : DynamicControl
        {
            //Get webform control
            public override Control GetControl()
            {
                return new CheckBox() { ID = Name, Visible = Visible, Enabled = Enabled };
            }
        }

    User control aspx file.

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="LoadFromXML.ascx.cs" Inherits="WebFormCSharp.UserControl.LoadFromXML" %>
    <h1>
        <asp:Label ID="lblHeader" runat="server" Text=""></asp:Label>
    </h1>
    <asp:Table ID="tableContainer" runat="server">
    
    </asp:Table>

    Dynamic create webform control according xml.

        public partial class LoadFromXML : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(DynamicPage));
                using(FileStream stream = File.Open(Server.MapPath("~/UserControl/control.xml"), FileMode.Open, FileAccess.Read))
                {
                    //Deserialize DynamicPage object from xml
                    DynamicPage dpage = (DynamicPage)serializer.Deserialize(stream);
                    //Set header text
                    lblHeader.Text = dpage.Header.HeaderText;
                    //Init table rows and columns
                    for (int i = 0; i < dpage.MaxRow; i++)
                    {
                        var row = new TableRow();
                        for (int j = 0; j < dpage.MaxColumn; j++)
                        {
                            row.Cells.Add(new TableCell());
                        }
                        tableContainer.Rows.Add(row);
                    }
                    //Add control to page
                    foreach (var control in dpage.Controls)
                    {
                        tableContainer.Rows[control.Row - 1].Cells[control.Column - 1].Controls.Add(control.GetControl());
                    }
                }
            }
        }

    Best Regards,
    Wang Li

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, July 29, 2015 11:09 PM

All replies

  • User-84896714 posted

    Hi tfran,

    Welcome to ASP.NET forum. TemplateReference is used to dynamic create visual studio project/file. It can't used in ASP.NET User Control. If you want to show xml element as webforms control, I suggest you read xml first, and dynamic create control use C# in code behind.  I wrote demo for you reference.
    Convert xml to object, you could use XmlSerializer.

        [XmlRoot("page")]
        public class DynamicPage
        {
            [XmlElement("header")]
            public DynamicPageHeader Header { get; set; }
            [XmlArray("controls")]
            [XmlArrayItem("textbox", typeof(DynamicTextBox))]
            [XmlArrayItem("checkbox", typeof(DynamicCheckBox))]
            public List<DynamicControl> Controls { get; set; }
            //Row count
            public int MaxRow
            {
                get { return Controls.Max(s => s.Row); }
            }
            //Column Count
            public int MaxColumn
            { 
                get { return Controls.Max(s => s.Column); } 
            }
        }
        [XmlRoot("header")]
        public class DynamicPageHeader
        {
            [XmlElement("headertext")]
            public string HeaderText { get; set; }
        }
        public abstract class DynamicControl
        {
            [XmlElement("enabled")]
            public bool Enabled { get; set; }
            [XmlElement("visible")]
            public bool Visible { get; set; }
            [XmlElement("hasdependants")]
            public bool Hasdependants { get; set; }
            [XmlElement("name")]
            public string Name { get; set; }
            [XmlElement("value")]
            public string Value { get; set; }
            [XmlElement("row")]
            public int Row { get; set; }
            [XmlElement("column")]
            public int Column { get; set; }
    
            public abstract Control GetControl();
        }
        [XmlRoot("textbox")]
        public class DynamicTextBox:DynamicControl
        {
            //Get webform control
            public override Control GetControl()
            {
                return new TextBox() { ID = Name, Text = Value, Visible = Visible, Enabled = Enabled };
            }
        }
        [XmlRoot("checkbox")]
        public class DynamicCheckBox : DynamicControl
        {
            //Get webform control
            public override Control GetControl()
            {
                return new CheckBox() { ID = Name, Visible = Visible, Enabled = Enabled };
            }
        }

    User control aspx file.

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="LoadFromXML.ascx.cs" Inherits="WebFormCSharp.UserControl.LoadFromXML" %>
    <h1>
        <asp:Label ID="lblHeader" runat="server" Text=""></asp:Label>
    </h1>
    <asp:Table ID="tableContainer" runat="server">
    
    </asp:Table>

    Dynamic create webform control according xml.

        public partial class LoadFromXML : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(DynamicPage));
                using(FileStream stream = File.Open(Server.MapPath("~/UserControl/control.xml"), FileMode.Open, FileAccess.Read))
                {
                    //Deserialize DynamicPage object from xml
                    DynamicPage dpage = (DynamicPage)serializer.Deserialize(stream);
                    //Set header text
                    lblHeader.Text = dpage.Header.HeaderText;
                    //Init table rows and columns
                    for (int i = 0; i < dpage.MaxRow; i++)
                    {
                        var row = new TableRow();
                        for (int j = 0; j < dpage.MaxColumn; j++)
                        {
                            row.Cells.Add(new TableCell());
                        }
                        tableContainer.Rows.Add(row);
                    }
                    //Add control to page
                    foreach (var control in dpage.Controls)
                    {
                        tableContainer.Rows[control.Row - 1].Cells[control.Column - 1].Controls.Add(control.GetControl());
                    }
                }
            }
        }

    Best Regards,
    Wang Li

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, July 29, 2015 11:09 PM
  • User340887899 posted

    Hi Wang Li,

      Thank you for your response.  What you have in the code behind is currently how I have implemented.  However I am looking for a simpler solution where I do not have to parse my xml.  Could you please clarify one point in your reply.  You have mentioned that "TemplateReference  is used to dynamic create visual studio project/file".  Is it that the key word "TemplateReference" that I have used is wrong.  Is there any other way to define a template in my ascx page?

    Regards,

    tfran

     

     

    Thursday, July 30, 2015 1:08 AM
  • User-84896714 posted

    Hi tfran,

    Is it that the key word "TemplateReference" that I have used is wrong. 

    Yes, we cann't use TemplateReference in asp.net.

    Is there any other way to define a template in my ascx page?

    According to your requirement, that's the only way I could provide.

    Best Regards,
    Wang Li

    Thursday, July 30, 2015 2:20 AM