What is the best way to display multidimensional data in WPF? I won't know the size/shape of the data until runtime. Ideally I would like to use databinding but that is not a strict requirement. I was thinking some sort of grid but I don't know how to dynamically bind to the data and have it figure out the number of rows and columns. Suggestions and examples please?
-
Clarification: By size/shape I mean MxN and not circles/squares. I am dealing with array data that can be anywhere from 1D to 6D that I want to display in a table-like fashion (more the 2D should just be displayed successively in the "table"). I am not dealing with jagged arrays or sparse matrices. My question is really, what is a good control to use to implement this "table". – KrisTrip Apr 21 '10 at 13:18
-
Another Clarification: I also need it to act somewhat like an excel table. For example, I need to be able to select a rectangle of data to copy/paste from/to. – KrisTrip Apr 21 '10 at 14:03
-
You know, don't count on a huge response if you don't give points for correct answers to your question (there's no doubt these are correct) :) – Piotr Justyna Apr 21 '10 at 14:29
-
I haven't had a chance to test them out yet. I will certainly be giving points and selecting a best answer once I get a chance to try it out. Unfortunately I can really only work on this in the evening as it is not part of my day job. – KrisTrip Apr 21 '10 at 15:34
5 Answers
Sounds as though you want an Excel-like interface for 2D arrays with editing capability. For the other dimensions, you will have to come up with tabs or a series of comboboxes.
Check out the WPF Toolkit DataGrid. There is an option for auto generate columns. Experiment with that.
However, you will have some code behind to deal with the other dimensions since the Datagrid can only represent 2D data.
Corey
Edit: (04/28/2010) Here is a working solution.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using Microsoft.Windows.Controls;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public List<List<object>> TheData { get; set; }
public MainWindow()
{
InitializeComponent();
// Generate some random data
Random r = new Random();
TheData = new List<List<object>>
{
new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) },
new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) },
new List<object> { r.Next(100), r.Next(100), r.Next(100) },
new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) },
new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) },
new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100), r.Next(100) }
};
// Now bind data to the grid
// We need at least one element
if (TheData.Count > 0)
{
// Find the longest row so we create enough columns
var max = TheData.Max(c => c.Count);
for (var i = 0; i < max; i++)
{
TheGrid.Columns.Add(
new DataGridTextColumn
{
Header = string.Format("Column: {0:00}", i),
Binding = new Binding(string.Format("[{0}]", i))
}
);
}
}
TheGrid.ItemsSource = TheData;
}
}
}
The XAML...
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="GridTest">
<Grid x:Name="LayoutGrid">
<toolkit:DataGrid x:Name="TheGrid"
AutoGenerateColumns="False"
IsReadOnly="False"
CanUserAddRows="False"/>
</Grid>
Some thing to note about this approach, if you allow editing of data and allow jagged arrays, you will need to new up a new List on the short rows.
As far as > 2D data, you will need some sort of option to select another dimension since the datagrid can only represent 2D data.

- 42
- 3
-
This is exactly what I am talking about! WPF Toolkit DataGrid looks promising. – KrisTrip Apr 22 '10 at 13:21
I think the best solution for you is to just use TreeView :) if you're using MVVM, this is the most brilliant tutorial regarding TreeView i have found: http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx
Please keep me informed if you need more info.

- 4,888
- 3
- 25
- 40
-
TreeView is not a good solution for me. It is array data that needs to be displayed in a table-like fashion (like an excel grid or something) – KrisTrip Apr 21 '10 at 13:12
-
In this case I have 2 alternatives for you. First: you can template tree view to look just like a table (I'm insisting on using TreeView, because it's perfectly easy to bind to hierarchical data structures). Second: you can use just a regular grid with bound rows/columns or a listbox with bound, templated listbox items. If I were your, I would pick the first solution :) Regards, Piotr. – Piotr Justyna Apr 21 '10 at 13:27
-
I also need it to act like an excel table. For example, I need to be able to select a rectangle of data to copy/paste from/to. I don't think a TreeView can handle this type of functionality. – KrisTrip Apr 21 '10 at 14:02
-
You'd be surprised ;) I have a feeling, that this question should be asked again but under a different title (eg how can a mimic Excel bahaviour in my WPF application). I found something for you, you can sheck out a free trial: http://www.devexpress.com/Products/NET/Controls/WPF/Grid/filter.xml I'm afraid they used a regular Grid to implement it. – Piotr Justyna Apr 21 '10 at 14:27
I've done something similar where the data was a List or Lists, or an array of arrays. Not sure how locked in you are to using multidimensional arrays versus this method for "grid like" data.
Here's how I bound against the List of Lists.
<Resources>
<DataTemplate x:Key="GridDtInner">
<TextBlock Text="{Binding YourProperty}"/>
</DataTemplate>
<DataTemplate x:Key="GridDtOuter">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource GridDtInner}" />
</DataTemplate>
</Resources>
<ItemsControl ItemTemplate="{DynamicResource GridDtOuter}" ItemsSource="{Binding YourList, Mode=Default}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Obviously I've snipped things for brevity but I hope this makes sense.
Regards,
Mike McAulay

- 11
- 2
I've done something very similar, but most likely in a completely different industry than what you're working in.
When you say size / shape of data, I assume that you're not literally talking about circles vs. squares, but instead are saying that you've got an NxM matrix of data and you don't know what N and M are until runtime. I also assume that you want to display some kind of text in each cell of the NxM matrix.
Please note that the following XAML has been modified from my code and isn't tested, but I wanted to give you a basic idea of how I did it.
<ListBox Width="300" Height="300" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding Cells}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="Auto" Height="Auto" ItemWidth="{Binding CellBoundary}" ItemHeight="{Binding CellBoundary}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Width="{Binding CellDiameter}" Height="{Binding CellDiameter}" Text="{Binding CellValue}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I changed the ListBox's ItemsPanel to just be a ListBox. So as long as you have an NxM matrix (it can be sparse, too), you treat is as a vector with NxM cells. Each cell is effectively an item in the ListBox.
Next, you set the DataTemplate for each ListBox item to just be a TextBlock, where the TextBlock's size is databound and the value displayed is in the CellValue
member of your Cells, which is an ObservableCollection<double>
or similar, databound to Cells
.
The only thing you have to do at this point in code behind is to figure out what N and M are, and do the necessary math to calculate the size of the ListBox (could be inside of a ViewBox to make it scale), so that the values are displayed accordingly. Obviously, you'll need to change my hardcoded values to something databound as well.
This approach seems the simplest for me to wrap my brain around, so that's why I've been using it for my stuff.
I should also add that in order to do a sparse matrix, you'll set CellValue to 0, but you could also use a DataTrigger to make the TextBlocks invisible if the value is 0, thus giving the illusion of a sparse matrix.

- 14,618
- 13
- 91
- 145
I just found the DataGrid in the WPF Toolkit which is showing some potential. It at least allows selection of single cells. I will post code when I figure out the databinding.
http://wpf.codeplex.com/releases/view/40535
http://windowsclient.net/wpf/wpf35/wpf-35sp1-toolkit-datagrid-feature-walkthrough.aspx

- 4,943
- 12
- 55
- 74