XamPivotGridGrouping 3 – Elements of a Pivot Grid
In my last blog, we built out a GroupingFlatDataSource which we can use to supply the data to our XamPivotGridGrouping control.Before we start to look at exactly how to go about that, let’s review the requirements of our project, and then take a look at the control itself, and the accompanying XamDataSelectorGrouping control, by examining some of the key elements in the control.
PROJECT REQUIREMENTS:
For our project, we are building a “Statistics” review tool to allow us to examine NFL player stats in a variety of different ways.Our focus, of course, is on the XamPivotGridGrouping.The basics of what we are being asked to do with the control are as follows:
- The Player Label must show both the Player name and an image of the player. Player name will be bold and font-size 16pts.
- The Team Label must show the team logo.
- The Position Label must show an image (silhouette) and abbreviated text regarding player position and will be font-size 24pts.
- Type (Pass, Rush, Def), Category (Yards, Score, TO) and Statistic columns must be static in their position and cannot be moved, or removed from the row listing. As a result, they should not be visible in the Rows section of the DataSelector nor should they be listed in the Field Selection area.
- Name, Team, Position must all be sortable (A-Z, Z-A) across the entire data set.
- The statistic results for Passer Rating, Avg Yards Passing, Avg Yards Rushing, Comp %, FG %, and XP% must be calculated based on the visible values relating to their formulas.
- These same fields will be highlighted with unique color schemes for the Row Headers and the Data Rows. All other statistical results will be white/white.
- The Data Selector Field Selection area will not list hierarchal data fields, but rather the specific field (dimension/measure) that is available, and will display a custom icon.
- The “Measures” area will be hidden, because for the purposes of this application, the only measure will be Statistic Total, and it should not be removable.
- The Control will be styled based on a specific scheme.
Before we start to dig into these requirements, let’s take a closer look at the control and its elements, so we start to get an understanding of what we will need to do to fulfill the stated requirements.
CONTROL ELEMENTS
There are two specific controls we need to examine to fulfill our required specs, the XamPivotGridGrouping control and the XamDataSelectorGrouping control.We’ve looked at what the XamPivotGridGrouping does in general, so let’s briefly overview the DataSelector as well.
The XamDataSelectorGrouping can greatly aid in the manipulation of your data at runtime.Its purposeis to allow users to select data.Given a DataSource (such as the one we built in the last blog), the XamDataSelectorGrouping can give you an interactive UI component to select a database to connect to (if you are using database data), a choice of which cube to extract data from (if you have multiple cubes), and a set of measures. When you have selected those a tree will be loaded with all the available dimensions with their respective hierarchies along with a list with all the available measures.
Figure 1 - XamDataSelectorGrouping
The XamDataSelectorGrouping along with the XamPivotGridGrouping controls are both required for us to effectively satisfy the project’s requirements.Let’s take a more detailed look at the elements of each one, starting with the XamPivotGridGrouping
XAMPIVOTGRIDGROUPING CONTROL
The image below divides the XamPivotGridGrouping into 4 sectors:
- Measures & Filters
- Row Headers
- Column Headers
- Data Cells
Figure 2 - XamPivotGridGrouping Sectors
Let’s examine these areas, and their function, briefly.
Measures & Filters
In this area you would normally see the measures (Total in this sample is the Measure) and any hierarchies which had been placed in the filter area, but which are not in any of the other sectors.Any hierarchy can only be placed within a single collection (Rows, RowsGroups, Columns, Filters, Measures) at any given time.Measures can be any numeric dimension of the data.When measures are added the XamPivotGridGrouping will show aggregate computation data for that specific slice.If no rows or columns are specified, the grid will display the sum of the dimension for all the items in the input data.For example, if we were to remove all the columns, our resultant grid would look like this:
Column Headers
When you add a hierarchy to the Columns area, a new slice with the current rows will be created.Adding more hierarchies to the same area dices the data.Unlike in the XamPivotGrid, the XamPivotGridGrouping shows the hierarchy tree in a horizontal structure.When you expand or collapse the columns you can drill down or up into the data.
Figure 3 - Column Headers
Notice that the Parent columns for 2012 and Week 1 are now empty.This means that all data items are assigned to either the First Half or Second Half hierarchies (or their child hierarchies).If there was a Pass Yards statistic that was set for Week 1, but was not assigned a value for any further hierarchies, that remainder would be displayed in Week 1.
Row Headers
Row headers, similar to Column headers, slice the data.The difference now is the data is being sliced based on the current columns.Adding more hierarchies to Rows dices the data.The hierarchy tree for rows is display horizontally as well, and can be confusing because people sometimes fail to understand that these are notdata cells, but rather is a grouping of hierarchical row headers.For example, in the image below, the row hierarchy is highlighted.
As you can see clearly, the Team, Position, Type, Category and Statistic Row headers are all children of the Name hierarchy.Remember our requirement that states “Name, Team, Position must all be sortable (A-Z, Z-A) across the entire data set.”?How do records in a hierarchical set sort?They sort within the confines of the hierarchy.There is an issue here which we will need to resolve.
Data Cells
Our last sector is the Data Cell sector.This sector shows the data computed as a result of the requested slice(s).In other words, this is a query to the data source, which has been defined by the hierarchies in the rows and columns, filtered by those hierarchies in the filters area (if any), and computed based on the measure(s).
You can place conditional formatting on the data cells by providing a template or style for each cell or you can allow the grid itself to display numeric format for the data.
Digging Deeper - XamPivotGridGrouping
The table below lists the key elements of each of these areas that we are going to need to concern ourselves with in order to meet the project requirements.
As you can see, there are a lot of moving parts to concern ourselves with.Let’s finish up this post by looking a little closer at the XamDataSelectorGrouping control.
XAMDATASELECTORGROUPING CONTROL
The image below divides the XamDataSelectorGrouping into 6 sectors:
- Hierarchies
- Filters
- Columns
- Rows
- Measures
- Row Groups
Figure 4 - Data Selector Sectors
Let’s examine these areas, and their function, briefly.
HIERARCHIES
This area can provide both a Database selector, and cube selector if you are connected to a database for data.Additionally, it provides the measures and dimensions that the grid will use.Each item in the list is a hierarchical structure.It can be modified to limit the items which appear in the list.
FILTERS
This area is a drop target for adding dimensions into the filters collection.
COLUMNS
This area is a drop target for adding dimensions into the columns collection.
ROWS
This area is a drop target for adding dimensions into the rows collection.
MEASURES
This area is a drop target for adding dimensions into the measures collection.
ROW GROUPS
This area is a drop target for adding dimensions into the row groups collection.The Rows Groups area allows the pivoted data rows to be grouped by the associated dimension, as shown below:
Figure 5 - Row Grouping
Digging Deeper - XamDataSelectorGrouping
The table below lists the key elements of each of these areas that we are going to need to concern ourselves with in order to meet the project requirements.
Even More Elements
In addition to those elements listed above, we have some other items which we will need to modify/style or behavorialize in order to satisfy the specifications.These are as follows:
FIELD CHOOSER |
|
| The Field Chooser is essentially a Popup control.It is sourced by a collection of AreaItemData objects and we will need to adapt this to fit some specific limitations. |
|
|
FILTERING CONTROL |
|
| The filtering control which also is essentially a popup control manages the ability to filter the hierarchies.Based on our requirements, we’ll need to modify this control and add sorting features here for the ability to Sort the associated column/row from A=>Z or Z=>A. |
Before I close this post out, let’s take the data source we created in my last post, and apply it to the XamPivotGridGrouping, and the XamDataSelector.
For demonstration purposes, my main window contains 3 user controls.The XAML is as follows:
<local:PivotGridGroupingMainx:Name="CustomGroupingPivotGrid"
DataContext="{BindingPath=DataContext,
RelativeSource={RelativeSource
AncestorType=Window}}"
Grid.Column="1"Grid.Row="1"
Visibility="{Binding
ElementNameShowCustomizedGroupingPivotGrid,
Path=IsChecked,
Converter={StaticResource
boolToVisibilityConverter}}"/>
<local:StandardPivotGrid x:Name="BasePivot"Grid.Column="1"Grid.Row="1"
DataContext="{Binding Path=DataContext,
RelativeSource={RelativeSource
AncestorType=Window}}"
Visibility="{Binding ElementName=ShowBasePivotGrid,
Path=IsChecked,
Converter={StaticResource
boolToVisibilityConverter}}"/>
<local:StandardGroupingView x:Name="GroupingViewPivot"
Grid.Column="1" Grid.Row="1"
DataContext="{Binding Path=DataContext,
RelativeSource={RelativeSource
AncestorType=Window}}"
Visibility="{Binding ElementName=ShowGroupingPivotGrid,
Path=IsChecked,
Converter={StaticResource
boolToVisibilityConverter}}"/>
As you can see here, I am passing the datacontext of the main window ( an object called GroupingMainViewModel) to the StandardGroupingView.DataContext via a binding.There are several ways I could do this, but this seemed the most effective for this sample.
Inside the StandardGroupingView there is a XamPivotGridGrouping item and a XamDataSelectorGrouping item.The XAML for these is also shown here:
<ig:XamPivotGridGrouping x:Name="BaseGroupingPivot" Grid.Row="1" Grid.Column="1"
DataSource="{Binding StatisticResultsDataSource}">
<ig:XamPivotGridGrouping.RowGroupBySettings>
<ig:RowGroupBySettings Indent="10">
ig:RowGroupBySettings>
<ig:XamPivotGridGrouping.RowGroupBySettings>
<ig:XamPivotGridGrouping.FieldChooser>
<ig:FieldChooser RowsItemsSource="{Binding RowsChooseList}"
MeasuresItemsSource="{Binding MeasuresChooseList}"
DisplayMemberPath="Caption"MeasuresGroupHeader="Measures"
RowsGroupHeader="Columns"
FieldUniqueNameMemberPath="ItemUniqueName"
FieldOrdinalMemberPath="Index" MaxHeight="500" Width="22"/>
<ig:FieldChooser.GroupHeaderTemplate>
<DataTemplate>
<Grid>
<ContentControl Margin="10, 2" Content="{Binding}"BorderThickness="0"
FontWeight="Bold"FontStyle="Italic" />
Grid>
DataTemplate>
ig:FieldChooser.GroupHeaderTemplate>
ig:FieldChooser><ig:XamPivotGridGrouping.FieldChooser>
ig:XamPivotGridGrouping>
<ig:Expander Grid.Column="2" Grid.Row="1" >
<ig:XamDataSelectorGrouping x:Name="dataSelector"
DataSource="{Binding DataSelectorFlatDataSource}">
<ig:XamDataSelectorGrouping>
Both the DataSelector and the PivotGrid are bound to a property of the GroupingMainViewModel:
publicGroupingFlatDataSource StatisticResultsDataSource
{
get
{
if(DataConstructor.OffensiveStaticstAllTeamsData != null)
{
return DataConstructor.OffensiveStaticstAllTeamsData;
}
DataConstructor.OffensiveStatisticsAllTeams();
return DataConstructor.OffensiveStaticstAllTeamsData;
}
}
publicGroupingFlatDataSource DataSelectorFlatDataSource
{
get
{
return DataConstructor.OffensiveStaticstAllTeamsData;
}
}
These properties both return the OffensiveStaticstAllTeamsData property from the DataConstructorViewModel, which is itself a property of the GroupingMainViewModel:
privatereadonlyDataConstructorViewModel m_data;
publicDataConstructorViewModel DataConstructor
{
get
{
return m_data;
}
}
So you can see, both the grid and the data selector are bound to the same data source.
Without making any further changes, if we run the sample, here is what our XamPivotGridGrouping will look like:
Figure 6 - Standard View of XamPivotGridGrouping
Where are our expanding group columns?This looks exactly like the XamPivotGrid!What’s going on!?!
There are a couple more settings we need to apply to the XamPivotGridGrouping to get us closer to what we expect.In the XAML we need to add the following to our declaration of the grid:
<ig:XamPivotGridGrouping x:Name="BaseGroupingPivot"
Grid.Row="1" Grid.Column="1"
DataSource="{Binding StatisticResultsDataSource}"
ParentInFrontForColumns="True"
UseColumnGroupByView="True">
UseColumnGroupByView must be set to true to enable the style of column grouping we want.And I am also setting ParentInFrontForColumns to assure that my parent column is at the front of my column hierarchy.
Now when we run it we get a little closer to our desired result:
Figure 7 - XamPivotGridGrouping View
This gives us a pretty solid idea of how much work we have in front of us.As I mentioned before, there are a lot of moving parts in the XamPivotGridGrouping and quite a few in the XamDataSelectorGrouping as well.Now that we have an idea of at least some of what’s involved, we can start the process of implementing our requirements and modifying the XamPivotGridGrouping control to fit what has been spec’d out.
In my next post we’ll look at how we can modify the XamDataSelectorGrouping items so that we can meet the specification of no hierarchies there, and we’ll also look at how to handle adding custom RowHeader Templates to add images and change font sizes for the Name, Team and Position Row Headers.