Force TextBlock to wrap in WPF ListBox

WpfListboxWord WrapTextblock

Wpf Problem Overview


I have a WPF listbox which displays messages. It contains an avatar on the left side and the username and message stacked vertically to the right of the avatar. The layout is fine until the message text should word wrap, but instead I get a horizontal scroll bar on the listbox.

I've Googled and found solutions to similar issues, but none of them worked.

<ListBox HorizontalContentAlignment="Stretch"  ItemsSource="{Binding Path=FriendsTimeline}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Border BorderBrush="DarkBlue" BorderThickness="3" CornerRadius="2" Margin="3" >
                    <Image Height="32" Width="32"  Source="{Binding Path=User.ProfileImageUrl}"/>
                </Border>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Path=User.UserName}"/>
                    <TextBlock Text="{Binding Path=Text}" TextWrapping="WrapWithOverflow"/> <!-- This is the textblock I'm having issues with. -->
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Wpf Solutions


Solution 1 - Wpf

Contents of the TextBlock can be wrapped using property TextWrapping. Instead of StackPanel, use DockPanel/Grid. One more thing - set ScrollViewer.HorizontalScrollBarVisibility property to Disabled value for the ListBox.

Updated Hidden to Disabled based on comment from Matt. Thanks Matt.

Solution 2 - Wpf

The problem might not be located in the ListBox. The TextBlock won't wrap, if one of the parent controls provides enough space, so that it hasn't the need to wrap. This might be caused by a ScrollViewer control.

Solution 3 - Wpf

If you want to prevent TextBlock to grow, and you want it to just fit in the size of the listbox, you should set the width of it explicitly.

In order to change it dynamically, it means not a fix value, but you need to bind it to its proper parent element in the visual tree. You can have something like this:

<ListBox ItemsSource="{Binding MyItems}" Name="MyListBox">

  <ListBox.Resources>
    <Style TargetType="ListBoxItem">
      <Setter Property="Width" 
              Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollContentPresenter}, Path=ActualWidth}" />
    </Style>
  </ListBox.Resources>

  <ListBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Title}" TextWrapping="Wrap" />
    </DataTemplate>
  </ListBox.ItemTemplate>

</ListBox>

If it does not work, try to find the proper elements (which has to be binded to what) with the Live Visual Tree in Visual Studio.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEric HaskinsView Question on Stackoverflow
Solution 1 - WpfNashView Answer on Stackoverflow
Solution 2 - WpfMartin MoserView Answer on Stackoverflow
Solution 3 - WpfeldorView Answer on Stackoverflow