Si riporta l'articolo scritto per il sito https://www.iprogrammatori.it/articoli/microsoft-net-framework/art_c-merge-di-righe-nel-controllo-datagridview-raggruppare-righe_1755.aspx
In questo articolo vedremo come applicare in un controllo di tipo DatagridView in ambito Windows Application, tramite il linguaggio di programmazione C#, il merge tra più righe con un valore uguale.
Nel caso che si vuole realizzare un’applicazione per la gestione dei dati, e visualizzarli raggruppandoli per categoria, avremo una categoria con un valore e poi nelle colonne a seguire i vari dati per ogni cella di riga.
Il merge, o meglio raggruppamento è un modo di rappresentare i dati su specifiche esigenze.
In questo articolo vedremo come tramite Windows Application e con Visual Studio 2019 versione del Framework 5, che è l’ultima appena rilasciata con cui scriviamo l’articolo, fornire una particolare visualizzazione dei dati, il tutto come mostrato in figura 1.
Figura 1 – la visualizzazione dei dati
Creazione del progetto
Si crea un nuovo progetto, di tipo Windows Application, selezionando come linguaggio di programmazione C# e il modello tipo App Forms, selezionando la versione del Framework 5.0. Dopo aver creato il progetto, aggiungere un controllo DatagridView, impostando la proprietà “Name” con il valore “DtgDati” e la proprietà “Dock” su “Top”, in questo modo il controllo verrà posizionato in alto, come nella figura 1.
Stesura del codice
Terminata la realizzazione della form, dobbiamo creare una classe denominata “DataGridViewMergedColumn” che permette di impostare uno stile alle varie celle di una determinata riga.
In particolare la classe sarà il modello di colonna, che tramite il metodo “IsValoreRipetuto” della sottoclasse “DataGridViewMergedTextBoxCell” permetterà di capire se il valore precedente è uguale a quello procedente oppure no, in caso affermativo la cella sarà unita.
Nella classe inoltre vengono sovrascritti (“override”) gli eventi “GetFormattedValue” e “Paint” per fornire lo stile a noi desiderato.
Dopo aver creato la classe denominata “” dobbiamo inserire lo spazio dei nomi per gestire la ereditarie alle classe per la gestione delle colonne e celle del controllo DatagridView.
Qui di seguito gli spazio dei nomi delle suddette operazioni.
C#
using System.Windows.Forms;
using
System.ComponentModel;
using
System.Drawing;
Terminato l’inserimento dello spazio dei nomi, non resta che scrivere gli eventi e la sottoclasse per la gestione delle colonne e celle.
Qui di seguito il frammento di codice della classe “DataGridViewMergedColumn” delle suddette operazioni.
C#
public class
DataGridViewMergedColumn : DataGridViewTextBoxColumn
{
public DataGridViewMergedColumn()
{
CellTemplate = new DataGridViewMergedTextBoxCell();
}
private class
DataGridViewMergedTextBoxCell : DataGridViewTextBoxCell
{
private bool
IsValoreRipetuto(int IndiceRiga, int IndiceColonna)
{
if
(IndiceRiga == 0)
return
false;
DataGridViewCell
CellaCorrente = this.DataGridView.Rows[IndiceRiga].Cells[IndiceColonna];
DataGridViewCell
CellaPrecedente = this.DataGridView.Rows[IndiceRiga - 1].Cells[IndiceColonna];
return
Object.Equals(CellaCorrente.Value, CellaPrecedente.Value);
}
protected
override object GetFormattedValue(object Valore, int IndiceRiga, ref
DataGridViewCellStyle StileCella, TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts
context)
{
if
((IndiceRiga > 0) && IsValoreRipetuto(IndiceRiga, this.ColumnIndex))
return
string.Empty;
else
return
base.GetFormattedValue(Valore, IndiceRiga, ref StileCella, valueTypeConverter,
formattedValueTypeConverter, context);
}
protected
override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle
cellBounds, int rowIndex, DataGridViewElementStates cellState, object value,
object formattedValue, string errorText, DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts
paintParts)
{
if
(rowIndex < this.DataGridView.Rows.Count - 1)
{
if
(IsValoreRipetuto(rowIndex + 1, this.ColumnIndex))
{
advancedBorderStyle.Bottom
= DataGridViewAdvancedCellBorderStyle.None;
}
}
base.Paint(graphics,
clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText,
cellStyle, advancedBorderStyle, paintParts);
}
}
}
Terminata la scrittura della classe ompiliamo per vedere se tutto funzionare correttamente e facciamo doppio click sulla form, in modo che passiamo in visualizzazione grafica.
Facciamo doppio click in un punto qualunque della form in modo che passiamo in visualizzazione codice, e precisamente nell’evento load della form.
Si crea un metodo che simulerà un caricamento dei dati, con un datatable, avente tre colonne, denominata, categoria, descrizione e quantità. La colonna “Categoria”, sarà quella considerata per raggruppare le righe. Al termine del caricamento del controllo DatagridView, eliminiamo la colonna “Categoria” per aggiungere quella personalizzata, utilizzando la classe creata in precedenza denominata “DataGridViewMergedColumn”.
Qui di seguito il frammento di codice delle suddette operazioni, relativo alla creazione del datatable con i dati e la personalizzazione della colonna.
C#
private void
CaricaDati()
{
DataTable Dati = new DataTable();
DataColumn Categoria = new
DataColumn("Categoria");
DataColumn Descrizione = new
DataColumn("Descrizione");
DataColumn Quantita = new
DataColumn("Quantita");
Dati.Columns.Add(Categoria);
Dati.Columns.Add(Descrizione);
Dati.Columns.Add(Quantita);
DataRow riga = Dati.NewRow();
riga["Categoria"] =
"Hardware";
riga["Descrizione"] =
"SSD";
riga["Quantita"] =
"10 pezzi";
Dati.Rows.Add(riga);
riga = Dati.NewRow();
riga["Categoria"] =
"Hardware";
riga["Descrizione"] =
"RAM";
riga["Quantita"] =
"3 pezzi";
Dati.Rows.Add(riga);
riga = Dati.NewRow();
riga["Categoria"] =
"Hardware";
riga["Descrizione"] =
"Monitor";
riga["Quantita"] = "30
pezzi";
Dati.Rows.Add(riga);
riga = Dati.NewRow();
riga["Categoria"] =
"Hardware";
riga["Descrizione"] =
"Schede madri";
riga["Quantita"] =
"8 pezzi";
Dati.Rows.Add(riga);
riga = Dati.NewRow();
riga["Categoria"] =
"Software";
riga["Descrizione"] =
"Microsoft Office";
riga["Quantita"] =
"8 pezzi";
Dati.Rows.Add(riga);
riga = Dati.NewRow();
riga["Categoria"] =
"Software";
riga["Descrizione"] =
"Microsoft Windows";
riga["Quantita"] =
"23 pezzi";
Dati.Rows.Add(riga);
DtgDati.DataSource = Dati;
DataGridViewMergedColumn ColonnaMerge = new
DataGridViewMergedColumn();
string NomeColonna =
"Categoria";
ColonnaMerge.HeaderText =
NomeColonna;
ColonnaMerge.Name = NomeColonna;
ColonnaMerge.DataPropertyName =
NomeColonna;
int colidx =
DtgDati.Columns[NomeColonna].Index;
DtgDati.Columns.Remove(NomeColonna);
DtgDati.Columns.Insert(colidx,
ColonnaMerge);
}
Come si è visto nel precedente codice, nella parte finale del codice, si crea la colonna personalizzata e si imposta il nome e fonte dati della colonna relativo alla classe per effettuare il merge delle righe, creata in precedenza, rimuovendo la colonna utilizzata all’inizio per il caricamento dei dati.
Ora non resta che richiamare questo metodo nell’evento load della form, ed eseguire il nostro applicativo.
Nell’evento load della form, richiamiamo il caricamento dei dati nel seguente modo.
C#
private void
Form1_Load(object sender, EventArgs e)
{
CaricaDati();
}
Conclusioni
L’articolo ha voluto fornire al lettore la possibilità di estendere alcune funzionalità di un controllo DatagridView, con aspetti grafici che possono tornare utile nello sviluppo di applicazioni gestionali in questo caso raggruppando le righe.
Le potenzialità offerte dal controllo DataGridView, sono numerose ed è un modo semplice di estendere il controllo rendendo piacevole lo sviluppo di applicazioni con questo controllo.
Il codice si può utilizzare anche con ambienti di sviluppo precedenti alla 2019 e versioni precedenti di Framework.