当将新集合分配给绑定属性时,ListView不显示observablecollection,即使调用了RaisePropertyChanged

时间:2016-04-19 15:47:31

标签: c# wpf mvvm mvvm-light observablecollection

我有一个绑定到ObservableCollection的ListView。我面临的问题是,当我分配新集合时,即使我正在调用RaisePropertyChanged,视图也不会更新。

//TrackIO.GetTracks()
public static ObservableCollection<Track> GetTracks() 
{
     return tracks;
}

    <ListView x:Name="TrackListView" 
                  SelectionMode="Single" 
                  ItemsSource="{Binding Path=ObservableTracks}"
                  SelectedIndex="{Binding SelectedTrackIndex, Mode=TwoWay}"
                  >
        <!-- Column Binding matches track object properties -->
             <ListView.View>
                <GridView>
                    <GridViewColumn Header="Title" Width="600" DisplayMemberBinding="{Binding Title}" />
                    <GridViewColumn Header="Album" Width="350" DisplayMemberBinding="{Binding Album}" />
                    <GridViewColumn Header="Artist" Width="250" DisplayMemberBinding="{Binding Artist}" />
                    <GridViewColumn Header="Duration" Width="200" DisplayMemberBinding="{Binding FormattedDuration}" />
                </GridView>
            </ListView.View>
     </ListView>

    private ObservableCollection<Track> _observableTracks;
    public ObservableCollection<Track> ObservableTracks
    {
        get { return _observableTracks; }
        private set
        {
            _observableTracks = value;
            RaisePropertyChanged();
        }
    }

我正在使用MVVM灯来通知viewmodel,将属性设置为不同的集合。

正如您所看到的,我在集合中有项目,因此当我将新集合分配给ObservableTracks属性时。应该调用RaisePropertyChanged(),但视图为空/什么都不显示。 enter image description here

非常感谢任何帮助。感谢。

2 个答案:

答案 0 :(得分:1)

以下代码在我的机器上运行正常。

视图模型:

public class Track
{
    public string Title { get; set; }
}

public class MainViewModel : ViewModelBase
{
    private ObservableCollection<Track> _observableTracks;

    public MainViewModel()
    {
        DoSomething = new RelayCommand(() => ObservableTracks = new ObservableCollection<Track>() { new Track { Title = "test" } });
    }

    public ObservableCollection<Track> ObservableTracks
    {
        get { return _observableTracks; }
        private set
        {
            _observableTracks = value;
            RaisePropertyChanged();
        }
    }

    public RelayCommand DoSomething { get; private set; }
}

查看:

<Window.DataContext>
    <local:MainViewModel />
</Window.DataContext>

<StackPanel>
    <Button Command="{Binding DoSomething}" Content="Do something" />
    <ListView x:Name="TrackListView" 
              SelectionMode="Single" 
              ItemsSource="{Binding Path=ObservableTracks}"
              SelectedIndex="{Binding SelectedTrackIndex, Mode=TwoWay}"
              >
        <!-- Column Binding matches track object properties -->
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Title" Width="600" DisplayMemberBinding="{Binding Title}" />
                <GridViewColumn Header="Album" Width="350" DisplayMemberBinding="{Binding Album}" />
                <GridViewColumn Header="Artist" Width="250" DisplayMemberBinding="{Binding Artist}" />
                <GridViewColumn Header="Duration" Width="200" DisplayMemberBinding="{Binding FormattedDuration}" />
            </GridView>
        </ListView.View>
    </ListView>
</StackPanel>

您是否忘记设置视图的DataContext?

如果没有,你能分享一个失败的简短例子吗?

答案 1 :(得分:0)

需要调用setter才能调用RaisePropertyChanged方法。如果它是私有的,则无法从外部代码调用它。如果Resharper将其标记为不更改状态,则应使用注释忽略它(尽管由于方法调用它不应该标记它)。

private ObservableCollection<Track> _observableTracks;
public ObservableCollection<Track> ObservableTracks
{
    get { return _observableTracks; }
    set
    {
        _observableTracks = value;
        RaisePropertyChanged();
    }
}

此外,在设置之前检查相等值是一个很好的模式:

...
set
{
    if (_observableTracks == value)
    {
        return;
    }
}

最后,RaisePropertyChanged会刷新所有属性,您可能只需要更改单个属性通知:

RaisePropertyChanged(() => ObservableTracks);