41
votes

When I place a TextBlock inside of a Horizontally Aligned StackPanel it does not wrap. I realize that this is because the available width of the StackPanel is PositiveInfinity but are there any workarounds?

My layout is much more complicated than this sample so I cannot remove the StackPanel or the Horizontal Orientation. I just tried to reproduce the simplest possible example that exhibits the behavior.

    <StackPanel Orientation="Horizontal">
        <Rectangle Width="50" Height="50" Fill="Blue" VerticalAlignment="Top" />
        <Rectangle Width="50" Height="50" Fill="Red" VerticalAlignment="Top" />
        <TextBlock TextWrapping="Wrap"
                Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus leo lectus, viverra ut lobortis vel, mollis eget lectus. Suspendisse laoreet consequat ultrices. Curabitur ultricies, tortor feugiat porttitor faucibus, lorem eros pretium nisl, eu ullamcorper mauris tortor sit amet augue." />
    </StackPanel>

Update: The width of the TextBlock must be dynamic. I need it to flow with the window as it is resized.

Update 2: Added another element to the StackPanel because I need the children laid out Horizontally.

Update 3 (Solution): Replaced the StackPanel with a DockPanel.

<DockPanel>
    <DockPanel DockPanel.Dock="Top">
        <Rectangle Width="50" Height="50" Fill="Blue" VerticalAlignment="Top" DockPanel.Dock="Left" />
        <Rectangle Width="50" Height="50" Fill="Red" VerticalAlignment="Top" DockPanel.Dock="Left" />
        <TextBlock TextWrapping="Wrap"
                Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus leo lectus, viverra ut lobortis vel, mollis eget lectus. Suspendisse laoreet consequat ultrices. Curabitur ultricies, tortor feugiat porttitor faucibus, lorem eros pretium nisl, eu ullamcorper mauris tortor sit amet augue." />
    </DockPanel>
</DockPanel>
4

4 Answers

56
votes

It's because you're using Horizontal orientation on the StackPanel. That means that the StackPanel is giving full width to each child control, and then laying them out horizontally - even if that means exceeding its bounded/visible width. Because there's nothing to constrain the width of the TextBlock, it doesn't wrap.

If you switch to Vertical orientation then the wrapping works, but I'm guessing there's a reason for you specifying otherwise. Can you show what layout you're trying to achieve?

29
votes

You could use a grid instead of the StackPanel (which as explained does not restrict its content.). A grid allows much more control over layout of items than a StackPanel does and if your image is collapsed then the 'auto' column will have a 0 width.

<DockPanel>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Rectangle Width="50" Height="50" Fill="Blue" VerticalAlignment="Top" />
        <TextBlock TextWrapping="Wrap" Grid.Column="1"
            Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus leo lectus, viverra ut lobortis vel, mollis eget lectus. Suspendisse laoreet consequat ultrices. Curabitur ultricies, tortor feugiat porttitor faucibus, lorem eros pretium nisl, eu ullamcorper mauris tortor sit amet augue." />
    </Grid>

</DockPanel>
11
votes

I got couple of solution for this problem.

1) binding parent width to textblock width. (im the following case i considered usercontrol as parent).

<UserControl x:Class="WpfApplication1.MyWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" Name="userctrl">   
    <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" HorizontalAlignment="Left" >
            <TextBlock TextWrapping="Wrap" MaxWidth="{Binding ElementName=userctrl,Path=ActualWidth}"
                Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus leo lectus, viverra ut lobortis vel, mollis eget lectus. Suspendisse laoreet consequat ultrices. Curabitur ultricies, tortor feugiat porttitor faucibus, lorem eros pretium nisl, eu ullamcorper mauris tortor sit amet augue." />

        </StackPanel>       
    </DockPanel>
</UserControl>

2) other solution is using Grid instead of stackpanel

<UserControl x:Class="WpfApplication1.MyWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" Name="userctrl">   
    <DockPanel>
        <Grid DockPanel.Dock="Top" HorizontalAlignment="Left" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBlock TextWrapping="Wrap" 
                Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus leo lectus, viverra ut lobortis vel, mollis eget lectus. Suspendisse laoreet consequat ultrices. Curabitur ultricies, tortor feugiat porttitor faucibus, lorem eros pretium nisl, eu ullamcorper mauris tortor sit amet augue." />
            <TextBlock TextWrapping="Wrap" Grid.Column="1" Margin="20 0 0 0"
                Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus leo lectus, viverra ut lobortis vel, mollis eget lectus. Suspendisse laoreet consequat ultrices. Curabitur ultricies, tortor feugiat porttitor faucibus, lorem eros pretium nisl, eu ullamcorper mauris tortor sit amet augue." />

        </Grid>       
    </DockPanel>
</UserControl>
5
votes

If you were like me and was wondering why the Textblock was still not wrapping after defining a Width.

Try adding a MaxWidth to the Textblock with same same value as Width,

This stops the control from growing in Width once the application has started.

Hope this helps!