Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Nested gridview in asp.net - Part 43

Suggested Videos 
Part 40 - Detailsview insert update delete using sqldatasource control
Part 41 - Detailsview insert update delete using objectdatasource control
Part 42 - Detailsview insert update delete without using data source controls



In this video we will discuss about nesting gridview controls.

Here is what we want to achieve
1. The outermost grdiview control, should display all the continents available.
2. The Countries column in the outermost gridview control, should display all the countries belonging to the continent in another gridview control. This means we are nesting countries gridview in continents gridview.
3. The Cities column in the countries gridview control, should display all the cities belonging to the country in another gridview control. This means we are nesting cities gridview in countries gridview.





So, this effectively means we are nesting Countries gridview inside Continents gridview and Cities gridview is nested inside Countries gridview
Continents GridView Control => Countries GridView Control  => Cities GridView Control 

We will be using the following tables for this demo. If you need the sql script to create and populate these tables, please refer to Part 34 of asp.net gridview tutorial
tblContinents
tblCountries
tblCities


Step 1: Create an asp.net web application project. Add a class file with name = ContinentDataAccessLayer.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace Demo
{
    public class Continent
    {
        public int ContinentId { get; set; }
        public string ContinentName { get; set; }
    }
    
    public class ContinentDataAccessLayer
    {
        public static List<Continent> GetAllContinents()
        {
            List<Continent> listContinents = new List<Continent>();

            string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
            using (SqlConnection con = new SqlConnection(CS))
            {
                SqlCommand cmd = new SqlCommand("Select * from tblContinents", con);
                con.Open();
                SqlDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    Continent continent = new Continent();
                    continent.ContinentId = Convert.ToInt32(rdr["ContinentId"]);
                    continent.ContinentName = rdr["ContinentName"].ToString();

                    listContinents.Add(continent);
                }
            }

            return listContinents;
        }
    }
}

Step 2: Add a class file with name = CountriesDataAccessLayer.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace Demo
{
    public class Country
    {
        public int CountryId { get; set; }
        public string CountryName { get; set; }
        public int ContinentId { get; set; }
    }
    
    public class CountryDataAccessLayer
    {
        public static List<Country> GetCountriesByContinent(int ContinentId)
        {
            List<Country> listCountries = new List<Country>();

            string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
            using (SqlConnection con = new SqlConnection(CS))
            {
                SqlCommand cmd = new SqlCommand("Select * from tblCountries where ContinentId = @ContinentId", con);
                SqlParameter parameter = new SqlParameter();
                parameter.ParameterName = "@ContinentId";
                parameter.Value = ContinentId;
                cmd.Parameters.Add(parameter);
                con.Open();
                SqlDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    Country country = new Country();
                    country.CountryId = Convert.ToInt32(rdr["CountryId"]);
                    country.CountryName = rdr["CountryName"].ToString();
                    country.ContinentId = Convert.ToInt32(rdr["ContinentId"]);

                    listCountries.Add(country);
                }
            }

            return listCountries;
        }
    }
}

Step 3: Add a class file with name = CitiesDataAccessLayer.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace Demo
{
    public class City
    {
        public int CityId { get; set; }
        public string CityName { get; set; }
        public int CountryId { get; set; }
    }
    
    public class CityDataAccessLayer
    {
        public static List<City> GetCitiesByCountryId(int CountryId)
        {
            List<City> listCities = new List<City>();

            string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
            using (SqlConnection con = new SqlConnection(CS))
            {
                SqlCommand cmd = new SqlCommand("Select * from tblCities where CountryId = @CountryId", con);
                SqlParameter parameter = new SqlParameter();
                parameter.ParameterName = "@CountryId";
                parameter.Value = CountryId;
                cmd.Parameters.Add(parameter);
                con.Open();
                SqlDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    City city = new City();
                    city.CityId = Convert.ToInt32(rdr["CityId"]);
                    city.CityName = rdr["CityName"].ToString();
                    city.CountryId = Convert.ToInt32(rdr["CountryId"]);

                    listCities.Add(city);
                }
            }

            return listCities;
        }
    }
}

Step 4: Add Countries property to Continent class, in ContinentDataAccessLayer.cs file as shown below.
public class Continent
{
    public int ContinentId { get; set; }
    public string ContinentName { get; set; }
    public List<Country> Countries
    {
        get
        {
            return CountryDataAccessLayer.GetCountriesByContinent(this.ContinentId);
        }
    }
}

Step 5: Add Cities property to Country class, in CountryDataAccessLayer.cs file as shown below.
public class Country
{
    public int CountryId { get; set; }
    public string CountryName { get; set; }
    public int ContinentId { get; set; }
    public List<City> Cities
    {
        get
        {
            return CityDataAccessLayer.GetCitiesByCountryId(this.CountryId);
        }
    }
}

Step 6: Add a gridview control to your webform. Configure it, to include 2 BoundFields and 1 template field. Set AutoGenerateColumns="False". The 2 bound fields are for displaying ContinentId and ContinentName. Set DataField and HeaderText properties of these 2 bound fields accordingly.

Step 7: Drag and drop another gridview control, in TemplateField of GridView1 control. By Default the ID for the newly added gridview control will be GridView2. Now configure GridView2 to include 3 bound fields and a template field. The 3 bound fields are for displaying CountryId, CountryName and ContinentId. Set DataField and HeaderText properties of these 3 bound fields accordingly. Set AutoGenerateColumns="False". Set DataSource attribute of GridView2 control to bind to Countries property.
DataSource='<%# Bind("Countries") %>'

Step 8: Drag and drop another gridview control, in TemplateField of GridView2 control. By Default the ID for the newly added gridview control will be GridView3. Set DataSource attribute of GridView3 control to bind to Cities property.
DataSource='<%# Bind("Cities") %>'

At this point the HTML of your webform should be as shown below.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
    <asp:BoundField DataField="ContinentId" HeaderText="ContinentId" />
    <asp:BoundField DataField="ContinentName" HeaderText="ContinentName" />
    <asp:TemplateField HeaderText="Countries">
        <ItemTemplate>
            <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" 
                DataSource='<%# Bind("Countries") %>'>
                <Columns>
                    <asp:BoundField DataField="CountryId" HeaderText="CountryId" />
                    <asp:BoundField DataField="CountryName" HeaderText="CountryName" />
                    <asp:BoundField DataField="ContinentId" HeaderText="ContinentId" />
                    <asp:TemplateField HeaderText="Cities">
                        <ItemTemplate>
                            <asp:GridView ID="GridView3" runat="server" 
                                DataSource='<%# Bind("Cities") %>'>
                            </asp:GridView>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </ItemTemplate>
    </asp:TemplateField>
</Columns>
</asp:GridView>

Step 9: Copy and paste the following code in Page_Load() event of WebForm1.aspx.cs
GridView1.DataSource = ContinentDataAccessLayer.GetAllContinents();
GridView1.DataBind();

4 comments:

  1. Nice I can see a lot of usage for this little trick with the gridview control. Thank you very much for this and all your videos so far, I'm enjoying the whole series :)

    ReplyDelete
  2. Hi Venkat, how do you implement the same thing but enabling selection on the inner gridviews (countries and cities) where you can edit, delete and add new rows?

    ReplyDelete
  3. Give me Some Solution about Json Object bind in gridview from Database
    Json is nesterd json

    ReplyDelete
  4. Sir how to create expandable gridview..

    ReplyDelete

It would be great if you can help share these free resources