c# - seleccionar - La tabla enlazada de DataGridView solo genera un evento RowChanged con un doble clic. ¿Cómo hago para que haga dos?
seleccionar row datagridview c# (7)
Tengo un DataGridView cuyo DataSource es una DataTable. Esta DataTable tiene una columna booleana, que se interpreta como una casilla de verificación en DataGridView.
employeeSelectionTable.Columns.Add("IsSelected", typeof(bool));
...
employeeSelectionTable.RowChanged += selectionTableRowChanged;
dataGridViewSelectedEmployees.DataSource = employeeSelectionTable;
...
private void selectionTableRowChanged(object sender, DataRowChangeEventArgs e)
{
if ((bool)e.Row["IsSelected"])
{
Console.Writeline("Is Selected");
}
else
{
Console.Writeline("Is Not Selected");
}
break;
}
Cuando el usuario hace un clic en una casilla de verificación, se comprueba y selectionTableRowChanged mostrará "Se seleccionó".
De forma similar, cuando el usuario lo revisa nuevamente, la casilla se borra y las salidas selectTableRowChanged "No se selecciona".
Aquí es donde tengo el problema:
Cuando el usuario hace doble clic en la casilla de verificación, se marca la casilla de verificación, se llama al evento RowChanged ("Está Seleccionado"), y luego se borra la casilla de verificación, y no se llama a ningún evento RowChanged correspondiente. Ahora el suscriptor del evento RowChanged no está sincronizado.
Mi solución en este momento es crear una subclase de DataGridView y reemplazar WndProc para comer WM_LBUTTONDBLCLICK, por lo que cualquier doble clic en el control se ignora. ¿Hay una mejor solución?
¿Hay alguna razón por la cual deba hacerse ese nivel bajo? ¿Puede el método de DoubleClick simplemente ser un método vacío que lo come?
¿Por qué no dejar la columna IsSelected sin límites? Utilice el evento CellContentClick para enviar los datos a la tabla de datos subyacente y deje solo el evento CellDoubleClick o RowChange.
private void dgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if(e.ColumnIndex == <columnIndex of IsSelected>)
{
string value = dgv[e.ColumnIndex, e.RowIndex].EditedFormattedValue;
if( value == null || Convert.ToBoolean(value) == false)
{
//push false to employeeSelectionTable
}
else
{
//push true to employeeSelectionTable
}
}
}
Ya intenté sobreescribir el método OnDoubleClick en la subclase DataGridView para no hacer nada, pero todavía permitía que la casilla de verificación se cambiara por segunda vez.
Idealmente, quería que se llamara dos veces al evento RowChanged de DataTable. ¿Hay alguna manera de afectar la DataTable subyacente a través del método OnDoubleClick anulado?
No sé por qué tuve que hacerlo, pero pude poner un evento de marcación de temporizador adjuntado a una actualización de vista de tabla de datos que acaba de actualizar el dgv después del segundo clic.
En evento de clic de celda
** _RefreshTimer = new Timer();
_RefreshTimer.Tick += new EventHandler(RefreshTimer_Tick);
_RefreshTimer.Interval = 100;
_RefreshTimer.Start();
}
}
}
void RefreshTimer_Tick(object sender, EventArgs e)
{
dgv.Refresh();
_RefreshTimer.Stop();
_RefreshTimer = null;
}**
En caso de que desee una columna de casilla de verificación dentro de un DataGridView, cree algo como esto:
DataGridViewCheckBoxCell checkBoxCell = new MyDataGridViewCheckBoxCell();
...
DataGridViewColumn col = new DataGridViewColumn(checkBoxCell);
...
col.Name = "colCheckBox";
...
this.dgItems.Columns.Add(col);
donde dgItems es la instancia de DataGridView.
Como pueden ver, tengo una clase MyDataGridViewCheckBoxCell que es una subclase de la clase DataGridViewCheckBoxCell. En esta subclase defino:
protected override void OnContentDoubleClick(DataGridViewCellEventArgs e)
{
//This the trick to keep the checkbox in sync with other actions.
//base.OnContentDoubleClick(e);
}
Cuando el usuario haga doble clic en una casilla de verificación en la columna de casilla de verificación, la casilla se comportará como si se hubiera hecho clic solo. Esto debería resolver su problema de sincronización.
Esta no es exactamente una solución elegante, pero ¿por qué no simplemente hacer lo siguiente?
private void dgv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
dgv_CellClick(sender, e);
}
Esto forzaría explícitamente el segundo evento de CellClick y evitaría la desincronización.
El motivo por el que hacer un método de evento de DoubleClick vacío no ayudaría es que se ejecute además de las otras operaciones que ocurren cuando se produce un doble clic.
Si observa el código generado por Windows o ejemplos de controladores de eventos que agregan programáticamente, use + = para asignar el controlador de eventos. Esto significa que está agregando ese controlador de eventos además de los otros que ya existen, podría tener múltiples controladores de eventos activados en el evento de guardar.
Mi instinto hubiera sido anular la clase DataGridView, luego anular el método OnDoubleClick y no llamar al método base OnDoubleClick.
Sin embargo, lo he probado muy rápido y estoy viendo algunos resultados interesantes.
Reuní la siguiente clase de prueba:
using System;
using System.Windows.Forms;
namespace TestApp
{
class DGV : DataGridView
{
private string test = "";
protected override void OnDoubleClick(EventArgs e)
{
MessageBox.Show(test + "OnDoubleClick");
}
protected override void OnCellMouseDoubleClick(System.Windows.Forms.DataGridViewCellMouseEventArgs e)
{
MessageBox.Show(test + "OnCellMouseDoubleClick");
}
protected override void OnCellMouseClick(System.Windows.Forms.DataGridViewCellMouseEventArgs e)
{
if (e.Clicks == 1)
{
// Had to do this with a variable as using a MessageBox
// here would block us from pulling off a double click
test = "1 click ";
base.OnCellMouseClick(e);
}
else
{
MessageBox.Show("OnCellMouseClick");
}
}
}
}
Luego inserta esto en un formulario de Windows, agregando una columna de casilla de verificación y ejecutando el programa.
En una nueva ejecución, haciendo doble clic en la casilla de verificación hace que la pantalla del mensaje muestre "1 clic en OnDoubleClick".
Esto significa que OnCellMouseClick se ejecutó en la primera parte del doble clic y luego OnDoubleClick se ejecutó en el segundo clic.
Además, desafortunadamente, la eliminación de la llamada a los métodos base no parece impedir que la casilla de verificación reciba el clic.
Sospecho que para este enfoque de trabajo puede que deba tomarse más y anular DataGridViewCheckBoxColumn y DataGridViewCheckBoxCell que ignora el doble clic. Suponiendo que esto funcione, podría dejar de hacer doble clic en la casilla de verificación, pero permitirla en los otros controles de la columna.
He publicado una respuesta a otra pregunta que trata sobre la creación de columnas y columnas de DataGridView personalizadas aquí .