In WPF, can you bind a ListView (NOT DataGrid) to a Matrix (Cross-Tab) DataSet?
Question
Is it possible in WPF to bind a ListView (NOT a DataGrid) to a Matrix (Cross-Tab) DataSet in which the columns are unknown beforehand?
Using the Northwind database as an example: the simple query below will return a wellknown dataset which can easily be bound to a listview:
SELECT Year(o.OrderDate) AS [Year], Month(o.OrderDate) AS [Month],
COUNT(o.OrderID) AS [NumOrders]
FROM Orders o
GROUP BY Year(o.OrderDate), Month(o.OrderDate)
ORDER BY 1, 2
To generate a more meaningful report, we might run the result set from the above query (in a reporting program) to generate some thing as below shown below:
SELECT [Year],
SUM(CASE [Month] WHEN 1 Then NumOrders ELSE 0 END) AS 'Jan',
SUM(CASE [Month] WHEN 2 Then NumOrders ELSE 0 END) AS 'Feb',
SUM(CASE [Month] WHEN 3 Then NumOrders ELSE 0 END) AS 'Mar',
SUM(CASE [Month] WHEN 4 Then NumOrders ELSE 0 END) AS 'Apr',
SUM(CASE [Month] WHEN 5 Then NumOrders ELSE 0 END) AS 'May',
SUM(CASE [Month] WHEN 6 Then NumOrders ELSE 0 END) AS 'Jun',
SUM(CASE [Month] WHEN 7 Then NumOrders ELSE 0 END) AS 'Jul',
SUM(CASE [Month] WHEN 8 Then NumOrders ELSE 0 END) AS 'Aug',
SUM(CASE [Month] WHEN 9 Then NumOrders ELSE 0 END) AS 'Sep',
SUM(CASE [Month] WHEN 10 Then NumOrders ELSE 0 END) AS 'Oct',
SUM(CASE [Month] WHEN 11 Then NumOrders ELSE 0 END) AS 'Nov',
SUM(CASE [Month] WHEN 12 Then NumOrders ELSE 0 END) AS 'Dec'
FROM
(
SELECT Year(o.OrderDate) AS [Year], Month(o.OrderDate) AS [Month],
COUNT(o.OrderID) AS [NumOrders]
FROM Orders o
GROUP BY Year(o.OrderDate), Month(o.OrderDate)
)t0
GROUP BY [Year]
Which results into something like this:
My question is, It it possible to bind this final result to a ListView or a Flowdocument in WPF without having prior knowledge of the resulting columns?
Solution
You can add columns dynamically to a ListView by using Attached Properties. Check out this article on the CodeProject it explains exactly that...
OTHER TIPS
You can generate the GridViewColumns for the ListView programatically and apply the binding to that. Loop through the columns in the DataSet and add a corresponding GridViewColumn into the ListView.
var gridView = (GridView)list.View;
foreach(var col in table.Columns) {
gridView.Columns.Add(new GridViewColumn{
Header=col.ColumnName,
DisplayMemberBinding=new Binding(col.ColumnName)});
}