Component One Silvelright FlexGrid Tip 6 (Group Header customatization)

Continuing our previous example of using Data Table to create grid on the fly, we will add one more column for grouping purpose to produce an output like the following

image

This also shows how to do grouping when using DataTable in Silverlight. So lets look at the code which generates the data to populate the grid and also grouping.

private void LoadData()
{
   _dataTableWithData = new DataTable();
   _dataTableWithData.Columns.Add("ID");
   _dataTableWithData.Columns.Add("Name");
   _dataTableWithData.Columns.Add("Age");
   _dataTableWithData.Columns.Add("Group");
   for (int i = 0; i < 10; i++)
   {
      int grp = ((i>3)?1:i);
      _dataTableWithData.Rows.Add(i, "Name" + i.ToString(), i, grp);
   }
   var gd = _dataTableWithData.DefaultView.GroupDescriptions;
   gd.Add(new PropertyGroupDescription("Group"));
}

As you can see, we create group row as we would create normal group row in FlexGrid. When we run the code it creates the groups properly but I do not like the default group header information in the group row. It shows

Group: value (number item)

What if I do not want to show the number of item in the parenthesis, how would I go about not showing it? That is what we are going to see today. This is easily achieved by using a custom converter for GroupHeaderConverter. Here is the custom header converter that we need to do to show only ‘Group : GroupName’

public class GroupHeaderConverter:IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
     var group = value as CollectionViewGroup;
     if (group != null)
        return string.Format("Group: {0}", group.Name);
     return null;
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
   throw new NotImplementedException();
  }
}

As you can see it is very simple value converter. For every group, we check and see if the row is a group row and if it is, then just return “Group: ” + group.name. One thing you need to make sure to use, the first type conversion. Make sure you you get the group information of type CollectionViewGroup. With that you get all group related information. Which is very powerful if you want to handle grouping completely different. Now that we have a group header converter, we need to let flex grid know to use this converter for the group headers by

_flex.GroupHeaderConverter = new GroupHeaderConverter();
That's all about it, now if you run the program you get the group header the way we wanted it to be.

image


Not only we saw how to customize the group header, we also saw how to do grouping in Data Table. Thanks Bernardo for the pointers.

Advertisements

Component One Silverlight FlexGrid Tip 4 (Group Aggregate)

In the previous blog we looked at performing simple grouping. While grouping is interesting, most of the time you group them and to see some king of group aggregation. Component One provides following group aggregates to be performed on any given column definition.

  1. Average
  2. Count
  3. Maximum
  4. Minimum
  5. None
  6. Range
  7. Std
  8. StdPop
  9. Sum
  10. Var
  11. VarPop

Lets all of these in action, we will take our favorite Person class we used in the previous example for simple grouping and add all aggregation on the Age and see what does it create

<c1:C1FlexGrid Name="flexGrid" ItemsSource="{Binding PeopleCollection}" AutoGenerateColumns="False" >
   <c1:C1FlexGrid.Columns>
     <c1:Column Binding="{Binding Name}"/>
     <c1:Column Binding="{Binding Age}" Header="Average" GroupAggregate="Average"/>
     <c1:Column Binding="{Binding Age}" Header="Count" GroupAggregate="Count"/>
     <c1:Column Binding="{Binding Age}" Header="Maximum" GroupAggregate="Maximum"/>
     <c1:Column Binding="{Binding Age}" Header="Minimum" GroupAggregate="Minimum"/>
     <c1:Column Binding="{Binding Age}" Header="None" GroupAggregate="None"/>
     <c1:Column Binding="{Binding Age}" Header="Range" GroupAggregate="Range"/>
     <c1:Column Binding="{Binding Age}" Header="Std" GroupAggregate="Std"/>
     <c1:Column Binding="{Binding Age}" Header="StdPop" GroupAggregate="StdPop"/>
     <c1:Column Binding="{Binding Age}" Header="Sum" GroupAggregate="Sum"/>
     <c1:Column Binding="{Binding Age}" Header="Var" GroupAggregate="Var"/>
     <c1:Column Binding="{Binding Age}" Header="VarPop" GroupAggregate="VarPop"/>
   </c1:C1FlexGrid.Columns>
</c1:C1FlexGrid>

 

All of them are self explanatory on what it does. The default behaviour is None. If you do not have a group aggregate for a column, it will default it to None so that no group aggregation will not happen.

image