2010-05-27 18 views
6

Argh, anche se ho cercato su google, lo apprezzerei davvero se qualcuno potesse rompere il mio problema perché tutti gli esempi di codice online mi confondono di più dell'assistenza (forse è solo tardi) .. .WPF Databinding con un oggetto Collection

ho una semplice classe come definito di seguito:

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; } 
    } 
} 

che è memorizzato in un database, e attraverso un po 'più di codice metto in un oggetto ObservableCollection per tentare di DataBind in WPF seguito:

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

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

In XAML, mi sono un ListView che mi piacerebbe popolare un oggetto ListViewItem (costituito da un blocco di testo) per ogni oggetto nell'oggetto "Persone" man mano che viene aggiornato dal database. Mi piacerebbe anche che il blocco di testo si legasse alla proprietà "Nome" dell'oggetto Person.

ho pensato in un primo momento che ho potuto fare questo:

lstPeople.DataContext = objPeople; 

dove lstPeople è il mio controllo ListView nel mio XAML, ma che ovviamente non fa nulla. Ho trovato decine di esempi online in cui le persone attraverso XAML creano un oggetto e poi lo legano attraverso il loro XAML; ma non uno in cui ci leghiamo a un oggetto istanziato e ri-disegniamo di conseguenza.

Qualcuno potrebbe darmi alcune indicazioni su:

A) Come associare un controllo ListView ai miei istanziati "Persone" oggetto di raccolta?

B) Come posso applicare un modello al mio ListView per formattarlo per gli oggetti nella raccolta?

Anche i collegamenti a un esempio decente (non uno che funziona su un oggetto dichiarato in XAML per favore) sarebbero apprezzati.

Grazie per il vostro tempo.

risposta

6

Eri così vicino.

lstPeople.ItemsSource = objPeople; // :) 

L'unica altra cosa che serve è come applicare una vista per ogni elemento nella vostra collezione. Nessun problema. Non userò un ListView ... Userò semplicemente un ItemsControl perché è un po 'più semplice.

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

Questo è praticamente tutto. La strategia è la stessa per Listview, ma è necessario fornire solo un po 'di XAML per fornire intestazioni di colonne e cose. Al momento non sono sicuro al 100% di averne bisogno, quindi l'ho lasciato fuori.

Modifica: Ecco un metodo di estensione per "AddRange" che farà ciò che si tenta di fare sottoclasse ObservableCollection. Po 'più facile ... soprattutto se si finisce con un sacco di tipi di raccolta (si)

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

Poi si può solo fare:

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

+1 ho avuto una risposta quasi identica a voi. – slugster

+0

Ah, grazie per aver esposto tutti! – Randster

0

@Anderson battermi per secondi, la mia risposta è stata molto simile.

Una cosa che posso aggiungere però: non v'è alcuna necessità di definire un nuovo tipo di collezione che eredita da ObservableCollection, invece si può semplicemente fare questo:

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

l'unica volta che si desidera estendere lo è se hai intenzione di fare qualcosa di diverso o di fantasia, cosa che non sembra fare.

+0

L'OP voleva un metodo di tipo "AddRange" per la sua collezione. Ho spesso voluto questo io stesso su ObservableCollections. Capisco perché lo faresti. Ho scritto ExtensionMethods per fare la stessa cosa. –

+0

@Anderson - sì, a prima vista tutto ciò che ho visto era la funzione * Aggiungi *, quando l'hai citata ho guardato di nuovo e ho visto il parametro che ci stava passando. – slugster

0

In effetti la risposta 'Anderson Imes' è corretto (upvote), anche se ho due osservazioni:

In primo luogo, se avete solo bisogno di visualizzare una proprietà di un oggetto, penso che sia più facile e più pulito da usare ListBox invece di ListView, perché il codice per il legame della proprietà sarà ridotto a

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

in secondo luogo, se si sta utilizzando WPF e rilegatura, assicurarsi che gli oggetti implementano INotifyPropertyChanged, in modo che i cambiamenti sono sempre sincronizzati tra UI e la oggetti.

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

Grazie per il suggerimento; ulteriormente googling mi porta a credere che tu abbia ragione e dovrò implementare INotifyPropertyChanged nel mio codice. Grazie per l'informazione! – Randster

Problemi correlati