Click here to Skip to main content
15,881,600 members
Articles / Desktop Programming / WPF

MVVM ListBox Grouping

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
18 Jan 2012CPOL2 min read 27.7K   2   1
This is an example to show the use of MVVM in creating a grouping listbox.

This is an example to show the use of MVVM in creating a grouping listbox. The example shows a list of employees with their job title, name and grade. I’ve defaulted to grouping by Job Title and supplied to buttons on the window to allow you to toggle the grouping between job title and grade. This is to demonstrate the dynamic behaviour of the grouping in the view model.

First let’s start with the EmployeeViewModel:

C#
public class EmployeeViewModel
{
    public string Name
    {
        get;
        set;
    }
    public string JobTitle
    {
        get;
        set;
    }
    public string Grade
    {
        get;
        set;
    }
}

Nothing to strenuous here, just a POCO.

Followed by the MainViewModel:

C#
public class MainViewModel
{
    private ObservableCollection employees = new ObservableCollection();
    private ObservableCollection groupingColumns = new ObservableCollection();
    public MainViewModel()
    {
        var view = CollectionViewSource.GetDefaultView(Employees);
        GroupByJobTitleCommand = new GroupByCommand(GroupingColumns, "JobTitle");
        GroupByGradeCommand = new GroupByCommand(GroupingColumns, "Grade");
        GroupingColumns.CollectionChanged += (s, e) =>
        {
            view.GroupDescriptions.Clear();
            foreach (var groupName in GroupingColumns)
            {
                view.GroupDescriptions.Add(new PropertyGroupDescription(groupName));
            }
        };
    }
    public ObservableCollectionEmployees
    {
        get { return this.employees; }
    }
    public ObservableCollectionGroupingColumns
    {
        get { return this.groupingColumns; }
    }
    public ICommand GroupByJobTitleCommand
    {
        get;
        private set;
    }
    public ICommand GroupByGradeCommand
    {
        get;
        private set;
    }
}

And the GroupByCommand that will allow us to switch the grouping field:

C#
public class GroupByCommand : ICommand
{
    private ObservableCollection groupingColumns;
    private string groupName;
    public GroupByCommand(ObservableCollectiongroupingColumns, string groupName)
    {
        this.groupingColumns = groupingColumns;
        this.groupName = groupName;
    }
    public bool CanExecute(object parameter)
    {
        return true;
    }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {
        this.groupingColumns.Clear();
        this.groupingColumns.Add(this.groupName);
    }
}

Followed by the XAML:

XML
<Grid Grid.IsSharedSizeScope="True">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox ItemsSource=’{Binding Employees}’>
<ListBox.GroupStyle>
<x:Static Member=’GroupStyle.Default’ />
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="col1" Width="200"/>
<ColumnDefinition SharedSizeGroup="col2" Width="200"/>
<ColumnDefinition SharedSizeGroup="col3" Width="200"/>
</Grid.ColumnDefinitions>
<TextBlock Text=’{Binding Name}’/>
<TextBlock Text=’{Binding JobTitle}’ Grid.Column="1"/>
<TextBlock Text=’{Binding Grade}’ Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Command="{Binding GroupByJobTitleCommand}">Group By Job Title</Button>
<Button Command="{Binding GroupByGradeCommand}">Group By Job Grade</Button>
</StackPanel>
</Grid>

The XAML here is pretty straightforward, but a couple of points:

  1. We’ve used ListBox.GroupStyle to tell the list box we want group styling.
  2. The IsSharedSizeScope on the out Grid and SharedSizeGroup on the column definitions have been used to make each row line up and give us the appearance of a more traditional grid with the data in columns.

And finally, the code behind (dirty words I know, but it’s just setting up the DataContext):

C#
public MainWindow()
{
    InitializeComponent();
    var mainViewModel = new MainViewModel();
    mainViewModel.Employees.Add(new EmployeeViewModel() { 
      Name = "Blogs, Fred", JobTitle = "Programmer", Grade = "1" });
    mainViewModel.Employees.Add(new EmployeeViewModel() { 
      Name = "Gates, Bill", JobTitle = "Project Manager", Grade = "1" });
    mainViewModel.Employees.Add(new EmployeeViewModel() { 
      Name = "Jobs, Steve", JobTitle = "Analyst", Grade = "2" });
    mainViewModel.Employees.Add(new EmployeeViewModel() { 
      Name = "Smith, John", JobTitle = "Programmer", Grade = "2" });
    mainViewModel.Employees.Add(new EmployeeViewModel() { 
      Name = "Davis, Mavis", JobTitle = "Project Manager", Grade = "3" });
    this.DataContext = mainViewModel;
}

So we’ve basically set up a list of employees in the MainViewModel and attached an instance of it as our DataContext. In this view model, we have a couple of commands for actually doing the grouping. By default we have a normal list of employees and then selecting either of the buttons will group them by that property.

I believe this is a more MVVM approach to doing grouping in a list box (or anything that support grouping) and keeps the logic in the view model. I’ve seen other examples, but most of them use the XAML to control the grouping and usually have fixed data sets in XAML declared as static resources.

The styling of this leaves a lot to be desired and you can’t expand or collapse the groups. To see how this is done, I suggest you look at Karl Shifflett’s example for some inspiration.

You can download the code from this article here.

This article was originally posted at http://tap-source.com?p=172

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) NoProblem Software Ltd
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionLink not usable Pin
Member 1130156411-Feb-20 17:03
Member 1130156411-Feb-20 17:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.