DataGrid: Sequential Table to 2D Matrix

Jan 30, 2009 at 3:11 AM
Edited Jan 30, 2009 at 3:16 PM

I wonder if you have any ideas as far as how to best go about this:

I have an ObservableCollection that I have bound to my DataGrid.  All displays well, with each item in the ObservableCollection occupying one row in the DataGrid.  What I need now is to provide a 2D matrix view of that same data.  Let's say the ObservableCollection has 100 items, and I'd like to show a heatmap-like representation of these 100 items, but in a 10x10 grid.  I have easily programmatically mapped the ObservableCollection to a uniform grid, and set each item to a cell in the uniform grid, but I'd like to use the DataGrid instead, as that would allow for a much richer set of functions for the user experience.  Also, definitely would like to make use of XAML instead of having to programmatically set things up, if possible.

As such, for a prototype, I created a DataGrid with some dummy DataGridTemplateColumns, each using the same CellTemplate.

                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="01"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="02"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="03"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="04"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="05"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="06"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="07"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="08"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="09"/>
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="10"/>

The GridCellTemplate is also defined as follows, where the HeatCell control is a ViewBox-based UserControl, with its own dependency properties, one of which is a circle, Center, which I'd like to bind to a value in an item in my ObservableCollection (I know I'll need to use a Converter to convert the numeric value, Quality, in my item to a color in my HeatCell).
            <DataTemplate x:Key="GridCellTemplate">
                <controls:HeatCell x:Name="HeatCell"/>

I guess I'm stumped at this point, because I'm not sure how to go about setting up my XAML to dynamically bind the Quality value of, say, item #72 in my ObservableCollection, to the Center property of the HeatCell at row #7 col #2 of my DataGrid.

Any thoughts would greatly be appreciated...

Thanks so much for your time.


Jan 30, 2009 at 3:57 PM
I guess part of the reason I'm perplexed is, because all the columns use the same data template, how do you tell the HeatCell  data template where to go in the Data Grid...


Jan 31, 2009 at 12:32 AM
Edited Jan 31, 2009 at 12:33 AM
Let me simplify the problem a little, in case anybody can have a crack at this.  The XAML below does the following:
  • Defines an XmlDataProvider just for dummy data
  • Creates a DataGrid with 10 columns
    • each column is a DataGridTemplateColumn using the same CellTemplate
  • The CellTemplate is a simple TextBlock bound to an XML element
If you run the XAML below, you will find that the DataGrid ends up with 5 rows, one for each book, and 10 columns that have identical content (all showing the book titles).  However, what I am trying to accomplish, albeit with a different data set, is that in this case, I would end up with one row, with each book title appearing in a single cell in row 1, occupying cells 0-4, and nothing in cells 5-9.  Then, if I added more data and had 12 books in my XML data source, I would get row 1 completely filled (cells covering the first 10 titles) and row 2 would get the first 2 cells filled.

Can my scenario be accomplished primarily in XAML, or should I resign myself to working in the code behind?  Any guidance would greatly be appreciated.  Thanks so much.

    d:DesignWidth="600" d:DesignHeight="400"  >
        <XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">
                <Inventory xmlns="">
                        <Book ISBN="0-7356-0562-9" Stock="in" Number="9">
                            <Title>XML in Action</Title>
                            <Summary>XML Web Technology</Summary>
                        <Book ISBN="0-7356-1370-2" Stock="in" Number="8">
                            <Title>Programming Microsoft Windows With C#</Title>
                            <Summary>C# Programming using the .NET Framework</Summary>
                        <Book ISBN="0-7356-1288-9" Stock="out" Number="7">
                            <Title>Inside C#</Title>
                            <Summary>C# Language Programming</Summary>
                        <Book ISBN="0-7356-1377-X" Stock="in" Number="5">
                            <Title>Introducing Microsoft .NET</Title>
                            <Summary>Overview of .NET Technology</Summary>
                        <Book ISBN="0-7356-1448-2" Stock="out" Number="4">
                            <Title>Microsoft C# Language Specifications</Title>
                            <Summary>The C# language definition</Summary>
                        <CD Stock="in" Number="3">
                            <Title>Classical Collection</Title>
                            <Summary>Classical Music</Summary>
                        <CD Stock="out" Number="9">
                            <Title>Jazz Collection</Title>
                            <Summary>Jazz Music</Summary>

        <DataTemplate x:Key="GridCellTemplate">
                    <Binding XPath="Title"/>


    <Grid x:Name="LayoutRoot">
        <custom:DataGrid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsSynchronizedWithCurrentItem="True"
        Background="{DynamicResource WindowBackgroundBrush}" HeadersVisibility="All" RowDetailsVisibilityMode="Collapsed"
        SelectionUnit="CellOrRowHeader" CanUserResizeRows="False" GridLinesVisibility="None" RowHeaderWidth="35" AutoGenerateColumns="False"
        CanUserReorderColumns="False" CanUserSortColumns="False">
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="01" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="02" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="03" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="04" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="05" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="06" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="07" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="08" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="09" />
                <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="10" />
                <Binding Source="{StaticResource InventoryData}" XPath="Book"/>