Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make some of DataGrid cells span multiple columns

Tags:

c#

wpf

OK, I have searched for pretty long time for solution of this problem. I am developing simple printing system for WPF DataGrids and have managed to print tables with uniform cell placement using DataTable and setting it as DataGrid's ItemSource.

However, I needed some rows to contain only one cell (you can think of it like "row group header" inside the table).

So, since I haven't found anything about DataTable's cells spanning multiple columns (if this can be made, it would be a great thing to know how), I figured I would have to add rows to DataGrid manually, and solve it something like this:

  • Make new DataGrid with desired columns
  • Add rows one by one, setting the DataGridCellPanel that spans or not spans through rows

The second point is where I have the problem (if it's right, that is). I need to add row to a DataGrid that uses simple array of strings as cell data (index in array should mach the cell index). Is there an easy way to do something like that?

like image 805
Dejan Maksimovic Avatar asked May 09 '13 20:05

Dejan Maksimovic


1 Answers

So after some more fiddling with all this, I have reached a very nice solution.

The best and easiest thing to do is to apply a data template to particular rows after the DataGrid is loaded. So, I stuck to original idea with DataTables and remembered the indices that needed to have their template changed. I just took the DataGridRows from these indices and applied the template that had custom made ItemsPanelTemplate that spans multiple columns.

EDIT: On Daniel's request, I'm including some code.

First thing we need is a template for spanning row:

<ControlTemplate TargetType='{x:Type DataGridRow}'
                 xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                 xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
    <Border>
        <DataGridCellsPresenter Foreground='Black'>
            <DataGridCellsPresenter.ItemsPanel>
                <ItemsPanelTemplate>
                    <local:DataGridSpannedCellPanel />
                </ItemsPanelTemplate>
            </DataGridCellsPresenter.ItemsPanel>
        </DataGridCellsPresenter>
    </Border>
</ControlTemplate>

NOTE: local:DataGridSpannedCellPanel is a custom DataGridCellsPanel with overridden ArrangeOverride method that makes first cell span entire size.

You can make a string in code-behind and load your template from it, for example. The next thing is creating your grid and initializing some of the rows with this new template:

var newGrid = MakeNewDataGrid();
newGrid.ItemsSource = myTable.AsDataView();
var template = XamlReader.Parse(HeaderRowTemplate) as ControlTemplate;

foreach (int index in myHeaderIndices)
{
    var container = newGrid.ItemContainerGenerator.ContainerFromIndex(index);
    var row = container as DataGridRow;
    if (row != null)
    {
        row.Template = template;
    }
}

Also note, rows in your table need to be made as follows:

if (bindableQuote.IsGroup())
{
    table.Rows.Add("Header");
}
else
{
    table.Rows.Add(rowData.ToArray());
}

That's about it, the only thing left is to figure out how to implement DataGridSpannedCellPanel.

like image 147
Dejan Maksimovic Avatar answered Nov 20 '22 07:11

Dejan Maksimovic