ti mando un esempio completo, del tipo Regioni-Province.
Vi è un Gridview che lista le regioni. Una colonna contiene una iconcina. Cliccandoci sopra si espande e fa vedere le province per quella data regione.
Io avrei usato un repeater, ma quello che conta è il principio di funzionamento

codice:
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
        If Not Me.IsPostBack Then
            BindData()
        End If
    End Sub
    
    Private Sub BindData()

        Dim connessione As OleDbConnection = Nothing
        
        Try
            'creo e apro la connessione
            connessione = New OleDbConnection(StringaConnessioneTest)
            connessione.Open()
            
            'le due istruzioni sql, regioni, province
            Dim sql1 As String = "SELECT * FROM REGIONI ORDER BY NOME_REGIONE"
            Dim sql2 As String = "SELECT * FROM Q_PROVINCIE ORDER BY NOME_PROVINCIA"
            
            'creo il dataset
            Dim ds As New DataSet()
            
            'aggiungo la tabella regioni al dataset
            Dim dt As DataTable = libreria.GetDataTable(connessione, sql1)
            dt.TableName = "regioni"
            ds.Merge(dt.DataSet)

            
            'aggiungo la tabella province al dataset
            dt = libreria.GetDataTable(connessione, sql2)
            dt.TableName = "province"
            ds.Merge(dt.DataSet)
            
            'relazione che lega le due tabelle
            ds.Relations.Add("provincie_regioni", ds.Tables("regioni").Columns("codice_istat_regione"), ds.Tables("province").Columns("codice_istat_regione"))

            Me.GridViewParent.DataSource = ds.Tables("regioni")
            Me.GridViewParent.DataBind()
            
            
        Catch ex As Exception
            Me.Label1.Text = ex.Message()
        Finally
            If Not connessione Is Nothing Then connessione.Close()
        End Try
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Pagina senza titolo</title>
    <link href="../../../../stili/Styles.css" rel="stylesheet" type="text/css" />

    <script language="javascript" type="text/javascript">
// <!CDATA[
function dettagli(v)
{
	var img_id = v.id;
	var div_id = "div" + v.id.substr(3);
	var div = document.getElementById(div_id);
	if(div.style.display == "")
	{
		div.style.display = "none";
		v.src = "/ArchivioEsempi2/immagini/piu.gif";
	}
	else
	{
		div.style.display = "";
		v.src = "/ArchivioEsempi2/immagini/meno.gif";
	}
}


// ]]>
    </script>

</head>
<body>
    <form id="form1" runat="server">
        <h3>GridView dentro GridView con GetChildRows</h3>
        <asp:Label ID="Label1" runat="server" Text="" EnableViewState="false"></asp:Label>
        <div>
            <asp:GridView ID="GridViewParent" runat="server" EnableViewState="false" AutoGenerateColumns="false" BorderColor="#CC9966" BorderStyle="None" BorderWidth="1px" BackColor="White" CellPadding="4">
                <SelectedRowStyle Font-Bold="True" ForeColor="#663399" BackColor="#FFCC66"></SelectedRowStyle>
				<RowStyle ForeColor="#330099" BackColor="White"></RowStyle>
				<HeaderStyle Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"></HeaderStyle>
            
                <Columns>
                    <asp:BoundField HeaderText="Regione" DataField="nome_regione" ItemStyle-VerticalAlign="Top" />
                    <asp:TemplateField HeaderText="Province" >
                        <ItemTemplate>
                            [img]/ArchivioEsempi2/immagini/piu.gif[/img]' style="margin:0px;"/>
                            <div id='div_<%# DataBinder.Eval(Container.DataItem, "CODICE_ISTAT_REGIONE")%>' style="display:none;">
                                <asp:GridView ID="GridViewChild" runat="server" EnableViewState="false" AutoGenerateColumns="false" DataSource='<%#directcast(Container.DataItem, system.Data.DataRowView).Row.GetChildRows("provincie_regioni")%>' ShowHeader="false" BorderColor="#3366CC" BorderStyle="None" BorderWidth="1px" BackColor="White" CellPadding="4" style="width:100%;">
					                <SelectedRowStyle Font-Bold="True" ForeColor="#CCFF99" BackColor="#009999"></SelectedRowStyle>
					                <RowStyle ForeColor="#003399" BackColor="White"></RowStyle>
					                <HeaderStyle Font-Bold="True" ForeColor="#CCCCFF" BackColor="#003399"></HeaderStyle>

                                    <Columns>
                                        <asp:TemplateField>
                                            <ItemTemplate>
                                                <%#DirectCast(Container.DataItem, System.Data.DataRow)("NOME_PROVINCIA")%>
                                            </ItemTemplate>
                                        </asp:TemplateField>
                                        
                                    </Columns>
                                </asp:GridView> 
                            </div>                           
                        </ItemTemplate>
                        
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>

codice:
    '-------------------------------------------------------------------------------------
    'Restituisce un oggetto DataTable o lancia eccezione in caso di errore
    'parametri: connessione, stringa sql
    '-------------------------------------------------------------------------------------
    Public Function GetDataTable(ByVal Connessione As OleDbConnection, ByVal stringaSQL$) As DataTable

        Try
            'creo un nuovo DataAdapter
            Dim DataAdapter As New OleDbDataAdapter(stringaSQL, Connessione)

            'creo un DataSet e lo riempio con i dati
            Dim DataSet As New DataSet
            DataAdapter.FillSchema(DataSet, SchemaType.Source)
            DataAdapter.Fill(DataSet, "sql")

            Return DataSet.Tables("sql")

        Catch Errore As Exception
            Throw
            Return Nothing
        End Try


    End Function

ps. ci sono altri modi: quello che preferisco è non usare il gridview e compormi la tabella da codice, con stringbuilder.