domenica 3 ottobre 2021

C# Merge di righe nel controllo DatagridView, raggruppare righe

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.

Nessun commento: