【问题标题】:MVVM binding ObservableCollection to Listview Not workingMVVM 绑定 ObservableCollection 到 Listview 不工作
【发布时间】: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 界面

标签: c# mvvm


【解决方案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 类当然也应该实现DependencyPropertyINotifyPropertyChanged

    【讨论】:

    • 我认为ObservableCollection 会在AddRemove 发生时引发collectionChanged event,只有在属性更改时我们需要RaiseProperty。如果我错了,请纠正我
    • 正确。但是,当 Person 的属性发生更改(例如 Name)时,除非 Person 类触发其自己的 PropertyChanged 事件,否则这不会反映在 View 中。
    • 在 OP 中,它的 Add() 被调用,所以假设会自动更新
    • @Eldho。实际上,Add() 方法会导致 ObservableCollection 触发 CollectionChanged 事件。
    • 是的,所以我假设 RaiseProperty 不是导致问题的原因
    猜你喜欢
    • 1970-01-01
    • 2012-05-26
    • 2018-05-21
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多