Come faccio a creare una datagrid master detail????

venerdì 27 agosto 2004 - 13.55

l.corallini Profilo | Junior Member




ho un po' di problemi perchè non riesco a nidificare due datagrid per creare una tabella master detail.
dovrei riuscire a creare una prima datagrid (non saprei se va bene anche un datalist o un repeater...), poi per ogni item scatenare un evento che mi costruisca un'altra datagrid (o equivalente) prendendo come parametri quelli dell'item della prima datagrid.
ho provato creando una sub sull'evento OnItemCreated della datagrid master m non funziona, ho provato sull'evento OnItemDataBound e ancora non funziona...o meglio non riesco a recuperare i dati contenuti nella prima datagrid.
...
(vedere file allegato)
...
l'errore che mi da è il seguente:
System.NullReferenceException: Object reference not set to an instance of an object.


sono abbastanza disperato, mi sembra impossibile sia così complicato creare una struttura tabellare di tipo master detail

grazie

luca

Brainkiller Profilo | Guru

La strada che stai seguendo è quella ottimale.
Generalmente si entra nell'evento OnItemDataBound si recuperano i dati di riga o di colonna e si crea dinamicamente una nuova DataGrid che viene aggiunta alla cella corrente così ottieni un Datagrid master detail.
Ci sono anche controlli appositi più evoluti che ti permettono di fare la stessa cosa come spiegato qui:
http://www.dotnethell.it/articles/article.aspx?ArticleID=107

Per il tuo particolare problema, perchè usi una TemplateColumn invece di una semplice BoundColumn?

Io per accedere ai valori contenuti nelle celle uso e.Item.Cells[0].Text oppure in VB.NET e.Item.Cells(0).Text
Lo zero è l'indice della colonna.

ciao
david

l.corallini Profilo | Junior Member

ho creato delle boundcolumn come da te suggerito, mi dava sempre problemi sull'evento onitemdatabound...ho capito il motivo: l'evento non "capisce" che il primo item creato è quello dell'intestazione e quindi mi passava valori errati alla query per il dettaglio.
ora vedo cosa succedo avendo risolto questo problema mettendo un controllo sull'indice della datagrid...
grazie

luca

l.corallini Profilo | Junior Member

...ecco infatti un altro problema...
all'interno della sub chimata dall'evento OnItemDataBound creo la datagrid di dettaglio e poi la aggiungo con la seguente riga di codice:

e.Item.Controls.Add(dgTratte)

l'errore è il seguente:

'TableRow' cannot have children of type 'DataGrid'.

credo che sbaglo qualcosa nel posizionare la datagrid di dettaglio...

l.corallini Profilo | Junior Member

ho letto l'articolo 107 in cui si nidificano 2 datagrid, mi chiedo come si possa fare quanto spiegato li:

"...All’interno del Datagrid1, per il quale nell’esempio è stato abilitato il paging, si crea un secondo datagrid, DataGrid2, il cui codice HTML è:

Listato n°8

<asp:DataGrid id="DataGrid2" width="80%" runat="server" BorderColor="Black" AutoGenerateColumns="False " DataSource='<%# CType(Container.DataItem,DataRowView).CreateChildView("CustomerRelation") %>' backcolor="yellow">
<HeaderStyle font-bold="True " forecolor="White" backcolor="#CCCC99"></HeaderStyle>
<Columns>
<asp:BoundColumn DataField="campofiglio" HeaderText="Campi collegati"/>

..."

non mi sembra sia possibile inserire un datagrid all'interno di un altro.bho!

luca

l.corallini Profilo | Junior Member

qualcuno riesce a farmi capire (magari scrivendo due righe di codice...) come si fa ad inserire una datagrid all'interno di un'altra? riesocad intercettare l'evento OnItemDataBound e a recuperare i valori che mi servono per far la query successiva e riempire la seconda datagrid, ma nn riesco a crearla materialmente...grazie, sono abbastanza disperat, i ltempo passa e io non arrivo a capo a nulla seppur con le precise indicazioni di brainkiller...

luca

Brainkiller Profilo | Guru

Allora ti spiego a grandi linee.
Generalmente nell'OnItemDataBound metti istruzioni di questo tipo.
Te la scrivo in C# perchè faccio più in fretta.

if ((e.Item.ItemType==ListItemType.Item) || (e.Item.ItemType==ListItemType.AlternatingItem))
{
}

Quindi verifichi che la riga che sta creando sia una riga di dati e non header, footer o simili.
Una volta che sei qui dentro puoi fare una cosa di questo tipo:

e.Item.Cells[index].Controls.Add(dg)

allora index è l'indice della cella nella riga presa in esame.
controllo è un oggetto di tipo DataGrid che hai creato dinamicamente assegnandogli altri dati.
Per crerare dinamicamente una DataGrid puoi fare così:

DataGrid dg=new DataGrid();
dg.CellPadding=2;
dg.GridLines=GridLines.Horizontal;
dg.AutoGenerateColumns=false;
dg.Width=Unit.Percentage(100);

BoundColumn bd1=new BoundColumn();
bd1.DataField="level4";
bd1.ItemStyle.Font.Bold=true;
bd1.ItemStyle.HorizontalAlign=HorizontalAlign.Left;
bd1.ItemStyle.Width=50;
bd1.HeaderText="ID";
bd1.HeaderStyle.HorizontalAlign=HorizontalAlign.Left;
bd1.HeaderStyle.Font.Bold=true;
dg.Columns.Add(bd1);

dg.DataSource= .... assegni dei dati ...
dg.DataBind();

Così facendo vedrai in ogni cella un DataGrid collegato.

ciao
david

l.corallini Profilo | Junior Member

finalmente!
sono riuscito a creare la grid 'figlia' e a visualizzarla.
avrei bisogno di un ultim oconsiglio su come poter indentare la grid 'figlia' per dare alla tabella un aspetto più lineare.
infatti ho inserito la grid 'figlia' nella cella successiva a quella che visualizzo (della grid padre) per cui le grid 'figlie' che io vorrei far apparire al di sotto del record 'padre' mi appaiono allineate a destra di questo, e a video appare una tabella simile a questa:

record figlio1
record figlio1
record padre1 record figlio1
record figlio1

record figlio2
record figlio2
record padre2 record figlio2
record figlio2


posso fare invece qualcosa del genere?

record padre1
record figlio1
record figlio1
record figlio1
record figlio1
record padre2
record figlio2
record figlio2
record figlio2
record figlio2

se l'evento OnitemDataBound si scatena alla creazione di ogni singolo item non posso nenache pensare di aggiungere una riga 'vuota' ad ogni riga della grid 'padre' altrimenti penso che otterrei la duplicazione della grid 'figlia'.

grazie comunque per l'indispensabile suggerimento.

luca

l.corallini Profilo | Junior Member

mi sono accorto che nel post la rappresentazione non era ottimale...



______________record figlio1
______________record figlio1
record padre1 __record figlio1
______________record figlio1
______________record figlio1

______________record figlio2
______________record figlio2
record padre2 __record figlio2
______________record figlio2
______________record figlio2


posso fare invece qualcosa del genere?

record padre1
__record figlio1
__record figlio1
__record figlio1
__record figlio1
__record figlio1

record padre2
__record figlio2
__record figlio2
__record figlio2
__record figlio2
__record figlio2

grazie

luca

p.s.
devo inserire anche una TemplateColumn che contenga una checkBox, ho scritto:

Dim tc As TemplateColumn = New TemplateColumn
Dim CheckBox As CheckBox = New CheckBox
tc.EditItemTemplate.InstantiateIn(CheckBox)
dgTratte.Columns.Add(tc)

ma non funziona...

Brainkiller Profilo | Guru

Mh.. guarda il codice HTML creato.
Dovrebbe essere una <table> poi un bel <br> e poi un'altra <table> figlia.
Forse è per questo ?

Per le checkbox prova a crearle anche quelle a runtime dinamicamente.

ciao
david

l.corallini Profilo | Junior Member

avendo inserito la grid figlia dentro una specifica cella con lo script

e.Item.Cells[index].Controls.Add(dg)

la <table> me la costruisce all'interno del <td> della tabella padre che a questa corrisponde...

per quanto riguarda il controllo checkbox da inserire ina TemplateColumn della grid figlia ci ho provato senza riuscirvi.
ho letto su MSDN che bisogna implementare una classe che mi crea il template per poi poterlo usare...niente di più semplice.

' Visual Basic
Private Class MyTemplate
Implements ITemplate
Shared itemcount As Integer = 0
Dim TemplateType As ListItemType

Sub New(ByVal type As ListItemType)
TemplateType = type
End Sub

Sub InstantiateIn(ByVal container As Control) _
Implements ITemplate.InstantiateIn
Dim lc As New Literal()
Select Case TemplateType
Case ListItemType.Header
lc.Text = "<TABLE border=1><TR><TH>Items</TH></TR>"
Case ListItemType.Item
lc.Text = "<TR><TD>Item number: " & itemcount.ToString _
& "</TD></TR>"
Case ListItemType.AlternatingItem
lc.Text = "<TR><TD bgcolor=lightblue>Item number: " _
& itemcount.ToString & "</TD></TR>"
Case ListItemType.Footer
lc.Text = "</TABLE>"
End Select
container.Controls.Add(lc)
itemcount += 1
End Sub
End Class

...per utilizzarlo....

' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Repeater1.HeaderTemplate = New MyTemplate(ListItemType.Header)
Repeater1.ItemTemplate = New MyTemplate(ListItemType.Item)
Repeater1.AlternatingItemTemplate = _
New MyTemplate(ListItemType.AlternatingItem)
Repeater1.FooterTemplate = New MyTemplate(ListItemType.Footer)
SqlDataAdapter1.Fill(DsCategories1)
Repeater1.DataBind()
End Sub


è così quindi? devo seguire passo passo questo esempio?

grazie david

l.corallini Profilo | Junior Member

ho provato a risolvere il problema dell'allineamento delle due DataGrid ma senza successo...
come ho scritto nel precedente post la grid figlia la inserisce esattamente nella cella indicata, e lì viene inserita la <table>.

ho provato ad aggiungere dinamicamente una riga vuota alla grid padre pensando che sarei riuscito a fargli inserire la grid figlia li, ma non è stato così.
non riesco a gestire l'evento OnItemDataBound . se riempissi la riga ritornerei al punto di partenza, se la lascio vuota va in errore la sub chamata dall'evento OnItemDataBound ...bho! non saprei proprio, eppure sembrerebbe una cosa di poco conto...


Brainkiller Profilo | Guru

Non devi aggiungere una riga vuota (Row) ma proprio un <br>.
O forse non ho capito. Non puoi fare un disegnino che faccia vedere come vuoi la tua datagrid ?

Io ho capito che hai una datagrid padre con tante righe e in ogni riga vuoi inserire un'ulteriorie DataGrid.

E' così ?

ciao
david

l.corallini Profilo | Junior Member

come aggiungo un <br> e soprattutto dove?!

ti posto il codice che utilizzo per costruirmi la fantomatica grid master/detail


************ ******************Datagrid padre***********************************
<asp:datagrid id="Datagrid1" runat="server" Width="100%" Font-Size="Small" AutoGenerateColumns="False"
PageSize="1" OnItemDataBound="carica_lista" ShowHeader="false" ItemStyle-BorderStyle="NotSet"GridLines="None">
<Columns>
<asp:BoundColumn DataField="progstaini" Visible="false"></asp:BoundColumn>
<asp:BoundColumn DataField="progstafin" Visible="false"></asp:BoundColumn>
<asp:BoundColumn DataField="codstainisco" Visible="false"></asp:BoundColumn>
<asp:BoundColumn DataField="codstafinsco" Visible="false"></asp:BoundColumn>
<asp:BoundColumn ItemStyle-Font-Size="10pt" ItemStyle-Font-Names="Verdana" ItemStyle-Font-Bold="True"
ItemStyle-Wrap="False" ItemStyle-ForeColor="Firebrick" DataField="Tratta" Visible="true"></asp:BoundColumn>
<asp:BoundColumn ItemStyle-Font-Size="10pt" ItemStyle-Wrap="False" DataField="prova" Visible="true"></asp:BoundColumn>
</Columns>
</asp:datagrid>

**********************Aggiunta della grid 'figlia' dalla sub carica_lista*********************
e.Item.Cells(5).Controls.Add(dgTratte)

*************************HTML prodotto*****************************************
la Cells(5) corrisponde proprio al <td> in cui inserisce la tabella 'figlia'
<table id="Datagrid1">
<tr>
<td nowrap="nowrap">BRENNERO BRENNER - BOLZANO</td>
<td nowrap="nowrap">
<table rules="rows" id="Datagrid1__ctl2__ctl0">
<tr>
<td align="Left" >Titolo</td>
<td align="Left">Titolo 2</td>
<td align="Left">Titolo 3</td>
</tr
<tr>
<td align="Left" >milan</td>
<td align="Left" >1</td>
<td align="Left" >1</td>
</tr>
<tr>
<td align="Left" >paris</td>
<td align="Left" >1</td>
<td align="Left" >1</td>
</tr>
</table>
</td>
</tr>
</table>

p.s.
ti mando una mmagine che rende bene l'idea di come viene visualizzata la tabella...

ciao

Brainkiller Profilo | Guru

Ma sei un programmatore di Trenitalia.com ?

ciao
david

l.corallini Profilo | Junior Member

non proprio...TSF, lavoriamo per FS al 98%, una delle poche cose che non gli facciamo è proprio il sito trenitalia.com

ciao

Brainkiller Profilo | Guru

LOL infatti vedevo la pagina che hai mandato ci sono dei percorsi dei treni e poi i colori sono quelli classici di Trenitalia :)

ciao
david

Peephee Profilo | Newbie

Scusate se forse chiedo chiarimenti su qualcosa già spiegato ma non ho capito bene questa cosa.

Vorrei creare anch'io un datagrid dentro un datagrid ma solo ad un dato evento scatenato.
Vorrei creare un dettaglio della riga selezionata, che "esplode" dando le informazioni sotto forma di DataGrid figlio
Come posso fare?
(in C#)

All'evento del comando recupero i valori della data riga e elaboro il nuovo DataSet figlio per il DataGrid figlio da inserire sotto la riga padre.

private void EsplodiRiga(object sender,DataGridCommandEventArgs args)
{
if (args.CommandName == "EsplodiRiga")
{
string argomenti = args.CommandArgument.ToString();
string[] argomento = argomenti.Split('?');
string utente = argomento[0];
string regione = argomento[1];
CreaDataSetChild(utente,regione); //mi restituisce il DataSet da bindare
}
}

Come faccio ad inserire una nuova riga proprio sotto quella che ho cliccato?

E come inserisco il datagrid figlio dentro questa riga?
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5