WPF & XAML – ListBoxes with a Grouping Capability

 

WPF & XAML – ListBoxes with a Grouping Capability

  • Comments 1

This tutorial is about learning: <ItemsControl.GroupStyle>

It is now possible to have a listbox with “grouping” capabilities.

The following example show an ItemsControl that is bound to an XmlDataProvider and the code-behind content that contains the logic to add and remove grouping.

When the check box is checked, the content of the ItemsControl is grouped by the Type attribute.

Each group is of type CollectionViewGroup.

The GroupStyle HeaderTemplate is specified so that it appears as a TextBlock that displays the Name of each the group. In this case, the Name is either Work or Home.

This blog entry is implementing the following sample:

http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.groupstyle.aspx

image

image

The next step is build this application and explain how it works.

(1) Start Visual Studio and select “File / New Project”

image

(2)  Select “WPF Application” and enter a project name, such as  “ItemsControlGroupStyle.” When you paste in the code, replace the whole window XAML code. Notice that you need to make sure you named your project ItemsControlGroupStyle.

image

Source code for Window1.xaml

<Window x:Class="ItemsControlGroupStyle.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Grouping Sample"
    Width="220" Height="550">
    <StackPanel>
        <StackPanel.Resources>
            <XmlDataProvider x:Key="myTasks" XPath="Tasks/Task">
                <x:XData>
                    <Tasks xmlns="">
                        <Task Name="Groceries" Priority="2" Type="Home">
                            <Description>Pick up Groceries and Detergent</Description>
                        </Task>
                        <Task Name="Laundry" Priority="2" Type="Home">
                            <Description>Do Laundry</Description>
                        </Task>
                        <Task Name="Email" Priority="1" Type="Work">
                            <Description>Email Clients</Description>
                        </Task>
                        <Task Name="Clean" Priority="3" Type="Work">
                            <Description>Clean my office</Description>
                        </Task>
                        <Task Name="Dinner" Priority="1" Type="Home">
                            <Description>Get ready for family reunion</Description>
                        </Task>
                        <Task Name="Proposals" Priority="2" Type="Work">
                            <Description>Review new budget proposals</Description>
                        </Task>
                    </Tasks>
                </x:XData>
            </XmlDataProvider>
        </StackPanel.Resources>
 
        <TextBlock Margin="12,5,5,0" FontSize="20" Text="My Task List"/>
        <CheckBox Margin="10,5,5,10" Checked="AddGrouping"
              Unchecked="RemoveGrouping">Group by task type</CheckBox>
        <ItemsControl Margin="10" Name="myItemsControl"
                  ItemsSource="{Binding Source={StaticResource myTasks}}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <DataTemplate.Resources>
                        <Style TargetType="TextBlock">
                            <Setter Property="FontSize" Value="18"/>
                            <Setter Property="HorizontalAlignment" Value="Center"/>
                        </Style>
                    </DataTemplate.Resources>
                    <Grid>
                        <Ellipse Fill="Silver"/>
                        <StackPanel>
                            <TextBlock Margin="3,3,3,0"
                         Text="{Binding XPath=@Name}"/>
                            <TextBlock Margin="3,0,3,7"
                         Text="{Binding XPath=@Priority}"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Control.Width" Value="100"/>
                    <Setter Property="Control.Margin" Value="5"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock FontWeight="Bold" FontSize="15"
                         Text="{Binding Path=Name}"/>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ItemsControl.GroupStyle>
        </ItemsControl>
    </StackPanel>
</Window>
 

Window1.xaml looks like this:

image

 

StackPanel.Resources contains XML data that is used to populate the listbox. There are 4 columns in each XML node (name, priority, type, description).

image

Notice that “Home” represents the top level grouping. Our “ItemsControl” points to “myTasks” for data. “myTasks” is just a <StackPanel> resource with XML data.

image

The <ItemsControl> control has pieces of XAML code:

  • ItemTemplate (Allows you to define how content is displayed)
  • ItemContainerStyle (Allows you to style the ItemsControl)
  • GroupStyle (Allows  you to group content)

The ItemTemplate section looks like this:

image

ItemContainerStyle

image

GroupStyle

image

GroupStyle allows us to easily specify a header template. Notice we are using “Name” as the “Path.” When we click on the Checkbox to tell WPF to group our list, then code executes below. The list is grouped according to “Type,” which is either “Home” or “Work.” 

image

Here is the code behind you will need for Window1.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace ItemsControlGroupStyle
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
        CollectionView myView;
        private void AddGrouping(object sender, RoutedEventArgs e)
        {
            myView = (CollectionView)CollectionViewSource.GetDefaultView(myItemsControl.ItemsSource);
            if (myView.CanGroup == true)
            {
                PropertyGroupDescription groupDescription
                    = new PropertyGroupDescription("@Type");
                myView.GroupDescriptions.Add(groupDescription);
            }
            else
                return;
        } 
 
        private void RemoveGrouping(object sender, RoutedEventArgs e)
        {
            myView = (CollectionView)CollectionViewSource.GetDefaultView(myItemsControl.ItemsSource);
            myView.GroupDescriptions.Clear();
        }
    }
}

All the source is available here:

image

There you have it, an example project that demonstrates grouping in a list.

  • Hi,

    Thanks a lot for sharing this application, I was searching the same.

    it is very simple to understand.

    I'm new in WPF so asking silly question.

    is there any way to set datasource dynamically instead of setting it statically?

    and instead of clicking on checkbox, how to set default grouping on "Type".

    I want to develop an application where i want to show county and its state, i want to bound the state to checkbox control so that user can select/unselect the state.

    e.g.

    <br> --country1

    <br>----state1

    <br>----state2

    <br>----state3

    <br> --country2

    <br>----state1

    <br>----state1

    Thanks in advance.

    -R

Page 1 of 1 (1 items)
Leave a Comment
  • Please add 8 and 7 and type the answer here:
  • Post