2016-04-14 15 views
0

Ich bin neu in MVVM, ich versuche ObservableCollection an Listview zu binden.MVVM-Bindung ObservableCollection zu Listview funktioniert nicht

Ansichtsmodell

namespace Multiwindow.Viewmodel 
{ 

    public class ViewModelBase 
    { 
     public Commandclass Cclass { get; set; } 

     private ObservableCollection<Person> observableprsn = new ObservableCollection<Person>(); 

     public ViewModelBase() 
     { 
      Cclass = new Commandclass(this); 
     } 

     public void oncommand() 
     { 
      for (int i = 0; i < 5; i++) 
      { 
       Person p = new Person(); 
       p.Name = "name"; 
       p.Lastname = "lastname" + i; 
       observableprsn.Add(p); 
      }   
     } 
    } 
} 

Ansicht

<Window.Resources> 
     <m:Person x:Key="personmodel"/> 
     <vm:ViewModelBase x:Key="vmodel"/> 
    </Window.Resources> 

    <Grid Background="Gray" DataContext="{StaticResource vmodel}"> 

      <Button Content="Load Window 2" Margin="155,108,177,157" 
        Command="{Binding Cclass, Source={StaticResource vmodel}}" /> 

      <ListView HorizontalAlignment="Left" Height="100" Width="184" 
         DataContext="{Binding Source={StaticResource vmodel}}" 
         ItemsSource="{Binding }"> 
       <ListView.View> 
        <GridView> 
         <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/> 
         <GridViewColumn Header="Address" DisplayMemberBinding="{Binding Lastname}"/> 
        </GridView> 
       </ListView.View> 
      </ListView> 

     </Grid> 

Taste Eines Klick i mit propert Namen und Nachnamen, einige Daten in der Schleife der Klasse Person zur Listenansicht bin Bindung, wo ich falsch ist. Danke

+0

Warum 'Itemssource = "{Binding}"> 'ist leer, sollte es" beobachtbar "sein – Eldho

+0

Gibt es irgendwelche verbindlichen Fehler in Ihrer Anwendung, sehen Sie bitte Ausgabe für Bindungsfehler – Eldho

+0

Kein Fehler, ich habe ItemsSource = "{Binding observableprsn}"> aber keine Auswirkungen versucht. – shiv

Antwort

1
private ObservableCollection<Person> observableprsn = new ObservableCollection<Person>(); 

statt Privateigentum benötigen Sie einen Public Sammlung

public ObservableCollection<Person> Persons 
    { 
     get { return _observableprsn; } 
     set 
     { 
      if (_observableprsn != value) 
      { 
       _observableprsn = value; 
      } 
     } 
    } 

    private ObservableCollection<Person> _observableprsn { get; set; } 

XAML (Dies funktioniert für mich)

<ListView HorizontalAlignment="Left" Height="100" Width="184" 
        ItemsSource="{Binding Persons}"> 
     <ListView.View> 
      <GridView> 
       <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/> 
       <GridViewColumn Header="Address" DisplayMemberBinding="{Binding lastName}"/> 
      </GridView> 
     </ListView.View> 
    </ListView> 
0

Jede Eigenschaft, die Sie in Ihrer Ansicht binden möchten, sollte entweder DependencyProperty sein oder INotifyPropertyChanged implementieren. Diese Eigenschaften sollten public sein, damit sie von der Ansicht zugänglich sind.

Implementieren Sie Ihre Ansichtsmodell wie folgt aus:

public class ViewModelBase : INotifyPropertyChanged 
{ 
    private ObservableCollection<Person> _observableprsn = new ObservableCollection<Person>(); 

    public ObservableCollection<Person> Persons 
    { 
     get { return _observableprsn; } 
     set 
     { 
      if (_observableprsn != value) 
      { 
       _observableprsn = value; 
       RaisePropertyChanged(() => Persons); 
      } 
     } 
    } 

    #region implementation of INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocatorAttribute] 
    protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression) 
    { 
     var propertyName = ExtractPropertyName(propertyExpression); 
     this.RaisePropertyChanged(propertyName); 
    } 

    [NotifyPropertyChangedInvocator] 
    protected virtual void RaisePropertyChanged(string propertyName) 
    { 
     OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
    } 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
     PropertyChanged?.Invoke(this, e); 
    } 

    private static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression) 
    { 
     if (propertyExpression == null) 
     { 
      throw new ArgumentNullException("propertyExpression"); 
     } 

     var memberExpression = propertyExpression.Body as MemberExpression; 
     if (memberExpression == null) 
     { 
      throw new ArgumentException("The expression is not a member access expression.", "propertyExpression"); 
     } 

     var property = memberExpression.Member as PropertyInfo; 
     if (property == null) 
     { 
      throw new ArgumentException("The member access expression does not access a property.", "propertyExpression"); 
     } 

     var getMethod = property.GetGetMethod(true); 
     if (getMethod.IsStatic) 
     { 
      throw new ArgumentException("The referenced property is a static property.", "propertyExpression"); 
     } 

     return memberExpression.Member.Name; 
    } 
    #endregion 
} 

Die Person-Klasse auch entweder DependencyProperty oder INotifyPropertyChanged implementieren natürlich sollte.

+0

Ich denke, "ObservableCollection" wird "collectionChanged Ereignis" auslösen, wenn 'Add' oder' Remove' ist aufgetreten, müssen wir nur 'RaiseProperty' wenn Eigenschaft geändert wird. Korrigieren Sie mich, wenn ich falsch liege – Eldho

+1

Richtig. Wenn jedoch eine Eigenschaft von Person geändert wird (z. B. Name), wird dies nur dann in der Ansicht angezeigt, wenn die Person-Klasse ihr eigenes PropertyChanged-Ereignis auslöst. –

+0

In OP wird 'Add()' aufgerufen, also angenommen, automatisch aktualisiert zu werden – Eldho

Verwandte Themen