New DataGrid for WPF

Times are changing and so is Studio for WPF. In addition to the new C1FlexGrid control we've just ported the existing C1DataGrid from Studio for Silverlight to WPF in the 2010 v2 release. Back in 2007 we introduced the original C1DataGrid control for WPF which was heavily designer inspired. It had many visual and interactive features such as drag-and-drop grouping, a carousel view, built-in themes based on Microsoft Office products, and Excel-like horizontal and vertical splits. It was ahead of its that time.

But now, we here at ComponentOne have decided to port all of our Silverlight controls to the WPF platform so we can deliver more controls with better performance and more functionality in much less time. This created a conflict because we already had a "C1DataGrid" (and C1Scheduler) in Studio for WPF. We ultimately decided to stick with the original Silverlight versions and thus move the old WPF versions to legacy, maintenance only mode. By porting controls from Silverlight to WPF we also strive to have more compatibility among our different platform studios. We now have C1DataGrid in Silverlight and WPF, we have C1FlexGrid in WinForms, Silverlight and WPF. We believe this not only improves the value of Studio Enterprise, but it creates a clearer migration path for components. The rest of this post goes over the differences between the old and new WPF C1DataGrid controls. Even if you haven't ever used the old grid this post is also a great getting started guide for the new one. But to sum up the rest of this blog post: The new C1DataGrid is faster, more flexible, more feature-packed, and is more code compatible to both the Microsoft DataGrid and of course, the C1DataGrid for Silverlight.


The new C1DataGrid is found in C1.WPF.DataGrid. The old C1DataGrid is found in C1.WPF.C1DataGrid.

.NET Compatibility

The old C1DataGrid is supported in pure .NET 3.0 and higher. The new C1DataGrid is supported in .NET 3.5 and higher.

User Interactions

The new C1DataGrid offers most of the same interactive features, as well as simple properties which enable you to restrict permission on any of these actions. In the old version, these properties begin with "Allow" (i.e. AllowEdit), whereas in the new version they begin with "CanUser" (i.e. CanUserEdit). The key interaction difference is the old C1DataGrid supports splits, both horizontal and vertical. The new C1DataGrid does not support splits but instead supports frozen columns.

User Interaction old C1DataGrid new C1DataGrid
Add Rows X X
Delete_Rows X X
Edit_Rows X X
Filter X X
Freeze Columns   X
Group X X
Reorder Columns X X
Resize Columns X X
Resize Rows   X
Sort X X
Splits X  

Data Binding

The new C1DataGrid control can be bound to any object that implements the IEnumerable interface (such as XmlDataProvider, ObjectDataProvider, DataSet, DataView, and so on). You can use the ItemsSource property to bind the grid.


Both C1DataGrids request all data from the datasource, however the UI representing the data generates only the visible items on demand. Below are test results showing time and memory consumption once populated with a large number of items. Each result is the average of three tests on a grid with 10 columns.

Number of Rows Old_C1DataGrid New_C1DataGrid Improvement
500,000 rows      
  Load Time 1226.1226 ms 85.675 ms ~_1 second faster
  Memory Consumption 37334425.33 bytes 22516 bytes ~37 MB less
1,000,000 rows      
  Load Time 2905.623 ms 86.342 ms ~_3 seconds faster
  Memory Consumption 75383612.00 bytes 31386.666 bytes ~75 MB less

The new C1DataGrid is about 1-3 seconds faster (95%) at loading a large number of rows and consumes massively less memory than the old C1DataGrid! This makes the new grid more responsive to user interactions such as scrolling, resizing, column reordering, etc; however both grids showed roughly equal results when tested for sorting because the work there is done on the data itself.


Both C1DataGrids support automatic and explicit column generation and the AutoGenerateColumns (Boolean) property.

Column Types

The old C1DataGrid has one standard column type, which can be customized with special data templates. There is built-in support for displaying checkboxes for Boolean values. The new C1DataGrid offers more built-in column types:

  • DataGridBoundColumn - bound to a data property
  • DataGridCheckBoxColumn - hosts Boolean content
  • DataGridComboBoxColumn - hosts enumerable content
  • DataGridDateTimeColumn - bound to a data property representing System.DateTime
  • DataGridImageColumn - hosts image content
  • DataGridNumericColumn - hosts numeric content
  • DataGridTemplateColumn - hosts custom user templates
  • DataGridTextColumn - hosts textual content

The DataGridTemplateColumn can be used to host any further special editors needed for a grid cell. Plus, we include custom classes implementing several more, less-common, column types (masked text, multi-line text, color, and composite). Example of explicit column declaration (new DataGrid):

<c1DataGrid:C1DataGrid x:Name="grid" AutoGenerateColumns="False">
        <c1DataGrid:DataGridBoundColumn Binding="{Binding LastName, Mode=TwoWay}" SortMemberPath="LastName" FilterMemberPath="LastName"/>
            <c1DataGrid:DataGridCheckBoxColumn Binding="{Binding IsAvailable, Mode=TwoWay}" SortMemberPath="IsAvailable" FilterMemberPath="IsAvailable"/>
        </c1DataGrid:C1DataGrid.Columns> </c1DataGrid:C1DataGrid>

Selection Mode

The old C1DataGrid has no special property or simple way for controlling selection behavior. The new C1DataGrid exposes a simple SelectionMode property with more selection modes than even the default WPF DataGrid. New C1DataGrid.SelectionMode options:

  • MultiColumn
  • MultiRange
  • MultiRow
  • None
  • SingleCell
  • SingleColumn
  • SingleRange
  • SingleRow

Retrieving Data

The new DataGrid has made it a lot simpler to access and retrieve values of any given cell. With the CurrentCell, CurrentRow and CurrentColumn properties you can access the selected items directly. Or if you want a cell that is not selected, for example, use the GetCellFromPoint method to get which cell is under the mouse pointer. The following code retrieves the text of the currently selected cell:

DataGridCell cell = c1DataGrid1.CurrentCell; MessageBox.Show(cell.Text);

To set the value of a cell you should make the change on the underlying dataitem. C1DataGrid will reflect these changes so long as the data item implements INotifyPropertyChanged.


The old C1DataGrid has a built-in filter bar. You can turn this feature on by simply setting the FilterBarVisibility property. The new C1DataGrid has built-in Excel-like filtering. This is turned on by default, however it's controlled by the CanUserFilter property.

Implementing a Filter Bar

To reproduce the built-in filter bar functionality of the old C1DataGrid, you can take advantage of the TopRows (and BottomRows) collection templates, as well as row freezing. Below is the XAML markup showing the TopRows collection. To freeze this row and prevent it from scrolling we also set the FrozenTopRowsCount property to "1". Below is a full sample implementing a custom filter-bar row.

<c1DataGrid:C1DataGrid x:Name="c1DataGrid1" FrozenTopRowsCount="1">  <c1DataGrid:C1DataGrid.TopRows>  <local:DataGridFilterRow />  </c1DataGrid:C1DataGrid.TopRows> </c1DataGrid:C1DataGrid>

Download Full DataGridFilterRow Sample


Grouping the data rows on similar values is a very convenient and quick analysis tool expected of any datagrid. The new C1DataGrid has built-in drag and drop grouping capabilities. You can turn this feature on or off with the CanUserGroup property. When True, a region appears above the column headers allowing users to drag any column header to group the data by that field. Users can rearrange and cancel any grouping.

Column Totals

Column totals, grouping aggregates, subtotals, row summaries...whatever you want to call it, you can accomplish this using the new C1DataGrid. The old C1DataGrid is capable of displaying a totals bar below the grid showing column totals. The new C1DataGrid supports displaying calculated totals on grouped rows and a grand totals row at the top or bottom of the grid using the TopRows and BottomRows feature. For example, we can display a grand totals row at the bottom of the grid by adding a DataGridSummaryRow in the BottomRows collection. To freeze this row and prevent it from scrolling we also set the FrozenBottomRowsCount property to "1":

<c1DataGrid:C1DataGrid x:Name="grid" FrozenBottomRowsCount="1" LoadedRowPresenter="grid_LoadedRowPresenter">  <c1grid:C1DataGrid.BottomRows>  <local:DataGridSummaryRow UpdateWhenFilters="True" />  </c1grid:C1DataGrid.BottomRows> </c1DataGrid:C1DataGrid>

Download Full DataGridSummaryRow Sample

Conditional Formatting

The old C1DataGrid requires you to write control templates in XAML with triggers just to apply a simple formatting style (such as set the background color to red for values matching a certain criteria). With the new C1DataGrid, this is handled best in code. In the LoadedCellPresenter event, you can run your logic and apply your formatting. In this small example we apply a red background brush to all products with a list price higher than 40.00.

private void c1DataGrid1_LoadedCellPresenter(object sender, DataGridCellEventArgs e)
 if (e.Cell.Column.Name == "ListPrice")
 DataRowView drv = (DataRowView)e.Cell.Row.DataItem;
 Decimal listPrice = (Decimal)drv["ListPrice"];
 if (listPrice > 40)
 e.Cell.Presenter.Background = Brushes.Red;

Customized Item/Multi-Line Rows

The old C1DataGrid is great for displaying multi-line rows while still supporting common grid features like sorting, filtering and grouping. The same effect can be achieved with the new C1DataGrid by creating a row DataTemplate. See the sample "Custom Rows" for full implementation details.

<DataTemplate x:Key="TemplateRow">  <Grid Height="50">
 <RowDefinition />
 <RowDefinition />
        <TextBlock Text="{Binding Name, Mode=OneWay}" />
        <TextBlock Text="{Binding ProductNumber, Mode=OneWay}" Grid.Row="1" />
        ...    </Grid> </DataTemplate>


To create a hierarchical grid using the new C1DataGrid, the solution is to wire up a nested child grid in the RowDetails template of the parent grid. See the article below for full instructions on how to create this using the new C1DataGrid which shares the same object model in Silverlight and WPF. 


The old C1DataGrid includes 13 built-in themes and further customization requires a template override. The new C1DataGrid features ClearStyle technology, and there are several exposed brushes for quick and flexible styling. This small amount of XAML can completely restyle the new C1DataGrid without having to customize the control's template. Each property below is actually a Brush, so you can create complex gradients and textured brushes rather than just supplying solid colors.

<Style x:Key="MyGridStyle" TargetType="c1dg:C1DataGrid">
    <Setter Property="Background" Value="#FF262626"/>
    <Setter Property="BorderBrush" Value="#FF595959"/>
    <Setter Property="HorizontalGridLinesBrush" Value="#FF595959"/>
    <Setter Property="MouseOverBrush" Value="#FF77933C"/>
    <Setter Property="RowBackground" Value="#FFFFFFFF"/>
    <Setter Property="AlternatingRowBackground" Value="#FFD9D9D9"/>
    <Setter Property="SelectedBrush" Value="#FFC3D69B"/>
    <Setter Property="VerticalGridLinesBrush" Value="#FF595959"/>
    <Setter Property="Foreground" Value="#FFFFFFFF"/>
    <Setter Property="RowForeground" Value="#FF000000"/>
    <Setter Property="AlternatingRowForeground" Value="#FF000000"/> </Style>

Excel Export

One of the key features of the old C1DataGrid is the ability to take the grid data and output it to an Excel file. This feature is not built-into the first release of the new DataGrid; however we provide sample code for accomplishing this task and exporting to Excel XML format. Take a look at this sample for full code. Download Full DataGridExcelExport Sample

The new C1DataGrid does not support card and carousel views. We plan to reintroduce the C1CarouselPanel to Studio for WPF in a future release to be used as a general carousel items control.

Greg Lutz

comments powered by Disqus