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 :
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.
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.



17:19
MarcoGG



Posted in: 





