I would expose the first collection as an ObservableCollection<T>
and the second collection as a bare IEnumerable
. You can then use the default collection view to handle the events necessary to re-filter the sub collection.
class FilteredVM : ViewModelBase
{
public ObservableCollection<MyVM> Items { get; private set; }
public IEnumerable<MyVM> SubItems { get; private set; }
public FilteredVM()
{
this.Items = new ObservableCollection<MyVM>();
this.SubItems = Enumerable.Empty<MyVM>();
var view = CollectionViewSource.GetDefaultView(this.Items);
view.CurrentChanged += (sender, e) => { SetupFilter(); };
view.CollectionChanged += (sender, e) => { SetupFilter(); };
}
private void SetupFilter()
{
var view = CollectionViewSource.GetDefaultView(this.Items);
var current = view.CurrentItem;
if (current != null)
{
this.SubItems = this.Items.Where((vm,idx) => idx > view.CurrentPosition);
}
else
{
this.SubItems = Enumerable.Empty<MyVM>();
}
this.OnPropertyChanged("SubItems");
}
}
Alternatively, if you'd like to keep CollectionViewSource
out of your VM:
class FilteredVM : ViewModelBase
{
private MyVM selectedItem;
public MyVM SelectedItem
{
get { return this.selectedItem; }
set
{
if (value != this.selectedItem)
{
this.selectedItem = value;
this.OnPropertyChanged("SelectedItem");
this.SetupFilter();
}
}
}
public ObservableCollection<MyVM> Items { get; private set; }
public IEnumerable<MyVM> SubItems { get; private set; }
public FilteredVM()
{
this.Items = new ObservableCollection<MyVM>();
this.SubItems = Enumerable.Empty<MyVM>();
this.Items.CollectionChanged += (sender, e) => { this.SetupFilter(); };
}
private void SetupFilter()
{
if (this.SelectedItem != null)
{
var item = this.SelectedItem; // save for closure
this.SubItems = this.Items.SkipWhile(vm => vm != item).Skip(1);
}
else
{
this.SubItems = Enumerable.Empty<MyVM>();
}
this.OnPropertyChanged("SubItems");
}
}
Keep in mind this will require SelectedItem
to be properly bound in the View to the ViewModel. The first approach listed allows the SelectedItem
to be bound to anywhere (or nowhere).