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

ListView not showing observablecollection, when a new collection is assigned to bound property, even though RaisePropertyChanged is called

我有一个绑定到 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 light 通知视图模型,将 属性 设置为不同的集合。

如您所见,我在集合中有项目,因此当我将新集合分配给 ObservableTracks 时 属性。 RaisePropertyChanged() 应该被调用,但是视图是 empty/shows 什么都没有。

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

需要调用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);

以下代码在我的机器上运行良好。

视图模型:

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?

如果没有,您能否分享一个失败的简短示例?