none
Binding en ObservableCollection RRS feed

  • Pregunta

  • No consigo que se visualicen de forma automática (por binding) los elementos añadidos a una ObservableCollection.

     

    <Window x:Class="pantalla.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:pantalla"    
        Title="Lista de Eventos" Height="585" Width="1149">
        
        <Window.Resources>
            <local:Rondas x:Key="ListaRondas">
             </local:Rondas>
            <DataTemplate DataType="{x:Type local:Ronda}">
                <StackPanel Orientation="Horizontal">
                    <Border Margin="3">
                        <TextBlock>
                            <TextBlock Text="{Binding Operador}" Width="100"/>
                        </TextBlock>
                    </Border>
                </StackPanel>
            </DataTemplate>
        </Window.Resources>
    
        <Grid Name="grid" DataContext="{StaticResource ListaRondas}">
            <ListView ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" 
                      Margin="12,12,21,73" Name="listView1">
            </ListView>
            <Button Height="30" HorizontalAlignment="Right" Margin="0,0,38,37" Name="button2" 
                    VerticalAlignment="Bottom" Width="101" Click="button2_Click">Añadir Elementos</Button>
            
        </Grid>
        
    </Window>
    
    

     


    El código C# es el siguiente:

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Diagnostics;
    
    namespace pantalla
    {
        /// <summary>
        /// Lógica de interacción para Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            public Ronda r = new Ronda();
            public Rondas rondas = new Rondas();
            
    
            public enum EstadosAlarma { Reposo, Enterado, Alarma } ;
    
            public Window1()
            {
                InitializeComponent();
                Inicio();
            }
            private void Inicio()
            {
                Ronda r1 = new Ronda();
                Ronda r2 = new Ronda();
                Ronda r3 = new Ronda();
                Ronda r4 = new Ronda();
                Ronda r5 = new Ronda();
                Ronda r6 = new Ronda();
                Ronda r7 = new Ronda();
    
        
    
                grid.DataContext = rondas; // Establecer el DataContext
    
                agregarRonda(r1, ref rondas,  "José");
                agregarRonda(r2, ref rondas,  "José Luis");
                agregarRonda(r3, ref rondas,  "Javier");
                agregarRonda(r4, ref rondas, "Juán Luis");
                agregarRonda(r5, ref rondas,  "Lucía");
                agregarRonda(r6, ref rondas,  "Santos");
                agregarRonda(r7, ref rondas,  "Juanbi");
               
    
                trazarRondas( rondas);
    
    
                grid.DataContext = rondas; // datos para la vinculación (se generarán más de forma dinámica)
            }
    
            private void trazarRondas(Rondas rondas)
            {
                int n = 0;
                foreach (Ronda ron in rondas)
                {
                    Trace.WriteLine(string.Format("{0} {1}", n, ron.Operador));
                    ++n;
                }
            }
    
         
            private static void agregarRonda(Ronda r3, ref Rondas rondas, 
                                                     string operador)
            {
                
                r3.Operador = operador;
                rondas.Add(r3);
            }
    
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                Ronda r = new Ronda();
                Rondas rondas = (Rondas) this.FindResource("ListaRondas");
                agregarRonda(r, ref rondas,  "Lucía");
                agregarRonda(r, ref rondas, "Santos");
                agregarRonda(r, ref rondas,  "Juanbi");
                agregarRonda(r, ref rondas, "Miguelón");
                agregarRonda(r, ref rondas,  "Inés Clara");
                agregarRonda(r, ref rondas,  "Rita");
                trazarRondas(rondas);
                
            }
            
        }
    
        public class Ronda : INotifyPropertyChanged
        {
            public enum EstadosAlarma { REPOSO = 0,  ALARMA = 1, ENT_AL = 2 } ;
    
            public event PropertyChangedEventHandler PropertyChanged;
            protected void Notify(string propName)
            {
                if (this.PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propName));
                }
            }
         
            private string operador;
            public string Operador
            {
                get { return this.operador; }
                set
                {
                    if (this.operador == value) { return; }
                    this.operador = value;
                    Notify("Operador");
                }
            }      
    
        }
    
        public class Rondas : ObservableCollection<Ronda> { };
    }
    
    

     


    Muchas gracias por la ayuda.

    José Luis Torre

     



    Atentamente José Luis Torre
    jueves, 29 de diciembre de 2011 18:01

Respuestas

  • José, acabo de hacer las pruebas. Efectivamente lo que comenté en la respuesta anterior influía en el error, pero no como había imaginado. 

    Lo que sucede es que el método Inicio() crea inicializa tu objeto llamado "rondas" y lo asigna al DataContext del grid, posterior a la asignación de "ListaRondas", definido en XAML. Por lo tanto los objetos que ves en la lista son los de "rondas". Por otra parte, en el método Inicio() asignás dos veces el DataContext. Esto no es necesario, ya que Rondas es un ObservableCollection, y no debés volver a asignar el contexto para que se refresquen los datos.

    Modificando de la siguiente manera button2_click, anda perfecto, pero habría otras cosas para hacer como mejorar el método "agregarRonda", borrar el elemento ListaRondas y sus referencias, etc.:

    private void button2_Click(object sender, RoutedEventArgs e)
    {
        //esta asignación oculta la variable "rondas" definida para esta clase,
        //que es la que usamos para el databinding
        //Rondas rondas = (Rondas)this.FindResource("ListaRondas");
    
        //esto es reemplazado, ya que si se usa una sola ronda se agrega el item "Rita" 6 veces
        //Ronda r = new Ronda();
        Ronda r1 = new Ronda();
        Ronda r2 = new Ronda();
        Ronda r3 = new Ronda();
        Ronda r4 = new Ronda();
        Ronda r5 = new Ronda();
        Ronda r6 = new Ronda();
    
        agregarRonda(r1, ref rondas, "Lucía");
        agregarRonda(r2, ref rondas, "Santos");
        agregarRonda(r3, ref rondas, "Juanbi");
        agregarRonda(r4, ref rondas, "Miguelón");
        agregarRonda(r5, ref rondas, "Inés Clara");
        agregarRonda(r6, ref rondas, "Rita");
        trazarRondas(rondas);
    }
    



    Martín Coll - mi blog es martincoll.com.ar, date una vuelta!
    • Propuesto como respuesta Martín Coll jueves, 29 de diciembre de 2011 20:33
    • Marcado como respuesta José Luis Torre jueves, 29 de diciembre de 2011 22:41
    jueves, 29 de diciembre de 2011 20:33

Todas las respuestas

  • Según lo que veo, establecés el DataContext del Grid tanto desde code-behind como desde XAML. Por otra parte, al definir en XAML tu ListaRondas, la inicializás sin ningún valor en ella. Lo que imagino es que se están superponiendo, y la que prevalece es justo la que se encuentra vacía.

    En un rato hago una prueba, si es que no lo hacés antes vos.

    Saludos!


    Martín Coll - mi blog es martincoll.com.ar, date una vuelta!
    jueves, 29 de diciembre de 2011 20:09
  • José, acabo de hacer las pruebas. Efectivamente lo que comenté en la respuesta anterior influía en el error, pero no como había imaginado. 

    Lo que sucede es que el método Inicio() crea inicializa tu objeto llamado "rondas" y lo asigna al DataContext del grid, posterior a la asignación de "ListaRondas", definido en XAML. Por lo tanto los objetos que ves en la lista son los de "rondas". Por otra parte, en el método Inicio() asignás dos veces el DataContext. Esto no es necesario, ya que Rondas es un ObservableCollection, y no debés volver a asignar el contexto para que se refresquen los datos.

    Modificando de la siguiente manera button2_click, anda perfecto, pero habría otras cosas para hacer como mejorar el método "agregarRonda", borrar el elemento ListaRondas y sus referencias, etc.:

    private void button2_Click(object sender, RoutedEventArgs e)
    {
        //esta asignación oculta la variable "rondas" definida para esta clase,
        //que es la que usamos para el databinding
        //Rondas rondas = (Rondas)this.FindResource("ListaRondas");
    
        //esto es reemplazado, ya que si se usa una sola ronda se agrega el item "Rita" 6 veces
        //Ronda r = new Ronda();
        Ronda r1 = new Ronda();
        Ronda r2 = new Ronda();
        Ronda r3 = new Ronda();
        Ronda r4 = new Ronda();
        Ronda r5 = new Ronda();
        Ronda r6 = new Ronda();
    
        agregarRonda(r1, ref rondas, "Lucía");
        agregarRonda(r2, ref rondas, "Santos");
        agregarRonda(r3, ref rondas, "Juanbi");
        agregarRonda(r4, ref rondas, "Miguelón");
        agregarRonda(r5, ref rondas, "Inés Clara");
        agregarRonda(r6, ref rondas, "Rita");
        trazarRondas(rondas);
    }
    



    Martín Coll - mi blog es martincoll.com.ar, date una vuelta!
    • Propuesto como respuesta Martín Coll jueves, 29 de diciembre de 2011 20:33
    • Marcado como respuesta José Luis Torre jueves, 29 de diciembre de 2011 22:41
    jueves, 29 de diciembre de 2011 20:33
  • Hola Martín:

    Muchas gracias por tu respuesta, ha sido de gran ayuda y me he aclarado bastante.

    Veo que el problema era establecer más de una vez el contexto, ahora lo hago sólo por código y me funciona perfectamente.

     

    Saludos

    José Luis

     


    Atentamente José Luis Torre
    jueves, 29 de diciembre de 2011 22:43