Principales respuestas
Como capturar el evento de final de edición de una celda en un datagridtextcolumn de un datagrid

Pregunta
-
Hola
Tengo un datagrid al que le paso por binding la propiedad llamada "Modelo" de una clase ViewModel y esta propiedad contiene una Lista de Entidades del Modelo en este caso una lista de entidades "Cuadrante", con lo cual cada fila del datagrid es una entidad "Cuadrante" y lo que se ve es una serie de valores correspondientes a una serie de días y al final un valor que es el total de los anteriores.
El caso es que lo que necesito es que al editar una fila automáticamente se actualice el total, es decir, el ultimo valor, pero en primer lugar no logro capturar ningún evento donde puede ver el nuevo valor que tiene no solo la celda en el datagrid sino la entidad subyacente y el evento CellEditEnding no me vale por que en este evento la edición aún no se ha cometido y no veo el cambio en la entidad.
No se si lo que pretendo se puede hacer pero en esas andamos
Un saludo
kintela @esekintela
Respuestas
-
Hola
Al final lo he conseguido de esta manera
En el evento CellEditEnding del datagrid tengo esto
DataGridCell cell = GetCell(e.Row, 35);
cell.Content = vm.Modelo[e.Row.GetIndex()].TotalFila;
por que en la columna 35 es donde van los Totales que los saco de la propiedad TotalFila del ViewModel enlazado al datagrid
Luego tengo estas 2 funciones
public DataGridCell GetCell(DataGridRow row, int column)
{
DataGridRow rowContainer = row;
if (rowContainer != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
if (cell == null)
{
dg_Cuadrante.ScrollIntoView(rowContainer, dg_Cuadrante.Columns[column]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
}
return cell;
}
return null;
}
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}Un saludo
kintela @esekintela
- Marcado como respuesta Roberto Quintela Modia martes, 22 de julio de 2014 15:28
Todas las respuestas
-
Hola.
Te pongo un codigo que utilice en su momento para interceptar y validar una celda en un datagrid de WPF.
private void dataGridSeries_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { // Obtengo el numero de fila seleccionado fila = e.Row.GetIndex(); // Obtengo el numero de columna seleccionada int columna= e.Column.DisplayIndex; // Obtengo lo que hay escrito en la celda en modo edición. FrameworkElement editado = e.EditingElement; // Obtengo el Item de toda la fila DataRowView filagrid = (DataRowView) e.Row.Item; // Instancio array con el mismo numero de posiciones que de Items string[] a = new string[filagrid.Row.ItemArray.Length]; TextBox texto = (TextBox)editado; // Recorro todas las posiciones del item para cambiar y validar el dato introducido. for (int con = 0; con <= filagrid.Row.ItemArray.Length - 1; con++) { a[con] = filagrid.Row.ItemArray[con].ToString(); } try { // Mi metodo para validar y cambiar punto por coma Validacion valido = new Validacion(); texto.Text = valido.CambiaAComa(texto.Text); if (valido.EsNumero(texto.Text)) { a[columna] = texto.Text; } else { a[columna] = "0"; } } // Si hay algun error el valor pasara a ser cero catch (Exception) { a[columna] = "0"; } // Cargo lo editado en el Item filagrid.Row.ItemArray = a; // Fuerzo la terminación de la edición filagrid.EndEdit(); // LLamo metodo para calcular errores y medias errores[fila] = Calculos.Error(filagrid); // Nuleo y vuelvo a cargar los datos para actualizar dataGridErrores.ItemsSource = null; dataGridErrores.ItemsSource = errores; Cambios(); }
En este codigo hay clases y metodos creados por mi que no sabras que son exactamente como Calculos y Validacion pero no son importantes, la idea principal son las 5 o 6 primeras lineas que es donde consigo los datos de la celda y en las ultimas lineas que es donde se vuelve a cargar los datos actualizados y validados.
Espero te sea de útilidad. Un saludo.
Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido útil agradécelo marcándola como útil.
-
Hola
Muchas Gracias por la ayuda. Me ha servido para ver como acceder al valor de la celda editada, pero mi problemática es que estoy usando un datagrid de WPF con el patrón MVVM (Model View ViewModel) con lo que la Vista donde se muestra el datagrid tiene un ViewModel (una clase) como datacontext y luego el itemsource del datagrid es una propiedad de ese ViewModel que en mi caso es una lista de entidades cada una de las cuales tiene X propiedades entre las que están los días del mes y una para el total con lo que se muestran una serie de filas editables con un calendario. Al editar una fila automáticamente en el evento que me comentas yo ya tengo actualizado el ViewModel asociado a la fila editada y la entidad del modelo que rellena ese ViewModel y por consiguiente la propiedad Total pero lo que no consigo hacer es que la columna del total en el gris se actualice en consecuencia.
Una vez que obtengo la fila del gris editada y el valor editado gracias a tu código
// Obtengo el numero de fila seleccionado
int numFila = e.Row.GetIndex();
// Obtengo el numero de columna seleccionada
int numColumna = e.Column.DisplayIndex;
// Obtengo lo que hay escrito en la celda en modo edición.
FrameworkElement editado = e.EditingElement;
TextBox texto = (TextBox)editado;
string valor = texto.Text;
DataGridRow filaGrid = e.Row;Ahora no se como acceder al elemento correspondiente a la propiedad Total ara que en el interface se vea el valor que por detrás automáticamente ya está actualizado. Un saludo
kintela @esekintela
-
Por cierto.
Si en este evento hago esto. Es decir "Refresco" el itemsource del datagrid
CuadranteViewModel vm = (CuadranteViewModel)(this.DataContext);
dg_Cuadrante.ItemsSource = vm.Modelo;El datagrid "dg_Cuadrante" no se actualiza. Pero si hago esto si. Pero claro el rendimiento es muy pobre
//CuadranteViewModel vm = (CuadranteViewModel)(this.DataContext);
//dg_Cuadrante.ItemsSource = null;
//dg_Cuadrante.ItemsSource = vm.Modelo;
Un saludo
kintela @esekintela
-
Mira.
Una de las cosas que estoy haciendo ahora que no se si sera muy elegante o muy efectiva, yo solo soy un mero aficionado que ademas esta empezado, es lo siguiente. Me instancio un objeto para toda la clase que es mi entidad.
public partial class FormPatrones : UserControl { private NegocioPatrones patronseleccionado = new NegocioPatrones(); // aqui sigue todo el codigo
luego uso el eventoSelectionChanged para tener controlado en todo momento el item seleccionado con sus datos.
private void dataGridPatrones_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count > 0) { patronseleccionado = (NegocioPatrones)e.AddedItems[0]; dataGridHistorico.ItemsSource = new NegocioHistoricoPatrones().Cargar(patronseleccionado.Identificacion , "Historico" + tipoform); } }
a partir de aqui teniendo el elemento seleccionado y con el codigo anterior podrias intentar modificarlo haber si consigues lo que deseas, por suerte ese elemento creo que es una referencia por tanto si lo modificas se vera reflejado.
Y como ves en este caso no pongo a null el ItemsSorce y se refrescan bien los datos, tambien es cierto que lo cargo con una instancia nueva.
Ya te digo quizad combinando estas dos cosas puedas conseguir algo.
AAAAAA Una cosa mas. ¿Has intentado en vez de esto?
// Obtengo el Item de toda la fila DataRowView filagrid = (DataRowView) e.Row.Item;
usar e.Row.Item y combertirlo en tu entidad.tuentidad seleccion = (tuentidad) e.Row.Item;
Hacer lo que tengas que hacer y luego modificarla seleccion.propiedadamodificar= valormodificado;
Me comentas un saludo.
Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido útil agradécelo marcándola como útil.
-
Hola
Muchas Gracias. Yo es que no tengo DataGridView tengo datagrid de WPF y como comenté antes el problema ahora es que ya se como acceder al valor de la celda editada pero no consigo actualizar automáticamente el valor de otra que es un total.
Un saludo
kintela @esekintela
-
El codigoque he puesto en los dos casos es para WPF aunque utilice un objeto
DataRowView
para combertir es lo que consegui.
Otra idea, podrias hacer que tu entidad herede de Inotificable, asi puedes hacer que cuando una propiedad cambie haya una notificacion que seria mas o menos como un evento y hacer lo que necesites, pero en este caso no puedo ayudar no lo he echo nunca y no se como funciona.. Haber si Lendro, Sergio o cualquiera que sepa un poco mas pueden contarnos un poco como funciona.
Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido útil agradécelo marcándola como útil.
- Editado Rodripelto miércoles, 9 de julio de 2014 11:54
-
-
-
Hola
Al final lo he conseguido de esta manera
En el evento CellEditEnding del datagrid tengo esto
DataGridCell cell = GetCell(e.Row, 35);
cell.Content = vm.Modelo[e.Row.GetIndex()].TotalFila;
por que en la columna 35 es donde van los Totales que los saco de la propiedad TotalFila del ViewModel enlazado al datagrid
Luego tengo estas 2 funciones
public DataGridCell GetCell(DataGridRow row, int column)
{
DataGridRow rowContainer = row;
if (rowContainer != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
if (cell == null)
{
dg_Cuadrante.ScrollIntoView(rowContainer, dg_Cuadrante.Columns[column]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
}
return cell;
}
return null;
}
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}Un saludo
kintela @esekintela
- Marcado como respuesta Roberto Quintela Modia martes, 22 de julio de 2014 15:28