Home > Back-end >  DataGrid enable text wrapping of columns with AutoGenerateColumns=true
DataGrid enable text wrapping of columns with AutoGenerateColumns=true

Time:09-29

I am working on an WPF MVVM application. I have a DataGrid, which is binded to a DataTable. AutoGenerateColumns is set to true.

However, I want to wrap the text of a column to 2 or 3 lines if needed. Currently, when I scroll the DataGrid, when the first column's text is longer, the first column expands as much as it needs and the last column is not seen anymore or is cut.

Here is the code:

<Grid.Resources>
    <Style x:Key="ColumnHeaderStyle" TargetType="DataGridColumnHeader">
         <Setter Property="ItemsControl.MinHeight" Value="50" />
         <Setter Property="ItemsControl.MinWidth" Value="60" />
         <Setter Property="ItemsControl.HorizontalContentAlignment" Value="Center" />
         <Setter Property="ItemsControl.VerticalContentAlignment" Value="Center" />
    </Style>
</Grid.Resources>

Grid:

<Grid
    Width="800"
    Height="500"
    Visibility="Visible">
    <Grid.Resources>
        //code
    </Grid.Resources>
    <DataGrid
        Name="Map"
        Width="Auto"
        Height="Auto"
        Margin="0,10,0,0"
        AutoGenerateColumns="True"
        AutoGeneratingColumn="Map_AutoGeneratingColumn"
        CanUserAddRows="False"
        CanUserReorderColumns="False"
        CanUserResizeColumns="True"
        CanUserResizeRows="True"
        CanUserSortColumns="False"
        ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}"
        FontStretch="Normal"
        IsReadOnly="True"
        ItemsSource="{Binding MapDataTable}" />

I omitted things that are not relevant to the question.

Here is what I have tried:

Attempt 1:

<Grid.Resources>
    <Style x:Key="ColumnHeaderStyle" TargetType="DataGridColumnHeader">
         <Setter Property="ItemsControl.MinHeight" Value="50" />
         <Setter Property="ItemsControl.MinWidth" Value="60" />
         <Setter Property="ItemsControl.HorizontalContentAlignment" Value="Center" />
         <Setter Property="ItemsControl.VerticalContentAlignment" Value="Center" />
         <Setter Property="ContentTemplate">
               <Setter.Value>
                    <DataTemplate>
                         <TextBlock TextWrapping="Wrap" />
                    </DataTemplate>
               </Setter.Value>
         </Setter>
    </Style>
</Grid.Resources>

Attempt 2:

<Grid.Resources>
    <Style x:Key="ColumnHeaderStyle" TargetType="DataGridColumnHeader">
         <Setter Property="ItemsControl.MinHeight" Value="50" />
         <Setter Property="ItemsControl.MinWidth" Value="60" />
         <Setter Property="ItemsControl.HorizontalContentAlignment" Value="Center" />
         <Setter Property="ItemsControl.VerticalContentAlignment" Value="Center" />
    </Style>
    <Style TargetType="TextBlock">
         <Setter Property="TextWrapping" Value="Wrap" />
    </Style>
</Grid.Resources>

Both of them don't work. What is the correct way to fix the text wrapping? AutoGenerateColumns MUST be true.

CodePudding user response:

As you have realized modifying the column header does not modify the column. The solution is to listen to the DataGrid.AutoGeneratingColumn event and modify the generated columns selectively.

I see that you are already listening to the AutoGeneratingColumn event. You simply have to modify the event handler to apply a TextBlock style to the text columns.

First define a Style that targets TextBlock and enables text wrapping:

<DataGrid AutoGeneratingColumn="Map_AutoGeneratingColumn">
  <DataGrid.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="TextWrapping" Value="Wrap" />
    </Style>
  </DataGrid.Resources>
</DataGrid>

Then go to the AutogeneratingColumn event handler Map_AutoGeneratingColumn and filter the text columns to set their initial width and to apply the previously defined TextBlock style:

private void Map_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
  var dataGrid = sender as DataGrid;
  if (e.Column is DataGridTextColumn textColumn)
  {
    textColumn.ElementStyle = dataGrid.FindResource(typeof(TextBlock)) as Style;
    e.Column.Width = 100;
  }
}
  • Related