1
votes

I have a problem with the repeater asp control.

I have a table on my database called course with columns CourseID, CourseName, CourseLink and another table called module with columns ModuleID, ModuleName. And another table called timetable with columns CourseID and ModuleID.

The way this works is when I click on HyperLink1,the paragraph bellow with the the same course id, it would changes the paragraph's style display from hidden to show (I used JavaScript to complete this function so it's not the problem here).

What I would like to know is, how can I list the ModuleNames That relate to that specif course ID.

I was thinking of using another repeater inside a repeater. However that just complicate things and to be hones really confuses me.

How can I get this to work, don't work about the sql because I am comfortable in creating a select command.

Here is the the ASP.NET forum.

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="DataSource1">
    <ItemTemplate>
        <p>
            <a id="HyperLink1" runat="server" href='<%# Eval("courselink") %>'>
                <%# Eval("CourseName") %>
            </a> <br />
        </p>

        <p id='<%# Eval("CourseID") %>' style="display:none">
            <%# Eval("ModulName") %>
        </p>
        <br />

    </ItemTemplate>
</asp:Repeater>

Thank you for your time and I look forward to finding out what I can do to solve this problem.

3
I suggest using strongly typed models, obtaining those in your code, and binding that to your Repeater. Then use nested repeaters.mason
Hi @mason I tried that at the beginning however I always had problems with getting ids from within a repeater, by nesting repeaters it would become even more complicated that's why I tried looking for other options, but it seems like this is the only way. Can I ask you to expand further on your explanation please. Thank youmSrsF
nested repeaters have been discussed before.mason

3 Answers

1
votes

You pretty much will need to use another repeater, the trick (if I remember correctly has I haven't used the legacy ASP.NET Web Forms since 2011) is that you hook into the ItemDataBound event in your code behind for the parent repeater and then use the Event Arguments to get the id that you associate to your child table, get that data, lookup the repeater by id from Repeater (I think it's the sender but there is some way to get at it) and bind the data.

I want to note this is much easier and cleaner with ASP.NET MVC and the use of ASP.NET Web Forms is generally discouraged.

1
votes

It could be the worst this way

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="DataSource1">
<ItemTemplate>
    <p>
        <a id="HyperLink1" runat="server" href='<%# Eval("courselink") %>'>
            <%# Eval("CourseName") %>
        </a> <br />
    </p>

    <p id='<%# Eval("CourseID") %>' style="display:none">
       <%# moduleName(Eval("id").ToString()) %>
    </p>
    <br />

</ItemTemplate>

public string moduleName(string id)
{
    string returnValue = "<ul>";
    using (SqlConnection con = new SqlConnection(DB))
    {
        using (SqlCommand com = new SqlCommand("SELECT * FROM module WHERE id = @id", con))
        {
            com.Parameters.AddWithValue("@id", id);
            if (con.State == System.Data.ConnectionState.Closed)
            {
                con.Open();
                using (SqlDataReader dr = com.ExecuteReader())
                {
                    while (dr.Read())
                    {                            
                        returnValue += "<li>"+ dr["modulename"].ToString()+"</li>";
                    }
                }
                con.Close();
            }
        }
    }
    returnValue += "</ul>";
    return returnValue;
}
1
votes

The best solution would be to create a strongly typed model for your presentation and don't use Eval, you would get something like this in your webform:

<asp:Repeater runat="server" DataSourceID="<%# Model %>">
    <ItemTemplate>
        <p>
           <a href="<%# ((Course)Container.DataItem).Link %>"><%# ((Course)Container.DataItem).Name %></a>  
        </p>

        <p id='<%# ((Course)Container.DataItem).ID %>' style="display:none">
            <asp:Repeater runat="server" DataSource="<%# ((Course)Container.DataItem).Modules %>">
                <HeaderTemplate>
                    <ul>
                </HeaderTemplate>
                    <ItemTemplate>
                        <li><%# ((Module)Container.DataItem).Name %></li>
                    </ItemTemplate>
                <FooterTemplate>
                    </ul>
                </FooterTemplate>
            </asp:Repeater>
        </p>
</ItemTemplate>

Then in your code behind create the following property:

public List<Course> Model
{
    get
    {
        List<Course> courses = new List<Course>();
        // Some example data, in your situation you should instantiate the classes based on the data from the database.
        Course exampleCourse = new Course();
        exampleCourse.ID = 1;
        exampleCourse.Name = "Example course";

        // Create example module 1
        Module exampleModule1 = new Module();
        exampleModule1.ID = 10;
        exampleModule1.Name = "Example Module 1";

        // Create example module 2
        Module exampleModule2 = new Module();
        exampleModule2.ID = 11;
        exampleModule2.Name = "Example Module 2";

        // add modules to the course
        exampleCourse.Modules.Add(exampleModule1);
        exampleCourse.Modules.Add(exampleModule2);

        // add course to the courses
        courses.Add(exampleCourse);
        return courses;
    }
}

Classes needed:

public class Course
{
    public int ID { get; set; }
    public string Link { get; set; }
    public string Name { get; set; }
    public List<Module> Modules { get; set; }
    public Course()
    {
        this.Modules = new List<Module>();
    }
}

public class Module
{
    public int ID { get; set; }
    public string Name { get; set; }
}

Last, in your page load, don't forget to databind:

protected void Page_Load(object sender, EventArgs e)
{
    this.DataBind();  
}