0

I have the following code in HTML:

<ul class="ulSpecialty" id="ulSpecialty_selector" runat="server">
    <!--<li class="liSubSpecialty active" data-trait-id="9">
        <a href="test.htm" class="premote trait-link large btn" data-trait-id="9">
            <span class="check"><i class="icon icon-ok"></i></span>
            <span class="name">Cardiology</span>
            <span class="count">6</span>
        </a>
    </li>-->
</ul>

How can I use the code-behind to add three of the commented out LI inside the ulSpecialty_selector UL in my page?

I am thinking as long as the runat="server" is there, I should be able to access it from the codebehind?

SearchForKnowledge
  • 3,663
  • 9
  • 49
  • 122

3 Answers3

1

You're correct, by adding runat="server" you make the UL available as server-side generic HTML control.

The easiest and most direct way is to assign innerHTML property directly in your server-side code:

 ulSpecialty_selector.InnerHtml = @"<li class='liSubSpecialty active' data-trait-id='9'>
        <a href='test.htm' class='premote trait-link large btn' data-trait-id='9'>
            <span class='check'><i class='icon icon-ok'></i></span>
            <span class='name'>Cardiology</span>
            <span class='count'>6</span>
        </a>
    </li>";

Or you can create individual LI elements in your server-side code (again by creating an HtmlGenericControl control and giving it a tag name of "LI"), specifying all properties of the newly created control and adding it to .Controls collection of the UL element above.

Yuriy Galanter
  • 38,833
  • 15
  • 69
  • 136
1

The fastest (and the most ugliest) way that answers your question is this:

Solution 1

.ASPX file

<ul class="ulSpecialty" id="ulSpecialty_selector" runat="server">
</ul>

.ASPX.cs file (code behind)

protected void Page_Load(object sender, EventArgs e)
{
    //the ugly way, fastest that answers your question
    TheUglyWay();            
}


private void TheUglyWay()
{
    StringBuilder innerHtml = new StringBuilder();
    for(var i = 0; i < 3; i++){
        string li = @"
    <li class=""liSubSpecialty active"" data-trait-id=""9"">
        <a href=""test.htm"" class=""premote trait-link large btn"" data-trait-id=""9"">
            <span class=""check""><i class=""icon icon-ok""></i></span>
            <span class=""name"">Cardiology</span>
            <span class=""count"">6</span>
        </a>
    </li>";
        innerHtml.AppendLine(li);
    }

    ulSpecialty_selector.InnerHtml = innerHtml.ToString();
}

The above method is by far the baddest thing you can do to solve your problem. Even if it works, the code does not comply with the .NET "way" of writing web applications, it is unmaintainable and ... just ugly :).

There are better ways, here's one of them that uses the Repeater control:

Solution 2

.ASPX file

<asp:Repeater runat="server" ID="rptSpeciality">
    <HeaderTemplate>
        <ul class="ulSpecialty" id="ulSpecialty_selector">
    </HeaderTemplate>
    <ItemTemplate>
        <li class="liSubSpecialty active" data-trait-id="9">
            <a href="test.htm" class="premote trait-link large btn" data-trait-id="9">
                <span class="check"><i class="icon icon-ok"></i></span>
                <span class="name">Cardiology</span>
                <span class="count">6</span>
            </a>
        </li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>

.ASPX.cs file (code behind)

protected void Page_Load(object sender, EventArgs e)
{
    //the better way, using a repeater
    TheBetterWay();
}

private void TheBetterWay()
{
    //bind the repeater to an array of three elements
    rptSpeciality.DataSource = new object[] { null, null, null };
    rptSpeciality.DataBind();
}

And of course, using this second solution you can insert data from code behind into the li tags using databinding expressions

Lucian
  • 3,981
  • 5
  • 30
  • 34
1

To add <li> to you <ul runat="server"> from your code behind you can do this:

using System.Web.UI.HtmlControls;  

HtmlGenericControl span = new HtmlGenericControl("span");
        span.Attributes.Add("class", "name");
        span.InnerText = "Cardiology";
        //make more spans

        HtmlAnchor a = new HtmlAnchor();
        a.HRef = "test.htm";
        a.Attributes.Add("class", "premote trait-link large btn");
        a.Attributes.Add("data-trait-id", "9");

        HtmlGenericControl li = new HtmlGenericControl("li");
        //add attributes

        a.Controls.Add(span);
        li.Controls.Add(a);

        ulSpecialty_selector.Controls.Add(li);

Cleaner than making a concatenated string!

UPDATE: How to implement this approach with a for loop:

using (var da = new SqlDataAdapter("SELECT * FROM mytable", "connection string"))
{
    var table = new DataTable();
    da.Fill(table);
}

    foreach(DataRow row in table.Rows){
        HtmlGenericControl li = new HtmlGenericControl("li");
        li.Attributes.Add("data-trait-id", row["TraitID"].ToString());

        HtmlAnchor a = new HtmlAnchor();
        a.Attributes.Add("data-trait-id", row["TraitID"].ToString());

        HtmlGenericControl span1 = new HtmlGenericControl("span");
        span1.Attributes.Add("class", "name");
        span1.InnerText = row["Name"].ToString();
        a.Controls.Add(span1);

        HtmlGenericControl span2 = new HtmlGenericControl("span");
        span2.Attributes.Add("class", "count");
        span2.InnerText = row["Count"].ToString();
        a.Controls.Add(span2);

        li.Controls.Add(a);
        ulSpecialty_selector.Controls.Add(li);
    }
zgood
  • 12,181
  • 2
  • 25
  • 26
  • Thank you. Would I be able to use FORLOOP to use an Array to populate those data? – SearchForKnowledge May 08 '14 at 16:44
  • @SearchForKnowledge Yes you can. I will update my answer with a loop example. – zgood May 08 '14 at 17:01
  • So from `HtmlGenericControl span = new HtmlGenericControl("span");` and `ulSpecialty_selector.Controls.Add(li);` would be inside the FOR LOOP? – SearchForKnowledge May 08 '14 at 17:13
  • Yes, if you were adding many `li`'s from your data. You may also need several nested FOR LOOP's. A loop for `li`'s and maybe a loop inside that one for the `span`'s. I will update the example – zgood May 08 '14 at 17:16
  • I took a second look and you may not need a nested loop... but all really depends how your data is setup. But the fact is that you can have many loops if you need them. – zgood May 08 '14 at 17:28
  • Thank you for taking the time to help me. I think most likely I won't need a second loop. – SearchForKnowledge May 08 '14 at 17:52
  • How can I convert this line: `DataRow row in dt.Rows` in the foreach statement to use SQL? – SearchForKnowledge May 08 '14 at 19:38
  • You would have do something like [this](http://msdn.microsoft.com/en-us/library/bh8kx08z(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-3) – zgood May 08 '14 at 20:15
  • Also instead of populating a `DataSet` you can just populate a `DataTable` – zgood May 08 '14 at 20:26
  • I got it to work. To read the data and fill it into the adapter. How can I use your code from above? :) – SearchForKnowledge May 09 '14 at 13:02
  • Sounds like you need a `SqlConnection` not a `OleDbConnection` – zgood May 09 '14 at 13:03
  • This is what I have so far: ` using (OleDbConnection connection = new OleDbConnection("Provider=MSDataShape;Data Provider=SQLOLEDB;" + "Data Source=wmb;Initial Catalog=DSPCONTENT01;User ID=z;Password=zha1")) { OleDbDataAdapter adapter = new OleDbDataAdapter("SHAPE {SELECT * FROM [DSPCONTENT01].[dbo].[BookingTable]} ", connection); DataSet dsLocation = new DataSet(); adapter.Fill(dsLocation, "Customers"); }` – SearchForKnowledge May 09 '14 at 13:04
  • I didn't receive any error. I think I can use your code but have to modify the `foreach` statement? – SearchForKnowledge May 09 '14 at 13:05
  • See if [this](http://stackoverflow.com/questions/6073382/read-sql-table-into-c-sharp-datatable) post helps – zgood May 09 '14 at 13:06
  • Couldn't I replace the DataTable into a DataSet? and still use your code? – SearchForKnowledge May 09 '14 at 13:09
  • You don't need to. A `DataSet` is just a collection of `DataTables`. Since you only need 1 `DataTable` the `DataSet` is unnessecary. I have Updated the post in the **Update** section – zgood May 09 '14 at 13:19
  • BTW I get the following error: ` System.Web.HttpException: 'System.Web.UI.WebControls.BulletedList' does not allow child controls.` – SearchForKnowledge May 09 '14 at 13:30