domenica 26 febbraio 2012

[C#] DataGridView e MultiSelezioni

Descrizione :
Una mia tecnica per gestire la Multi-Selezione utente su DataGridView.

+ Articolo :

Spesso nei Forum Tecnici capita di leggere richieste sull'utilizzo avanzato del Controllo DataGridView, sempre molto utile e adatto alla rappresentazione di dati in svariate situazioni.
In questo Articolo penso di dare una risposta pratica e abbastanza completa sul problema di riuscire a selezionare con il Mouse, ma non solo ( la tecnica seguente tiene conto anche della selezione via tastiera e via codice... ) i dati presenti in un DataGridView connesso ad un DataTable, mantenendo tale selezione attiva.
Non sono quindi necessarie colonne CheckBox aggiuntive nè combinazioni di tasti ( niente CTRL ) per eseguire le selezioni e inoltre le Righe o Celle selezionate vengono automaticamente raccolte in opportune List() di riferimento che rimangono sempre aggiornate e pronte al prelievo dei dati.

Per replicare l'esempio seguente basta predisporre la solita Application Windows Forms con una Form "FormMain".
Su FormMain servono 4 controlli. Nell'ordine da sinistra a destra sono :
--> DataGridView : DGV1.
--> ListBox : lst_dgv1.
--> DataGridView : DGV2.
--> ListBox : lst_dgv2.

- DGV1 rappresenta i dati del proprio DataSource ( DT1 ), e mostra la tecnica sulla selezione delle Rows.
Le Rows selezionate e raccolte nella propria List() "selectedRows", sono mostrate nella lst_dgv1.
- Analogamente, DGV2 rappresenta i dati del proprio DataSource ( DT2 ), e mostra la tecnica sulla selezione delle Cells.
Le Cells selezionate e raccolte nella propria List() "selectedCells", sono mostrate nella lst_dgv2.
Perciò le due ListBox qui hanno scopo di verifica costante e visibile di quanto avviene dietro le quinte.

Non occorre impostare alcuna proprietà dei controlli a design, in quanto tutto viene definito al Load().

La figura seguente mostra un esempio di utilizzo a runtime :


--> Codice FormMain :

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace DGVMultiSelect
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

        //DataTable per DGV1
        private DataTable DT1 = new DataTable();
        //DataTable per DGV1
        private DataTable DT2 = new DataTable();
        //SelectedIndices per Rows su DGV1
        private List<DataGridViewRow> selectedRows = new List<DataGridViewRow>();
        //SelectedCells per Cells su DGV2
        private List<DataGridViewCell> selectedCells = new List<DataGridViewCell>();

        private void FormMain_Load(object sender, EventArgs e)
        {
            //Impostazioni DGV1 - Dimostrazione con Rows
            DGV1.MultiSelect = true;
            DGV1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            DGV1.DefaultCellStyle.SelectionBackColor = Color.Red;
            DGV1.DefaultCellStyle.Font = new Font(System.Drawing.FontFamily.GenericSansSerif, 12);
            DGV1.ReadOnly = false;
            DGV1.AllowUserToAddRows = false;
            DGV1.AllowUserToDeleteRows = true;
            DGV1.DataSource = DT1;

            //Impostazioni DGV2 - Dimostrazione con Celle
            DGV2.MultiSelect = true;
            DGV2.SelectionMode = DataGridViewSelectionMode.CellSelect;
            DGV2.DefaultCellStyle.SelectionBackColor = Color.Green;
            DGV2.DefaultCellStyle.Font = new Font(System.Drawing.FontFamily.GenericSansSerif, 12);
            DGV2.ReadOnly = false;
            DGV2.AllowUserToAddRows = false;
            DGV2.AllowUserToDeleteRows = true;
            DGV2.DataSource = DT2;

            //DataTable per DGV1
            //Colonna PK
            DT1.Columns.Add("ID");
            DT1.PrimaryKey = new DataColumn[] {DT1.Columns["ID"]};
            //Altre Colonne
            for (int i = 1; i <= 9; i++)
            {
                DT1.Columns.Add("Colonna_" + i.ToString().PadLeft(2, '0'));
            }
            //...
            //Inserimento Rows
            DataRow R = null;
            for (int i = 0; i <= 9; i++)
            {
                R = DT1.NewRow();
                R[0] = i;
                for (int j = 1; j < DT1.Columns.Count; j++)
                {
                    R[j] = "Cella_" + j;
                }
                DT1.Rows.Add(R);
            }

            //DataTable per DGV2
            //Colonna PK
            DT2.Columns.Add("ID");
            DT2.PrimaryKey = new DataColumn[] {DT2.Columns["ID"]};
              //Altre Colonne
            for (int i = 1; i <= 9; i++)
            {
                DT2.Columns.Add("Colonna_" + i.ToString().PadLeft(2, '0'));
            }
            //...
            //Inserimento Rows
            for (int i = 0; i <= 9; i++)
            {
                R = DT2.NewRow();
                R[0] = i;
                for (int j = 1; j < DT2.Columns.Count; j++)
                {
                    R[j] = "Cella_" + j;
                }
                DT2.Rows.Add(R);
            }
        }

        private void CheckCurrentDgv1()
        {
            if (DGV1.CurrentRow == null)
            {
                return;
            }
            if (selectedRows.Contains(DGV1.CurrentRow))
            {
                selectedRows.Remove(DGV1.CurrentRow);
            }
            else
            {
                selectedRows.Add(DGV1.CurrentRow);
            }
            SelezioneDgv1();
        }

        private void SelezioneDgv1()
        {
            foreach (DataGridViewRow dgvr in DGV1.Rows)
            {
                if (selectedRows.Contains(dgvr))
                {
                    dgvr.Selected = true;
                }
                else
                {
                    dgvr.Selected = false;
                }
            }
            lst_dgv1.Items.Clear();
            lst_dgv1.Items.AddRange(selectedRows.ToArray());
        }

        private void DGV1_CurrentCellChanged(object sender, EventArgs e)
        {
            CheckCurrentDgv1();
        }

        private void DGV1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            SelezioneDgv1();
        }

        private void DGV1_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            if (selectedRows.Contains(e.Row))
            {
                selectedRows.Remove(e.Row);
            }
            SelezioneDgv1();
        }

        private void DGV1_DoubleClick(object sender, EventArgs e)
        {
            CheckCurrentDgv1();
        }

        private void CheckCurrentDgv2()
        {
            if (DGV2.CurrentCell == null)
            {
                return;
            }
            if (selectedCells.Contains(DGV2.CurrentCell))
            {
                selectedCells.Remove(DGV2.CurrentCell);
            }
            else
            {
                selectedCells.Add(DGV2.CurrentCell);
            }
            SelezioneDgv2();
        }

        private void SelezioneDgv2()
        {
            foreach (DataGridViewRow dgvr in DGV2.Rows)
            {
                foreach (DataGridViewCell dgvc in dgvr.Cells)
                {
                    if (selectedCells.Contains(dgvc))
                    {
                        dgvc.Selected = true;
                    }
                    else
                    {
                        dgvc.Selected = false;
                    }
                }
            }
            lst_dgv2.Items.Clear();
            lst_dgv2.Items.AddRange(selectedCells.ToArray());
        }

        private void DGV2_CurrentCellChanged(object sender, EventArgs e)
        {
            CheckCurrentDgv2();
        }

        private void DGV2_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            SelezioneDgv2();
        }

        private void DGV2_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            foreach (DataGridViewCell dgvc in e.Row.Cells)
            {
                if (selectedCells.Contains(dgvc))
                {
                    selectedCells.Remove(dgvc);
                }
            }
            SelezioneDgv2();
        }

        private void DGV2_DoubleClick(object sender, EventArgs e)
        {
            CheckCurrentDgv2();
        }


    }
}

Per quanto riguarda la parte Dati il codice è già ben commentato.
Con un paio di semplici Metodi scritti ad hoc e 4 Eventi ( comunque molto compatti ), il gioco è fatto.
Come si può notare, la tecnica tiene conto anche dell'eventuale eliminazione di Righe da parte dell'utente.
Inoltre L'Edit di Cella funziona in ogni caso, con Riga o Cella selezionata e non, e come è possibile notare ...


... non reca disturbi sulle pregresse selezioni.

Ovviamente il passo successivo ( che lascio ai lettori ) sarà quello di crearsi una propria Classe che eredita da DataGridView, e che conterrà questi ed altri Metodi ed Eventi, a seconda delle esigenze.

+ Fine Articolo.

Un Click su "Mi Piace" è il modo migliore per ringraziare l'autore di questo articolo.



0 commenti:

Posta un commento

 
Design by Free WordPress Themes Modificato da MarcoGG