ObservableCollection未更新列表,当添加项时。

6
我正在使用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>();
    }
}

我确认已经将项目添加到可观察对象中。 再次感谢您的帮助。


1
你是否正确实现了INotifyPropertyChanged接口? - Fang
@sthotakura 我没有任何代码。我认为集合会自动完成这个操作... - HaloMediaz
我的意思是你添加项目到可观察集合的代码。 - Suresh
你不需要使用INotifyPropertyChanged,只需正确地绑定列表即可。请查看下面的答案。 - M.kazem Akhgary
@M.kazemAkhgary ListView在一个UserControl中(我可能应该提到这一点)。我认为视图类中不应该有任何代码后台? - HaloMediaz
显示剩余3条评论
4个回答

7
将您的代码更改为以下内容:
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的每个属性都应通知其更改。

1
ObservableCollection已经实现了INotifyPropertyChanged吗? - HaloMediaz
是的,它确实可以,但是你的TrackListObservable没有这么做,因此当它被更改时不会通知。 - Arnaud Weil
6
@HaloMediaz,不完全正确 - ObservableCollection 实现了 INotifyCollectionChanged 接口,以便在添加/删除项目时,任何绑定的内容都会得到更新。但您仍需要实现 INotifyPropertyChanged 接口,并使各个属性通知它们已更新,否则绑定子系统将永远无法知道可观察集合被分配给了属性。 - slugster
ObservableCollection已经实现了这个功能。但我认为你错过了INotifyPropertyChanged。你试过我的解决方案了吗? - Arnaud Weil
2
@slugster 经过数小时的搜索,"You still need to implement INotifyPropertyChanged and have individual properties notify that they've updated otherwise..." 这句话是关键。我正在使用 Prism 库,但一旦我意识到个别属性也需要设置通知,它就可以正常工作了。谢谢! - dvdhns
显示剩余4条评论

1

你应该将此写为 itemsource

ItemsSource="{Binding ViewModel.TrackListObservable}"

同时将窗口的数据上下文设置为自身。
<Window DataContext="{Binding RelativeSource={RelativeSource Self}}" ...

在MainWindow中使用这个属性。
public AllTracksViewModel ViewModel { get; } = new AllTracksViewModel();

请注意,您需要将项目添加到此属性中:ViewModel.TrackListObservable 您还应该删除

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

由于数据上下文是主窗口本身,因此itemsource设置为ViewModel.TrackListObservable


1
您的代码看起来是正确的。但是我无法看到填充您的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" });
        }   
    }
}

请查看使用MVVM模式绑定ListView的工作示例

@HaloMediaz 随时提出问题。 - StepUp

0

请考虑在没有添加任何内容的情况下不要仅仅重复解决方案。 - Arnaud Weil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接