Principales respuestas
Problema con Datagrid y columnas CheckBox

Pregunta
-
Hasta ahora creía que después de tantos años y tantas versiones de WPF ya habría evolucionado, pero me planteo como es que hay quien sigue usándolo, cada línea de código te genera nuevos problemas y te pasas la vida buscando a ver que han hecho otros, pero esto es inimaginable, después de misteriosamente solucionar el problema de la aparición de los CheckBox ligados a datos de la base de datos, ahora el siguiente paso es darle la posibilidad mediante un botón de seleccionar todos, algo simple le enlazas al botón a un comando y en recorres la colección asociada al DataGrid y pones ese campo a true en todos y llamas a NotiFyPropertyChanged, ta simple y de nuevo que no y otra vez la pelea y a buscar por Internet a ver como se hace ....
Si no fuera porque el cliente exige WPF a donde iba a mandar a WPF.
os pongo de nuevo el código pero de verdad que aburrimiento
el GRID y el botón
<DataGrid x:Name="Dtg1" Focusable="False" AutoGenerateColumns="False" ItemsSource="{Binding ListadeSocios}" IsSynchronizedWithCurrentItem="True" TargetUpdated="Dtg1_TargetUpdated" >
<DataGrid.Columns>
<DataGridTextColumn Header="Nombre" Binding="{Binding Nombre}" Width="1*" />
<DataGridTextColumn Header="Apellido" Binding="{Binding Apellidos}" Width="1*" />
<DataGridCheckBoxColumn Header="Casado1" Binding="{Binding Casado, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="0.30*" />
<DataGridTemplateColumn Header="Casado" Width="0.30*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding Casado,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="MarcaTodo" Content="Marcar Todos" Command="{Binding MarcaTodoCommand}" Height="32" Width="125" HorizontalAlignment="Right" Margin="0 10 10 0" />el método ligado al comando
public void Marcatodo(object p)
{
foreach(var x in _listadeSocios)
{
x.Casado = true;
}
NotifyPropertyChanged("ListadeSocios");
}Ahora en memoria todos están casados, y así llega a la View pero de nuevo no pinta nada, podeis echarle un ojo, ya me tiene aburrido.
un saludo
Respuestas
-
Creo que el concepto lo tienes errado.
al hacer un foreach y actualizar la propiedad casado de cada objeto, no significa que el objeto original instanciado haya cambiado su valor. Solo modificaste la propiedad para ese objeto x y despues x se destruye para poder asignarsele otro clon con el objeto siguiente. Asi que en realidad no estan todos en true.
Yo hice lo siguiente, y me funciona:
public partial class MainWindow : Window { List<Socio> _listadeSocios; public MainWindow() { InitializeComponent(); _listadeSocios = new List<Socio>(); _listadeSocios.Add(new Socio("Juan", "Perez", false)); _listadeSocios.Add(new Socio("Pablo", "Hernandez", false)); _listadeSocios.Add(new Socio("Roberto", "Martinez", true)); _listadeSocios.Add(new Socio("José", "Sánchez", false)); Dtg1.ItemsSource = _listadeSocios; } private void MarcaTodo_Click(object sender, RoutedEventArgs e) { List<Socio> tmp_lista = new List<Socio>(); foreach( var x in _listadeSocios) { x.Casado = true; tmp_lista.Add(x); } _listadeSocios = tmp_lista; Dtg1.ItemsSource = _listadeSocios; Dtg1.UpdateLayout(); } private void Dtg1_SelectionChanged(object sender, SelectionChangedEventArgs e) { } } public class Socio { public bool Casado { get; set; } public string Nombre { get; set; } public string Apellido { get; set; } public Socio (string Nombre, string Apellido, bool Casado) { this.Nombre = Nombre; this.Apellido = Apellido; this.Casado = Casado; } public Socio() { } }
Al darle click al boton, pone a todos marcados como casados.
Espero te ayuda.
Saludos.
- Marcado como respuesta fjjcent miércoles, 26 de agosto de 2015 9:43
Todas las respuestas
-
Creo que el concepto lo tienes errado.
al hacer un foreach y actualizar la propiedad casado de cada objeto, no significa que el objeto original instanciado haya cambiado su valor. Solo modificaste la propiedad para ese objeto x y despues x se destruye para poder asignarsele otro clon con el objeto siguiente. Asi que en realidad no estan todos en true.
Yo hice lo siguiente, y me funciona:
public partial class MainWindow : Window { List<Socio> _listadeSocios; public MainWindow() { InitializeComponent(); _listadeSocios = new List<Socio>(); _listadeSocios.Add(new Socio("Juan", "Perez", false)); _listadeSocios.Add(new Socio("Pablo", "Hernandez", false)); _listadeSocios.Add(new Socio("Roberto", "Martinez", true)); _listadeSocios.Add(new Socio("José", "Sánchez", false)); Dtg1.ItemsSource = _listadeSocios; } private void MarcaTodo_Click(object sender, RoutedEventArgs e) { List<Socio> tmp_lista = new List<Socio>(); foreach( var x in _listadeSocios) { x.Casado = true; tmp_lista.Add(x); } _listadeSocios = tmp_lista; Dtg1.ItemsSource = _listadeSocios; Dtg1.UpdateLayout(); } private void Dtg1_SelectionChanged(object sender, SelectionChangedEventArgs e) { } } public class Socio { public bool Casado { get; set; } public string Nombre { get; set; } public string Apellido { get; set; } public Socio (string Nombre, string Apellido, bool Casado) { this.Nombre = Nombre; this.Apellido = Apellido; this.Casado = Casado; } public Socio() { } }
Al darle click al boton, pone a todos marcados como casados.
Espero te ayuda.
Saludos.
- Marcado como respuesta fjjcent miércoles, 26 de agosto de 2015 9:43
-
Entonces lo que me estas queriendo decir con esto, y lo digo para aclararme el concepto, es que la vista recogió una versión del objeto tal como estaba en el momento de la recogida y ya tiene su copia con los valores que tenia entonces, es decir que tiene su propia instancia, y que le hagas lo que le hagas a la clase que queda en el ViewModel ya no le afecta a la vista porque son instancias distintas, y la única solución es reemplazar la instancia que recogió la vista por otra con los valores cambiados.
Esto para mi es nuevo, yo creía que ViewModel y Vista compartían la misma instancia, de ahí que no entiendo los significados de conceptos como RelativeSource, AncestorType y demás que no imagino ni a que se refieren por lo que como dices algunos conceptos no los tengo claros.
podrías aclararme un poco el concepto de REALATIVESOURCE, es que lo leo en los libros y no lo entiendo debe presuponer algo que yo no conozco porque no entiendo ni porque ni para que se usa.
un saludo
-
ya entiendo lo que quieres decir, no sabía a que te referías, hablas de modificar o no la instancia del ViewModel y la lista de socios ligada a la instancia, y tienes razón al escribir _listaSocios no se hace referencia a la instancia, pero esa fue solo una de las pruebas, lo cierto es que el comando envía como parámetro el objeto Viewmodel referenciado como el Datacontext de la vista al decir CommandParameter="{Binding}" y yo en el comando hago la conversión de parámetro mediante xViewModel VM = (xVieModel) parameter y ahora ya al modificar VM.ListaSocios ya si estamos hablando de la misma instancia que se utiliza en la vista, y a pesar de ello al modificar su contenido tampoco se reflejaba ( es que hice pruebas de todas las formas), por eso me extraña que para que funcione haya que crear una nueva lista y machacar la original, creo que hay algo que aún no controlo.
gracias por tu ayuda