简体   繁体   中英

MVVM binding ObservableCollection to Listview Not working

I am new to MVVM, I am trying to bind ObservableCollection to Listview.

ViewModel

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

View

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

On button click i am binding to listview some data in loop of class person with propert Name and Lastname, where am i Wrong. thanks

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

Instead of private property you need a Public Collection

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

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

Xaml (This works for me)

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

Any property that you would like to bind in your view should be either a DependencyProperty or implement INotifyPropertyChanged . These properties should be public so that they are accessable by the view.

Implement your ViewModel like this:

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
}

The Person class should of course also either implement DependencyProperty or INotifyPropertyChanged .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM