MVVM 绑定 ObservableCollection 到 Listview 不工作

Posted

技术标签:

【中文标题】MVVM 绑定 ObservableCollection 到 Listview 不工作【英文标题】:MVVM binding ObservableCollection to Listview Not working 【发布时间】:2016-08-05 14:20:54 【问题描述】:

我是 MVVM 新手,我正在尝试将 ObservableCollection 绑定到 Listview。

视图模型

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

查看

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

单击按钮时,我将绑定到列表查看具有属性名称和姓氏的类人循环中的一些数据,我错在哪里。谢谢

【问题讨论】:

为什么ItemsSource="Binding "&gt; 应该是observableprsn 是空的 您的应用程序中是否有任何绑定错误,请查看绑定错误的输出 没有错误,我试过 ItemsSource="Binding observableprsn "> 但没有影响。 Vm中的命令是否被调用 是的 oncommand 被调用。从 ICommand 界面 【参考方案1】:
private ObservableCollection<Person> observableprsn = new ObservableCollection<Person>();

您需要Public 收藏而不是私有财产

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

    private ObservableCollection<Person> _observableprsn  get; set; 

Xaml(这对我有用)

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

【讨论】:

【参考方案2】:

您想在视图中绑定的任何属性都应该是DependencyProperty 或实现INotifyPropertyChanged。这些属性应该是public,以便视图可以访问它们。

像这样实现您的 ViewModel:

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

Person 类当然也应该实现DependencyProperty 或INotifyPropertyChanged。

【讨论】:

我认为ObservableCollection 会在AddRemove 发生时引发collectionChanged event,只有在属性更改时我们需要RaiseProperty。如果我错了,请纠正我 正确。但是,当 Person 的属性发生更改(例如 Name)时,除非 Person 类触发其自己的 PropertyChanged 事件,否则这不会反映在 View 中。 在 OP 中,它的 Add() 被调用,所以假设会自动更新 @Eldho。实际上,Add() 方法会导致 ObservableCollection 触发 CollectionChanged 事件。 是的,所以我假设 RaiseProperty 不是导致问题的原因

以上是关于MVVM 绑定 ObservableCollection 到 Listview 不工作的主要内容,如果未能解决你的问题,请参考以下文章

MVVM下拉框绑定触发事件

MVVM下拉框绑定触发事件

MVVM下拉框绑定触发事件

MVVM下拉框绑定触发事件

数据绑定库和MVVM

Note7:MVVM模式之数据绑定