Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF FlowDocument Table - AutoFit option?

I want a table to logically size the columns according to the contents. Is this possible in WPF?

alt text http://img43.imageshack.us/img43/2640/flowdocument.jpg

Here is the code I'm working with:

<Window x:Class="FlowDocument.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <Style TargetType="{x:Type TableCell}">
            <Setter Property="BorderBrush" Value="Gray" />
            <Setter Property="BorderThickness" Value="3" />


        </Style>
        <Style TargetType="{x:Type Paragraph}">
            <Setter Property="Padding" Value="2, 2, 2, 2" />
        </Style>
    </Window.Resources>
    <Grid>
        <FlowDocumentScrollViewer>
            <FlowDocument>
                <Table>
                    <Table.Columns>
                        <TableColumn Background="LightBlue" />
                        <TableColumn Background="Coral" />
                    </Table.Columns>
                    <TableRowGroup>
                        <TableRow>
                            <TableCell>
                                <Paragraph>This is a long piece of text</Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>This isn't</Paragraph>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>
                                <Paragraph>This is a another long piece of text. The column should be wider than the other one!</Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>Ditto</Paragraph>
                            </TableCell>
                        </TableRow>
                    </TableRowGroup>
                </Table>
            </FlowDocument>
        </FlowDocumentScrollViewer>
    </Grid>
</Window>
like image 628
Andrew Shepherd Avatar asked Sep 29 '09 08:09

Andrew Shepherd


2 Answers

It is possible by determining the desired width of the widest cell of a column. The widest cell can be determined by looping through all the rows determining the desired width of the cell and remembering the biggest value.

In this example, all columns are optimized. The value of 19 might result from the left and right cell padding plus cell border thickness.

void autoresizeColumns(Table table)
{
    TableColumnCollection columns = table.Columns;
    TableRowCollection rows = table.RowGroups[0].Rows;
    TableCellCollection cells;
    TableRow row;
    TableCell cell;

    int columnCount = columns.Count;
    int rowCount = rows.Count;
    int cellCount = 0;

    double[] columnWidths = new double[columnCount];
    double columnWidth;

    // loop through all rows
    for (int r = 0; r < rowCount; r++)
    {
        row = rows[r];
        cells = row.Cells;
        cellCount = cells.Count;

        // loop through all cells in the row    
        for (int c = 0; c < columnCount && c < cellCount; c++)
        {
            cell = cells[c];
            columnWidth = getDesiredWidth(new TextRange(cell.ContentStart, cell.ContentEnd)) + 19;

            if (columnWidth > columnWidths[c])
            {
                columnWidths[c] = columnWidth;
            }
        }
    }

    // set the columns width to the widest cell
    for (int c = 0; c < columnCount; c++)
    {
        columns[c].Width = new GridLength(columnWidths[c]);
    }
}


double getDesiredWidth(TextRange textRange)
{
    return new FormattedText(
        textRange.Text,
        CultureInfo.CurrentCulture,
        FlowDirection.LeftToRight,
        new Typeface(
            textRange.GetPropertyValue(TextElement.FontFamilyProperty) as FontFamily,
            (FontStyle)textRange.GetPropertyValue(TextElement.FontStyleProperty),
            (FontWeight)textRange.GetPropertyValue(TextElement.FontWeightProperty),
            FontStretches.Normal),
            (double)textRange.GetPropertyValue(TextElement.FontSizeProperty),
        Brushes.Black,
        null,
        TextFormattingMode.Display).Width;
}
like image 105
zznobody Avatar answered Nov 01 '22 08:11

zznobody


it's not quite what you're looking for, but you can do something like

<Table.Columns>
    <TableColumn Background="LightBlue" Width="2*"  />
    <TableColumn Background="Coral" Width="*" />
</Table.Columns>
like image 4
kenwarner Avatar answered Nov 01 '22 10:11

kenwarner