This article and code snippet here shows how to bind a repeater control and Gridview control to a relational data so the GridView and the Repeater control show related data.

Inserting a Repeater within Gridview is an easy task but to bind the headline in the GridViewand data items correspond to the particular head line into a Repeater control is a little bit trickier job. According to a requirement, I have to bind company name as headline and top four news of the company as its data items under the headline, again next company name and top four news of respective company and so on.

Here, I have to use a repeater control to bind news while I am binding company name in grid view. We can also make the company name as link button which on click, will navigate to corresponding page. For this we have to pass navigate URL for a company dynamically. We can do this by writing code in OnRowDataBound event of gridview. We can also make news row as link.

Mechanism

Take a GridView control and set its AutoGenerateColumns="False".  Put a label control within the GridView to bind company name. You can also use its BoundField.

Now, within the same ItemTemplate, place a repeater control and put one more label control within this repeater control to bind news of respective company. If you are using different ItemTemplate, then it will bind in another column, otherwise it will bind in the same column but in different rows as shown in fig. below.

Now it is your choice, whether you are interested to bind in same or different column. Here, I have used div tag, to separate company and their news rows. The div tag gives one more advantage i.e. we can apply CSS to a particular div for richer UI.

The complete source code is here.

      <div style="width:400px; font-family:Arial; font-size:small">
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" Width="100%" GridLines="None">
            <Columns>
                <asp:TemplateField>
                <ItemTemplate>
                    <div style="color:Blue;font-weight:bold">
                        <asp:Label ID="Label1" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"compname") %>'></asp:Label>
                    </div>
                    <asp:Repeater ID="Repeater1" runat="server" DataSource='<%#DataBinder.Eval(Container, "DataItem.InnerVal") %>'>
                    <ItemTemplate>
                    <div style="padding-left:20px; padding-top:5px">
                        <asp:Label ID="Label2" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"news") %>'></asp:Label>
                    </div>
                   
                    </ItemTemplate>
                    </asp:Repeater>
                    <div style="text-align:right">
                        <asp:HyperLink ID="link" runat="server">More</asp:HyperLink>
                    </div>
                </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </div>

It is obvious that we have to write some code in code behind to get the data from database.

I have used a stored procedure that returns two tables, i.e. for company name and news section. 

Now I am making a relation between these two tables in a DataSet, with column 'compname'.  And finally, binding the data in data controls.  

Here is the code on the page load event handler. As you can see from the binddat method, I get data in a DataSet from the database, sets a relation and sets the DataSource property of the GridView control to the DataSet. Rest data binding is done in the above ASP.NET code.

       protected void Page_Load(object sender, EventArgs e)
    {
        binddata();
    }

    // Function to bind data in data controls..
    public void binddata()
    {
        string str = "Data Source=VS-NAVINCHANDRA\\SQLEXPRESS;Initial Catalog=dbNavin;Integrated Security=SSPI"; // your connection string here
        SqlConnection con = new SqlConnection(str);
        DataSet ds = new DataSet();
        SqlDataAdapter da = new SqlDataAdapter("getCompNews", con); // name of your stored procedure,
        da.Fill(ds);

        ds.Relations.Add("InnerVal", ds.Tables[0].Columns["compname"], ds.Tables[1].Columns["compname"]);   // making a relation between two tables.
        GridView1.DataSource = ds.Tables[0];
        GridView1.DataBind();
    }

On clicking 'More' link button, it should redirect to page which shows all the news of that particular company. So, we have to set NavigateUrl property for this control dynamically. To do this, write the code given below. As I have passed company name in query string, you can very easily access respective company data from your table to display.

      protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            HyperLink lnkMore = (HyperLink)e.Row.FindControl("link");
            Label lbl=(Label)e.Row.FindControl("Label1");
            lnkMore.NavigateUrl = "~/Company.aspx?cmp="+lbl.Text;
        }
    }

As I have mentioned for stored procedure, so you must create a stored procedure that returns tables. If you don't want to create it, just copy and paste the stored procedure given below and compile it. Make sure that your database contains all tables and respective columns.

      Create Procedure [dbo].[getCompNews]

               as
               begin
               create table #Temp
              (
               compname varchar(50),
               news varchar(150)
               )

               Insert into #Temp
               select a.compname, b.news from Company as a
               inner join  CompNews as b on a.CompId=b.CompId order by compname
 
              
Select distinct compname from #Temp
               select * from #Temp
               end
               drop table #Temp

Here I am using stored procedure instead of using direct sql query. Offcourse a stored procedure is much better than a query.