【问题标题】:Observablecollection not updating list, when an item gets added添加项目时,Observablecollection 不更新列表
【发布时间】:2016-03-13 20:24:49
【问题描述】:

我正在使用 MVVM 模式并希望使用可观察的集合来更新 ListView。我经历了几个 SO 问题,但看不到我做错了什么。任何帮助深表感谢。谢谢。

View.xaml

命名空间:xmlns:local="clr-namespace:MusicPlayer.ViewModel"

数据上下文

<UserControl.DataContext>
    <local:AllTracksViewModel/>
</UserControl.DataContext>

列表视图

<ListView x:Name="TrackListView" 
                  ItemsSource="{Binding Path=TrackListObservable}">
...
<ListView.View>
   <GridView>
     <GridViewColumn Header="Title" Width="250" DisplayMemberBinding="{Binding Title}" />
      <GridViewColumn Header="Album" Width="200" DisplayMemberBinding="{Binding Album}" />
      <GridViewColumn Header="Artist" Width="150" DisplayMemberBinding="{Binding Artist}" />
      <GridViewColumn Header="Duration" Width="100" DisplayMemberBinding="{Binding FormattedDuration}" />
      </GridView>
    </ListView.View>
</ListView>

ViewModel.cs

public class AllTracksViewModel
{
    public ObservableCollection<Track> TrackListObservable { get; private set; }

    public AllTracksViewModel()
    {
        TrackListObservable = new ObservableCollection<Track>();
    }
}

我确认项目肯定会添加到 observable 中。 再次感谢您的帮助。

【问题讨论】:

  • 您是否正确实施 INotifyPropertyChanged?
  • 发布更新 observablecollection 的代码。
  • @sthotakura 我没有任何代码。我虽然该集合会自动执行此操作...
  • 我的意思是您将项目添加到可观察集合的代码。
  • 您不需要 INotifyPropertyChanged。你只需要绑定到正确的列表。请看下面我的回答

标签: c# wpf listview mvvm


【解决方案1】:

将您的代码更改为:

public class AllTracksViewModel : INotifyPropertyChanged
{
    ObservableCollection<Track> trackListObservable;

    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<Track> TrackListObservable {
      get { return trackListObservable; }
      set {
        trackListObservable = value;
        if(PropertyChanged!=null) {
          PropertyChanged(this, new PropertyChangedEventArgs("TrackListObservable"));
        }
      }
}

    public AllTracksViewModel()
    {
        TrackListObservable = new ObservableCollection<Track>();
    }
}

解释一下原因:你的 ViewModel 的每个属性都应该通知它的变化。

【讨论】:

  • ObservableCollection 不是已经实现了 INotifyPropertyChanged 吗?
  • 是的,但您的 TrackListObservable 没有,因此它不会在更改时通知。
  • @HaloMediaz 不完全 - ObservableCOllection 实现了 INotifyCollectionChanged 以便在添加/删除项目时,任何绑定的内容都会更新。您仍然需要实现 INotifyPropertyChanged 并让各个属性通知它们已更新,否则绑定子系统将永远不会知道可观察集合已分配给该属性。
  • @slugster 我不需要知道个别项目何时更新。我只需要知道何时添加/删除了一个项目,然后该项目会反映列表视图中的更改。
  • @slugster 经过数小时的搜索“您仍然需要实现 INotifyPropertyChanged 并让各个属性通知它们已更新...”是关键短语。我正在使用 Prism 库,但是一旦我意识到还需要设置各个属性以进行通知,这一切都奏效了。谢谢!
【解决方案2】:

你应该把它写成 itemsource

ItemsSource="{Binding ViewModel.TrackListObservable}"

并且还自己设置windows的数据上下文。

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}" ...

在 MainWindow 中使用此属性。

public AllTracksViewModel ViewModel { get; } = new AllTracksViewModel();

请注意,您必须向此属性添加项目。 ViewModel.TrackListObservable

你也应该删除

<UserControl.DataContext>
    <local:AllTracksViewModel/>
</UserControl.DataContext>

因为数据上下文是它自己的主窗口,所以 itemsource 设置为ViewModel.TrackListObservable

【讨论】:

    【解决方案3】:

    您的代码看起来正确。但是,我看不到填充您的TrackListObservable 的方法。我建议您在构造函数中调用填充方法FillData。让我举个例子:

    public class AllTracksViewModel
    {
        private ObservableCollection<Track> _trackListObservable;
        public ObservableCollection<Track> TrackListObservable
        {
           get { return _trackListObservable; }
           set { 
                 _trackListObservable = value;                 
               }
        }
    
        public AllTracksViewModel()
        {
             FillData();
        }
    
        private void FillData()
        {
           _trackListObservable = new ObservableCollection<Track>();
            for (int i = 0; i < 30; i++)
            {
               TrackListObservable.Add(new Track() { Title = "Ben & Joseph " + i.ToString(), 
                                                                     Artist = "Albahari" });
            }   
        }
    }
    

    请看binding ListView using MVVM pattern.的工作示例

    【讨论】:

    • @HaloMediaz 随时提出任何问题。
    【解决方案4】:

    这里你的属性 TrackListObservable 必须是 INotify 属性或依赖属性。这样只有你才能达到你想要的结果。

    关于 INotify 属性,请参考以下链接: https://msdn.microsoft.com/library/ms743695(v=vs.100).aspx

    【讨论】:

    • 请考虑不要只是重复解决方案而不添加任何内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多