Reputation: 1263
I have a ListView that is bound to an ObservableCollection. The problem I'm facing is that the view does not update, when I assign a new collection, even though I'm calling 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();
}
}
I'm using MVVM light to notify the viewmodel, to set the property to a different collection.
As you can see I have items in the collection, so when I assign a new collection to the ObservableTracks property. RaisePropertyChanged()
should be called, but the view is empty/shows nothing.
Any help is much appreciated. Thanks.
Upvotes: 0
Views: 1128
Reputation: 1346
The setter needs to be called in order to invoke the RaisePropertyChanged
method. If it is private, it cannot be called from external code. If Resharper flags it as not changing state, you should ignore it with a comment (though it should not flag it due to the method call).
private ObservableCollection<Track> _observableTracks;
public ObservableCollection<Track> ObservableTracks
{
get { return _observableTracks; }
set
{
_observableTracks = value;
RaisePropertyChanged();
}
}
Further, it is a good pattern to check the value for equality before setting:
...
set
{
if (_observableTracks == value)
{
return;
}
}
Finally, RaisePropertyChanged
makes all properties refresh, where you may only want the single property changed notification:
RaisePropertyChanged(() => ObservableTracks);
Upvotes: 0
Reputation: 1512
The following code is working fine on my machine.
ViewModel:
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; }
}
View:
<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>
Have you not forget to set the DataContext of your view?
If not could you share a short example that fails?
Upvotes: 1