2010-05-27 16 views
6

Argh, aunque he estado buscando en Google, realmente apreciaría que alguien pudiera resolver mi problema ya que todos los ejemplos de código en línea me confunden más que ayudar (quizás es tarde). .WPF Databinding With A Collection Objeto

tengo una clase simple como se define a continuación:

public class Person 
{ 
    int _id; 
    string _name; 

    public Person() 
    { } 

    public int ID 
    { 
     get { return _id; } 
     set { _id = value; } 
    } 

    public string Name 
    { 
     get { return _name; } 
     set { _name = value; } 
    } 
} 

que se almacena en una base de datos, ya través de un poco más de código que lo puse en un objeto ObservableCollection para intentar DataBind en WPF más adelante:

public class People : ObservableCollection<Person> 
{ 
    public People() : base() { } 

    public void Add(List<Person> pListOfPeople) 
    { 
     foreach (Person p in pListOfPeople) this.Add(p); 
    } 
} 

En XAML, tengo un ListView que me gustaría llenar un ListViewItem (que consiste en un bloque de texto) para cada elemento en el objeto "Personas" a medida que se actualiza desde la base de datos. También me gustaría que ese bloque de texto se vincule a la propiedad "Nombre" del objeto Persona.

Al principio pensé que podía hacer esto:

lstPeople.DataContext = objPeople; 

donde lstPeople es mi control ListView en mi XAML, pero que desde luego no hace nada. He encontrado TONELADAS de ejemplos en línea donde las personas a través de XAML crean un objeto y luego se unen a él a través de su XAML; pero no uno donde nos unimos a un objeto instanciado y redibujamos en consecuencia.

Podría alguien por favor, dame algunos consejos sobre: ​​

a) cómo enlazar un control ListView a mis instanciados "Personas" objeto de colección?

B) ¿Cómo podría aplicar una plantilla a mi ListView para formatearla para los objetos en la colección?

Incluso se apreciarán los enlaces a un ejemplo decente (no uno que opere en un objeto declarado en XAML por favor).

Gracias por su tiempo.

Respuesta

6

Estabas tan cerca.

lstPeople.ItemsSource = objPeople; // :) 

Lo único que necesita es cómo aplicar una vista para cada elemento de su colección. No hay problema. No usaré ListView ... Usaré un ItemsControl porque es un poco más simple.

<ItemsControl x:Name="lstPeople"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
       <TextBlock Text="{Binding Name}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Eso es más o menos. La estrategia es la misma para una vista de lista, pero debe proporcionar un poco más de XAML para proporcionar encabezados de columna y esas cosas. No estoy 100% seguro de que necesites esto en este momento, así que lo dejé fuera.

Edit: Aquí hay un método de extensión para "AddRange" que hará lo que está intentando hacer subclasificando ObservableCollection. Poco más fácil ... sobre todo si se termina con una gran cantidad de tipos de colección (usted)

public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items) 
{ 
    foreach(var item in items) 
    { 
      collection.Add(item); 
    } 
} 

A continuación, puede simplemente hacer:

ObservableCollection<Person> peeps = new ObservableCollection<Person>(); 
peeps.AddRange(new List<Person> 
{ 
    new Person() { Name = "Greg" }, 
    new Person() { Name = "Joe" } 
}); 
+0

+1 tuve una respuesta casi idéntica para usted. – slugster

+0

¡Ah, gracias por exponer a todos! – Randster

0

@Anderson golpearme por segundo, mi respuesta fue muy similar.

Una cosa voy a añadir sin embargo: no hay necesidad de definir un nuevo tipo de colección que hereda de ObservableCollection, en cambio sólo se puede hacer esto:

ObservableCollection<Person> myPeopleCollection = new ObservableCollection<Person>(); 

la única vez que quiera extenderla es si vas a hacer algo diferente o elegante con él, lo cual no parece que estés haciendo.

+0

OP deseaba un tipo de método "AddRange" para su colección. A menudo he querido esto en ObservableCollections. Puedo ver por qué harías eso. He escrito ExtensionMethods para hacer lo mismo. –

+0

@Anderson - sí, a primera vista, todo lo que vi fue la función * Agregar *, cuando lo mencionaste volví a mirar y vi el parámetro que le estaba pasando. – slugster

0

De hecho la respuesta de Anderson Imes 'es correcta (upvote), aunque tengo dos observaciones:

En primer lugar, si sólo necesita mostrar una propiedad de un objeto, creo que es más fácil y más limpio para usar ListBox vez de ListView, ya que el código para la unión de la propiedad se reducirá a

<ListBox x:Name="lstPeople" DisplayMemberPath="Name" /> 

en segundo lugar, si está utilizando WPF y Encuadernación, asegúrese de que sus objetos implementan INotifyPropertyChanged, por lo que los cambios siempre se sincronizan entre la interfaz de usuario y la objetos.

public class Person : INotifyPropertyChanged 
{ 
    int _id; 
    string _name; 

    public Person() 
    { } 

    public int ID 
    { 
     get { return _id; } 
     set { 
      _id = value; 
      RaisePropertyChanged("ID"); 
      } 
    } 

    public string Name 
    { 
     get { return _name; } 
     set { 
      _name = value; 
      RaisePropertyChanged("Name"); 
      } 
    } 

    pivate void RaisePropertyChanged(string propName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
    } 

} 
+0

Gracias por el consejo; seguir google me lleva a pensar que tienes razón y tendré que implementar INotifyPropertyChanged en mi código. ¡Gracias por la información! – Randster

Cuestiones relacionadas