Oliver Giesen
Oliver Giesen

Reputation: 9439

Is there some easy way to specify a MaxWidth for a WPF DataGridTextColumn that only affects auto-sizing?

In a WPF app I'm using a DataGrid to display data from a text file that has been parsed into multiple columns. One of the columns in particular contains text of very variable length. As the column widths auto-adapt to their content by default, some very long texts in this column often push the following columns out of sight, forcing the user to scroll horizontally.

At first I tried to remedy this by specifying a MaxWidth for the column but that will completely prevent users from resizing the column to see the full contents if they so desire. Simply setting Width to a fixed value is slightly better but then the column will often be wider than it needs to be...

So, what I'm looking for is a sort of "soft" MaxWidth that will only affect the column's auto-sizing but not the user's ability to resize it beyond that value... Is there a light-weight way to do this, ideally without code-behind (or at least very little)?

Upvotes: 0

Views: 138

Answers (1)

BionicCode
BionicCode

Reputation: 28968

You have some options. You can set the DataGrid.ColumnWidth to a fixed width or to DataGridLength.SizeToHeader:

For all columns:

<DataGrid ColumnWidth="{x:Static DataGridLength.SizeToHeader}" />

For individual columns:

<DataGridTextColumn Width="{x:Static DataGridLength.SizeToHeader}" />

Additionally you can add an ellipsis character to the cell's content to indicate overflowing cell content to the user.

When auto generating columns:

<DataGrid AutoGeneratingColumn="OnDataGrid_AutoGeneratingColumn"
          ColumnWidth="{x:Static DataGridLength.SizeToHeader}">
  <DataGrid.Resources>
    <Style x:Key="DataGridTextColumnEditStyle"
           TargetType="{x:Type TextBlock}"
           BasedOn="{StaticResource {x:Type TextBlock}}">
      <Setter Property="TextTrimming"
              Value="CharacterEllipsis" />
    </Style>
  </DataGrid.Resources>
</DataGrid>
private void OnDataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
  if (e.Column is DataGridTextColumn textColumn)
  {
    var dataGrid = sender as DataGrid;
    var textColumnEditStyle = dataGrid.FindResource("DataGridTextColumnEditStyle") as Style;
    textColumn.ElementStyle = textColumnEditStyle;
  }
}

When defining columns explicitly:

<DataGrid AutoGenerateColumns="False">
  <DataGrid.Columns>
    <DataGridTextColumn Width="{x:Static DataGridLength.SizeToHeader}">
      <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}"
               BasedOn="{StaticResource {x:Type TextBlock}}">
          <Setter Property="TextTrimming"
                  Value="CharacterEllipsis" />
        </Style>
      </DataGridTextColumn.ElementStyle>
    </DataGridTextColumn>
  </DataGrid.Columns>
</DataGrid>

Another solution is to allow the DataGrid to calculate the widths and validate and coerce each column width afterwards:

<DataGrid Loaded="OnDataGrid_Loaded" />
private const double MaxColumnWidth = 200;

private void OnDataGrid_Loaded(object sender, RoutedEventArgs e)
{
  var dataGrid = sender as DataGrid;

  // Alternatively, select the particular column of interest by index or Header value
  foreach (DataGridColumn column in dataGrid.Columns)
  {
    if (column.ActualWidth > MaxColumnWidth)
    {
      column.Width = MaxColumnWidth;
    }
  }
}

Upvotes: 1

Related Questions