ReactiveUI Goodies–IReactiveDerivedList Grouping

In my 2 previous posts ReactiveUI Goodies–IReactiveDerivedList Filtering 1 and ReactiveUI Goodies–IReactiveDerivedList Filtering 2 I demonstrated how CreateDerivedList(), a method provided by ReactiveList can be used to implement filter scenarios. In this post I would like to explore how we can utilize CreateDerivedList() to archive dynamic grouping in a ListView. Grouping is often used to bring give the user a better overview of the displayed data. E.g. Grouping names by their first letter. In our Todo list example a useful grouping would be by completed and uncompleted tasks. Before we can put our derived list grouping implementation in place we have to make some changes to the previous demo code. The TodoItemViewModel class now exposes a IsDone property we can bind to and raises the INPC event when changed.

public bool? IsDone
{
    get { return Item.Done; }
    set { Item.Done = value; this.RaisePropertyChanged(); }
}

Since we no longer want to show all items in one block we need to introduce a ItemGroup class.

public class ItemGroup : ReactiveObject
{
    private IReactiveDerivedList<TodoItemViewModel> _items;
    private string _title;
 
    public string Title
    {
        get { return _title; }
        set { this.RaiseAndSetIfChanged(ref _title, value); }
    }
 
 
    public IReactiveDerivedList<TodoItemViewModel> Items
    {
        get { return _items; }
        set { this.RaiseAndSetIfChanged(ref _items, value); }
    }
}

As you can see, the group now carries our IReactiveDerivedList of Todo item ViewModels and in addition a title that will be displayed above each group. Our MainViewModel needs to be changed accordingly by declaring a list of our new group objects instead of the Todo items itself.

With these changes in place we can now declare the grouping:

_rootList = new ReactiveList<TodoItemViewModel>();
_rootList.ChangeTrackingEnabled = true;
 
Groups = new ReactiveList<ItemGroup>();
 
Groups.Add(new ItemGroup { Title = "Todo", Items = _rootList.CreateDerivedCollection(x => x, x => x.IsDone == false, (x, y) => x.Item.DueDate.CompareTo(y.Item.DueDate)) });
Groups.Add(new ItemGroup { Title = "Completed Tasks", Items = _rootList.CreateDerivedCollection(x => x, x => x.IsDone == true, (x, y) => x.Item.DueDate.CompareTo(y.Item.DueDate)) });

Like in our last demo we enable change tracking for our root list of groups. This enables being moved between the done and not-done group as the user marks them. Then we create the two groups based on their IsDone property by defining the filter for the derived list.

The final result is a beautiful grouping that changes as the user checks the items.

TodoDemo

Please find the example code at https://github.com/bitdisaster/practicalcode

Happy coding!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s