none
Problema con Datagrid y columnas CheckBox RRS feed

  • 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

    lunes, 24 de agosto de 2015 15:44

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
    martes, 25 de agosto de 2015 17:31

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
    martes, 25 de agosto de 2015 17:31
  • 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

    miércoles, 26 de agosto de 2015 5:40
  • 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

     
    miércoles, 26 de agosto de 2015 9:42