venerdì 1 ottobre 2010

GridView con panel di espansione

Si riporta l'articolo scritto per il sito http://www.iprogrammatori.it/articoli/programmazione/art_aspnet-creazione-di-un-gridview-con-un-p_970.aspx


Introduzione
In questo articolo, vedremo come applicare ad un controllo GridView di Asp.Net 4 un pannello di espansione, che visualizza altre informazioni per una determinata riga della griglia, il tutto come mostrato in figura 1.





Figura 1


Ogni riga della griglia, ha un immagine, che al click (sul simbolo piu) permette di visualizzare un pannello composto da controlli label, informazioni su quel determinato record.
Per ogni riga avremmo diversi dati, in riferimenti al codice id di quel record.
Supponendo di avere una tabella anagrafica, nella quale si trova un campo IdPersona, un campo nome ed un campo Cognome, in relazione ad un’altra tabella denominata Dettaglio persona con un campo nome ed un campo codice, oltre al campo id chiave e idpersona, della tabella anagrafica. In questo modo avremmo una relazione di tabelle, che possiamo applicare nella griglia.
Nel nostro articolo, utilizzeremo le classi, ma tale esempio si può utilizzare benissimo anche con fonti dati provenienti da un databse.


Creazione delle classi.
Si crea una classe di nome Persona e una di tipo DettaglioPersona. Nella classe presona, si creano tre proprietà una di tipo intero (IdPersona) e due di tipo stirnga (nome e cognome) il tutto come riportato in nel codice qui sottostante.


VB.Net


Public Class Persona


Public Property IDPersona As Int32


Public Property Nome As String


Public Property Cognome As String


End Class



C#


public class Persona


{


public Int32 IDPersona { get; set; }


public string Cognome { get; set; }


public string Nome { get; set; }


}



Mentre nella classe Dettaglio persona si crea una proprietà di tipo intero, denominata IdPersona, a cui sarà relazionata la classe Persona, due proprietà di tipo stringa, denominate rispettivamente Citta e Codice.
Qui di seguito si riporta il codice delle suddette dichiarazioni.


VB.Net


Public Class DettaglioPersona


Public Property IDPersona As Int32


Public Property Citta As String


Public Property Codice As String


End Class



C#


public class DettaglioPersona


{


public Int32 IDPersona { get; set; }


public string Citta { get; set; }


public string codice { get; set; }


}


}




Creazione della pagina ASPX.
Passiamo in visualizzazione html per quanto riguarda la pagina ASPX, la funzione Espandi, permette di cambiare l’immagine di espansione e visualizzare o nascondere il panello, le immagini, sono state aggiunte al progetto.
Qui di seguito si riporta la funzione completa Javascript, che intercetta il pulsante e cambia l’immagine.



<script language="javascript" type="text/javascript">




function espandi(obj, row) {




var div = document.getElementById(obj);




var img = document.getElementById('img' + obj);




if (div != null) {




if (div.style.display == "none") {


div.style.display = "block";



if (row == 'alt') {


img.src = "/meno.gif";


}




else {


img.src = "meno.gif";


}


img.alt = "Clicca per nascondere";


}




else {


div.style.display = "none";




if (row == 'alt') {


img.src = "/piu.gif";


}




else {


img.src = "/piu.gif";


}


img.alt = "Clicca per aprire";


}


}


}




</script>



Aggiungiamo nella pagina web, un controllo gridView, impostiamo l’evento OnRowDataBound, in modo che in tale evento, intercettiamo il singolo record ed aggiungiamo il pannello.
Si aggiungono quattro colonne, di tipo templateField, nella prima, impostiamo il codice per la visualizzazione delle immagini (visualizzare (meno) e nascondere (piu) ) e il relativo cambio. Due colonne contenenti il valore delle proprietà Nome e Cognome, ed una colonna in cui si crea una tabella html (table) contenente un controllo di tipo panel, due controlli di tipo table lato server ed un controllo di tipo label.


Qui di seguito si riporta il codice completo html del controllo gridview


<asp:GridView ID="GrvAnagrafica" runat="server" AutoGenerateColumns="False" DataKeyNames="IDPersona"


OnRowDataBound="GrvAnagrafica_RowDataBound" CellPadding="4" ForeColor="#333333"


GridLines="None">


<AlternatingRowStyle BackColor="White" ForeColor="#284775" />


<Columns>


<asp:TemplateField>


<ItemTemplate>


<a href="javascript:espandi('div<%# Eval("IDPersona") %>', 'one');">


<img id="imgdiv<%# Eval("IDPersona") %>" alt="Dettaglio informazioni" src="/piu.gif" />


</a>


</ItemTemplate>


</asp:TemplateField>


<asp:TemplateField HeaderText="Nome" SortExpression="Nome ">


<ItemTemplate>


<asp:Label ID="lblNome" runat="server" Text='<%# Bind("Nome") %>'></asp:Label></ItemTemplate>


<HeaderStyle HorizontalAlign="Left" />


</asp:TemplateField>


<asp:TemplateField HeaderText="Cognome" SortExpression="Cognome">


<ItemTemplate>


<asp:Label ID="lblCognome" runat="server" Text='<%# Bind("Cognome") %>'></asp:Label></ItemTemplate>


<ItemStyle HorizontalAlign="Center" />


</asp:TemplateField>


<asp:TemplateField>


<ItemTemplate>


<tr>


<td colspan="100%">


<div id="div<%# Eval("IDPersona") %>">


<asp:Panel runat="server" ID="pnlSchedaDettaglio">


<table id="Table1" runat="server">


<tr>


<td colspan="70">


<asp:Label ID="Label1" runat="server" Text="Dettaglio Persona" Font-Bold="true" ForeColor="Red"></asp:Label>


</td>


</tr>


</table>


<asp:Table ID="tblSchedaDettaglio" runat="server">


</asp:Table>


</asp:Panel>


</div>


</td>


</tr>


</ItemTemplate>


</asp:TemplateField>


<asp:CommandField ShowEditButton="False" SelectText="Modifica" />


<asp:CommandField ShowDeleteButton="False" />


</Columns>


<EditRowStyle BackColor="#999999" />


<FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />


<HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />


<PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />


<RowStyle BackColor="#F7F6F3" ForeColor="#333333" />


<SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />


<SortedAscendingCellStyle BackColor="#E9E7E2" />


<SortedAscendingHeaderStyle BackColor="#506C8C" />


<SortedDescendingCellStyle BackColor="#FFFDF8" />


<SortedDescendingHeaderStyle BackColor="#6F8DAE" />


</asp:GridView>



Il controllo table, visualizzerà i titoli e le varie righe, che andremmo a caricare dinamicamente, mentre il controllo label, le varie informazioni.


Stesura di codice
Ora passiamo in visualizzazione codice.
Si creano due funzioni, una che permetterà di valorizzare la griglia, e l’altra di visualizzare il dettaglio della singola riga.
Qui di seguito si riporta un esempio di codice delle due funzioni.


VB.Net


Private Function CaricaDati() As List(Of Persona)


'carico 2 dati di tipo persona


Dim persone As New List(Of Persona)


Dim pers As New Persona()


pers.Cognome = "Mattei"


pers.Nome = "Emanuele"


pers.IDPersona = 1


persone.Add(pers)


pers = New Persona()


pers.Cognome = "Mattei2"


pers.Nome = "Emanuele2"


pers.IDPersona = 2


persone.Add(pers)


Return persone


End Function





Private Function CaricaDettaglioPersona() As List(Of DettaglioPersona)


Dim dettPersone As New List(Of DettaglioPersona)


Dim DettPersona As New DettaglioPersona()


DettPersona.Citta = "Roma"


DettPersona.Codice = "AA"


DettPersona.IDPersona = 1


dettPersone.Add(DettPersona)


DettPersona = New DettaglioPersona()


DettPersona.Citta = "Firenze"


DettPersona.Codice = "BB"


DettPersona.IDPersona = 1


dettPersone.Add(DettPersona)


DettPersona = New DettaglioPersona()


DettPersona.Citta = "Calabria"


DettPersona.Codice = "CC"


DettPersona.IDPersona = 2


dettPersone.Add(DettPersona)


Return dettPersone



End Function




C#


private List<Persona> CaricaDati()


{


//carico 2 dati di persona


List<Persona> persone = new List<Persona>();


Persona pers = new Persona();


pers.Cognome = "Mattei";


pers.Nome = "Emanuele";


pers.IDPersona = 1;


persone.Add(pers);


pers = new Persona();


pers.Cognome = "Mattei2";


pers.Nome = "Emanuele2";


pers.IDPersona = 2;


persone.Add(pers);



return persone;



}




private List<DettaglioPersona> CaricaDettaglioPersona()


{


List<DettaglioPersona> dettPersone = new List<DettaglioPersona>();


DettaglioPersona dettPersona = new DettaglioPersona();


dettPersona.Citta = "Roma";


dettPersona.codice = "AA";


dettPersona.IDPersona = 1;


dettPersone.Add(dettPersona);


dettPersona = new DettaglioPersona();


dettPersona.Citta = "Firenze";


dettPersona.codice = "BB";


dettPersona.IDPersona = 1;


dettPersone.Add(dettPersona);


dettPersona = new DettaglioPersona();


dettPersona.Citta = "Calabria";


dettPersona.codice = "CC";


dettPersona.IDPersona = 2;


dettPersone.Add(dettPersona);


return dettPersone;



}



Nell’evento load, valorizziamo la nostra riga, utilizzando la funzione CaricaPersona.
Qui di seguito si riporta il codice per l’evento load della form.


VB.Net


Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


Dim ListPersona As List(Of Persona) = CaricaDati()



GrvAnagrafica.DataSource = ListPersona


GrvAnagrafica.DataBind()


End Sub



C#


protected void Page_Load(object sender, EventArgs e)


{


List<Persona> listPersona = CaricaDati();



GrvAnagrafica.DataSource = listPersona;


GrvAnagrafica.DataBind();



}



Terminata questa parte, si passa all’evento rowDataBound, in cui andremmo ad intercettare la creazione della singola riga, ed eseguire una query Linq, per relazionare le due classi, e caricare dinamicamente il pannello
Qui di seguito si riporta il codice delle suddette operazioni.


VB.Net


Protected Sub GrvAnagrafica_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GrvAnagrafica.RowDataBound


If e.Row.RowType = DataControlRowType.DataRow Then


'Rilevo la tabella delle schede reati



Dim pnlSchedaDettaglio As Panel = e.Row.FindControl("pnlSchedaDettaglio")


Dim tblSchedaDettaglio As Table = pnlSchedaDettaglio.FindControl("tblSchedaDettaglio")


Dim valore As Int32 = CType(e.Row.DataItem, Persona).IDPersona


Dim ListDetPersona As List(Of DettaglioPersona) = CaricaDettaglioPersona()


Dim DettPersona = From pers In ListDetPersona


Where pers.IDPersona = valore


Select pers




tblSchedaDettaglio.Width = New Unit("100%")



'creo la riga


Dim trRiga As New TableRow()


tblSchedaDettaglio.Rows.Add(trRiga)


'colonna Città - imposta i dati


Dim TdColCitta As New TableCell()


TdColCitta.Width = New Unit("15%")


TdColCitta.Text = ""


trRiga.Cells.Add(TdColCitta)


'colonna Codice - imposta i dati


Dim TdColCodice As New TableCell()


TdColCodice.Width = New Unit("85%")


TdColCodice.Text = ""


trRiga.Cells.Add(TdColCodice)


Dim ContaElementi As Int16 = 0


For Each elemento In DettPersona



trRiga = New TableRow()


tblSchedaDettaglio.Rows.Add(trRiga)


'colonna Città - imposta i dati


TdColCitta = New TableCell()


TdColCitta.Width = New Unit("15%")


TdColCitta.Text = ""


trRiga.Cells.Add(TdColCitta)


'colonna Codice - imposta i dati


TdColCodice = New TableCell()


TdColCodice.Width = New Unit("85%")


TdColCodice.Text = ""


trRiga.Cells.Add(TdColCodice)


tblSchedaDettaglio.Rows(ContaElementi + 1).Cells(0).Text = elemento.Citta


tblSchedaDettaglio.Rows(ContaElementi + 1).Cells(1).Text = elemento.Codice


ContaElementi += 1




Next




End If


End Sub




C#


if (e.Row.RowType == DataControlRowType.DataRow)


{


//Rilevo la tabella delle schede reati


Panel pnlSchedaDettaglio = e.Row.FindControl("pnlSchedaDettaglio") as Panel;


Table tblSchedaDettaglio = pnlSchedaDettaglio.FindControl("tblSchedaDettaglio") as Table;





Int32 valore = ((Persona)e.Row.DataItem).IDPersona;


List<DettaglioPersona> ListDetPersona = CaricaDettaglioPersona();


var DettPersona = from pers in ListDetPersona


where pers.IDPersona == valore


select pers;








tblSchedaDettaglio.Width = new Unit("100%");



//creo la riga


TableRow trRiga = new TableRow();


tblSchedaDettaglio.Rows.Add(trRiga);


//colonna Città - imposta i dati


TableCell TdColCitta = new TableCell();


TdColCitta.Width = new Unit("15%");


TdColCitta.Text = "";


trRiga.Cells.Add(TdColCitta);


//colonna Codice - imposta i dati


TableCell TdColCodice = new TableCell();


TdColCodice.Width = new Unit("85%");


TdColCodice.Text = "";


trRiga.Cells.Add(TdColCodice);


//}





//Creo le colonne dei titoli


Label lblEtichettaCitta = new Label();


lblEtichettaCitta.Text = "Città";


lblEtichettaCitta.ID = "lblCitta";


tblSchedaDettaglio.Rows[0].Cells[0].Controls.Add(lblEtichettaCitta);


Label lblEtichettaTipoReato = new Label();


lblEtichettaTipoReato.Text = "Codice";


lblEtichettaTipoReato.ID = "lblCodice";


tblSchedaDettaglio.Rows[0].Cells[1].Controls.Add(lblEtichettaTipoReato);



Int16 ContaElementi = 0;


foreach (var elemento in DettPersona)


{


trRiga = new TableRow();


tblSchedaDettaglio.Rows.Add(trRiga);


//colonna Città - imposta i dati


TdColCitta = new TableCell();


TdColCitta.Width = new Unit("15%");


TdColCitta.Text = "";


trRiga.Cells.Add(TdColCitta);


//colonna Codice - imposta i dati


TdColCodice = new TableCell();


TdColCodice.Width = new Unit("85%");


TdColCodice.Text = "";


trRiga.Cells.Add(TdColCodice);


tblSchedaDettaglio.Rows[ContaElementi + 1].Cells[0].Text = elemento.Citta;


tblSchedaDettaglio.Rows[ContaElementi + 1].Cells[1].Text = elemento.codice;


ContaElementi += 1;


}



//}



}



}




Come si vede dal codice precedente, dopo aver rilevare l’oggetto panel, situato nella colonna della griglia, si crea un istanza della tabella contenuta al suo interno, in questo modo si crea una tabella, contenente i vari campi (titoli e valori)


Conclusioni
L’articolo ha voluto illustrare al lettore le basi per la creazione di una gridview con un pannello che integri le informazioni per ogni singola riga. Nell’esempio è stato utilizzato un controllo di tipo Label, ma nulla vieta che si possa inserire un controllo di tipo combobox, calendar, o altro.

Nessun commento: