0

What I'm trying to do is display a string, as a series of characters within a DataGrid. If you look at this example, hopefully it makes sense.

DataGrid layout

So, for the string 'Hello there!' what I'm trying to do is have the grid display look as close as possible to how it would look in a standard TextBlock.

However, no matter how small I make the cells, I cannot get them to align correctly, as there is always an unnatural spacing between the cells. I'm not sure what you actually call the space between cells either, padding, spacing?

Is there a way to have a DataGridCell fit its contents exactly, without any additional spacing on either side?

Tony
  • 3,587
  • 8
  • 44
  • 77
  • Just to clarify, you want to display a single character in each cell of the `DataGrid` with as little space as possible between the characters in each cell when rendered? – Pseudonymous Jan 03 '21 at 17:33
  • Correct, I would like a grid that can be addressed with columns/rows, but it needs to appear to the user as if it is just a string. No spacing before, or after each character. – Tony Jan 03 '21 at 17:34
  • You can download the [snoop](https://github.com/snoopwpf/snoopwpf) and check the visual tree controls and their properties; using that you can check that what is total size taken by Grid cell/header and which property governs that. – user1672994 Jan 03 '21 at 17:39
  • ever heard of monospace fonts? hint: IDE usually use them with great success – ASh Jan 03 '21 at 17:52
  • To remove the margins, does this help? https://stackoverflow.com/questions/26022106/wpf-datagridcell-margin IIRC, WPF sizes all columns to content (default is auto), yet I might have not understood the question correctly so for manually adjusting sizes of all columns a few lines of code might help: https://stackoverflow.com/questions/4997596/how-can-i-set-the-width-of-a-datagridcolumn-to-fit-contents-auto-but-comple – Hamed Jan 03 '21 at 18:36

2 Answers2

1

You'll have to fight the DataGrid a bit to do this but it is possible.

The first thing you want to do is to stop any screen space being reserved for the headers at all. You can do this by setting their Visibility property to Collapsed.

<Style TargetType="DataGridColumnHeader">
    <Setter Property="Visibility" Value="Collapsed" />
</Style>

If you're declaring columns explicitly you'll need to set their MinWidth value to 0 in the XAML otherwise, if they're being auto-generated, you'll need to loop them programmatically and set it there - I used the Loaded event. This default was set to 20.

private void StringRepresentationGrid_OnLoadedRepresentationGrid_OnLoaded(object sender, RoutedEventArgs e)
{
    foreach (var column in StringRepresentationGrid.Columns)
    {
        column.MinWidth = 0;
    }
}

Then you'll need to override the Template property of DataGridCell to something like the below. I've used a monospaced font to keep the layout regular.

<Style x:Key="CustomDataGridCellStyle" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
    <Setter Property="TextBlock.TextAlignment" Value="Center"/>
    <Setter Property="FontSize" Value="12" />
    <Setter Property="Border.BorderThickness" Value="0" />
    <Setter Property="TextBlock.FontFamily" Value="Consolas" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <TextBlock 
                    Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Text}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

This should give you something close to the spacing of a standard TextBlock in the DataGrid.

Pseudonymous
  • 839
  • 5
  • 13
0

The bottle neck of this is the choice of your control:

A datagrid consists of headers, rows and columns. What you are trying to do has several drawbacks:

  1. If you have a header (or cell in say row 1, column 1) that holds a 'w', the cell below (that would be row 2, column 1) that wants to adjust closely to an 'l' can't get closer than the width of the cell holding 'w' because the minimum size would be the one it needs to present the 'w', which is a bit more wider.

  2. You could however play around with negative values for padding, but this will lead to all sorts of issues.

  3. Even if you stick to one font size for headers (or set all headers to hidden), you would still have the issue mentioned under 1) for each cell.

In other words: a datagrid is not a good solution for your intention. Is there anything that restricts you from not using a user control that would consist of a textblock for each letter? That way I could think of a perfect solution for this, plus the benefit of having a control that gives you full control on styling each letter.