Search code examples
c#wpfxamlwpfdatagrid

TextWrapping inside a DataGrid


Goal

I have a WPF application that contain text inside a DataGrid. I want the text to wrap inside each cell. I also want to set a MinWidth for each column and if it has to, the ScrollViewer should create the horizonatl scroll bar. I never want a horizontal scroll bar to appear for the any of the cells or the DataGrid itself. If the user resizes the window, the rows should grow or shrink to accommodate the text wrapping, but it shouldn't allow the coulmns get so thin that they are no longer readable.

Problem

Right now, the text doesn't wrap because it is in a scrollviewer. I know of different ways that I can change this sample to get the text to wrap, but I can't get it to act exactly how I want it, as mentioned above.

Simplified xaml

<Window x:Class="SampleApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SampleApp"
    Title="App" Height="350" Width="525">

    <Window.Resources>
        <Style x:Key="WrappingTextBlock" TargetType="TextBlock">
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
        <Style x:Key="WrappingTextBox" TargetType="TextBox">
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
    </Window.Resources>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Stuff ... />

        <MoreStuff ... />

        <Border Grid.Row="1" Grid.Column="1">
            <ScrollViewer>
                <StackPanel>    
                    <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding AwesomeObject, Mode=TwoWay}" Margin="5" AutoGenerateColumns="False">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="#" Binding="{Binding Number, Mode=TwoWay}"/>
                            <DataGridTextColumn Header="Header" Binding="{Binding Data, Mode=TwoWay}"/>
                            <DataGridTextColumn MinWidth="50" Header="Long Text" Binding="{Binding SoMuchText, Mode=TwoWay}" ElementStyle="{StaticResource WrappingTextBlock}" EditingElementStyle="{StaticResource WrappingTextBox}"/>
                        </DataGrid.Columns>
                    </DataGrid>
                </StackPanel>
            </ScrollViewer>
        </Border>
    </Grid>
</Window>

Solution

  • Try setting the Width of the Columns to "*"

     <Border Grid.Row="1" Grid.Column="1">
         <ScrollViewer>
             <StackPanel>
                 <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding AwesomeObject, Mode=TwoWay}" Margin="5" AutoGenerateColumns="False">
                     <DataGrid.Columns>
                         <DataGridTextColumn Width="10*" Header="#" Binding="{Binding Number, Mode=TwoWay}"/>
                         <DataGridTextColumn Width="10*" Header="Header" Binding="{Binding Data, Mode=TwoWay}"/>
                         <DataGridTextColumn Width="50*" Header="Long Text" Binding="{Binding SoMuchText, Mode=TwoWay}" ElementStyle="{StaticResource WrappingTextBlock}" EditingElementStyle="{StaticResource WrappingTextBox}"/>
                     </DataGrid.Columns>
                 </DataGrid>
             </StackPanel>
         </ScrollViewer>
     </Border>
    

    This means that Column 1 will be minimum 10 length and growing This means that Column 2 will be minimum 10 length and growing This means that Column 3 will be minimum 50 length and growing

    You can play with the * resizing using percentages (.Number*) or lengths (Number*)