none
Textblock and Textwrapping="Wrap"

    Question

  • How do you make this work the way one would expect it to when it comes to layout?

     

    What I mean, is that under numerous scenarios, the Textblock causes the parent to size it's width greedily, when what you usually want is for it to be non-greedy with the width and greedy with the height.  I told the text to wrap, so wrap it!  There's a good example of what I mean on my blog at http://wekempf.spaces.live.com/blog/cns!D18C3EC06EA971CF!246.entry.  I've been searching for a solution, and simply can't find one, and it's driving me insane! Smile

    Thursday, June 14, 2007 1:16 AM

All replies

  • Looking at the following sample code from your blog:

    Code Snippet

    <Page

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
    <Grid>
    <Grid.ColumnDefinitions>
    <ColumnDefinition/>
    <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" Text="Title Here"/>
    <TextBlock Grid.Column="1" Text="Price" TextAlignment="Right"/>
    </Grid>
    <TextBlock TextWrapping="Wrap"><![CDATA[
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed neque et tellus tincidunt interdum. Morbi diam eros, imperdiet at, volutpat et, vestibulum quis, sem. Curabitur eu tellus vel felis molestie malesuada. Pellentesque nec lacus. Aenean fringilla nonummy sapien. Morbi eu odio at turpis cursus tristique. Integer nec lectus sit amet turpis bibendum feugiat. Cras posuere condimentum sapien. Vivamus accumsan, lacus at bibendum vehicula, magna elit consectetuer diam, ac luctus elit diam non leo. Vestibulum lobortis augue nec nisl. Fusce viverra purus consequat lacus. Nullam elementum mattis tellus. In hac habitasse platea dictumst. Aliquam ac velit sit amet urna placerat fringilla. Fusce mattis arcu eget urna. Sed lacus.
    ]]></TextBlock>
    </StackPanel>
    </Page>

    Your problem isn't the wrapping, your problem is a misunderstanding of layout.

    Since this is a page, the available space for arrangement is going to be positive infinity in either direction. Your stack panel has an infinite amount of space so it gives that infinite sizing information to the textblock. The textblock knows it renders from left to right, has as much space as it wants, figures out how much space it will take to render everything on one line, and gives that value back as it's desired size.

    If your code was in a window, it'd work differently since your max width would be constrained to the window.

    You could specify a MaxWidth or Width for the StackPanel and that should take care of things for you. For a more dynamic approach, you could do something like:

    Code Snippet


    <Page ... x:Name="_page">
      <StackPanel MaxWidth="{Binding ActualWidth, ElementName=_page}">

     ...


    This will have the maximum width of the StackPanel to the size of the available space will resize with the browser the way you'd expect it to.

    There's probably an easier way of doing this for pages, but I don't know too much there. Most of what I do is Windows. Not that there's too much of a difference thanks to WPF.


    Thursday, June 14, 2007 4:42 AM
  • Thanks for the reply, but it doesn't help.  See, the code on the blog is just an example.  The problem is much more general.  I have two specific places in real code where this is an issue that can be simply solved.  The first is very similar to the other blog post on this same topic that I referenced, but instead of a Listbox, I've got a ListView with a custom ListViewItem that has text beneath the GridViewRowPresenter, similar to here: http://www.beacosta.com/Archive/2006_02_01_bcosta_archive.html.  There's no clean way to get this one to work, as far as I can figure.  I tried the data binding trick you suggested a few days ago, but there's no obvious control width to bind to.  Binding to the ListView's width comes close, but this width is the width of the entire control, not of the "non-client" area, so the text still often runs longer than the viewable area and causes scroll bars.

     

    The second place this occurs uses roughly this layout (with lots of detail removed, so this isn't valid XAML):

     

    Code Snippet

    <Window>

      <DockPanel>

        <StackPanel DockPanel.Dock="Left">

          <StackPanel>

            <!-- Controls to filter the ListView, the size of which should dynamically determine the full size of this side panel area. -->

          </StackPanel>

          <StackPanel>

            <!-- Detailed information of item selected in ListView -->

            <!-- The following causes the entire side panel to expand to the width of the text, instead of the text wrapping. -->

            <TextBlock Textwrapping="Wrap" Text="{Binding Path=SomeTextBinding}"/>

        </StackPanel>

        <ListView DockPanel.Dock="Right">

          <!-- Template stuff that has the first issue discussed above. -->

        </ListView>

      </DockPanel>

    </Window>

     

     

    See, my problem isn't precisely in not understanding WPF layout.  I do understand what's happening here algorithmically.  I just don't agree with it.  When a TextBlock is set to wrap, it should not be greedy in determining it's width.  But regardless of my opinion of this design decision, for which I can do nothing about, my problem is that I can't discover a general solution to this problem that can be easily applied to every situation in which it occurs.  Which is tremendously frustrating, because for me it occurs frequently.  I'm about to consider rolling my own custom panel to do with this, but I don't even know if that will work, much less what's required to do it at this point.

    Thursday, June 14, 2007 12:57 PM
  • I have to agree with wekempf. The TextWrapping property almost never does what I want. Sure, it has to do with the underlying layout system, which is fine, but the TextElement seems rather poorly designed since it does not handle such common cases as above very well.

    My workaround to this problem in general is to use FlowDocuments, but this seems way more heavy-handed than it needs to be. Since I don't use XAML, FlowDocuments are even more annoying than they would be to the XAML programmer. (I know XAML is great because of name your reason here, but I write applications that I have to be able to scale, debug, and maintain, so this means no XAML, resources, or data binding.)

    Cheers,
    Adam
    • Proposed as answer by Eric Ouellet Friday, November 04, 2011 6:25 PM
    • Unproposed as answer by Eric Ouellet Friday, November 04, 2011 6:26 PM
    Thursday, September 24, 2009 9:44 PM
  • Hello,

     

    A little bit to late...

    The problem reside in the fact that you use stack panel instead of a grid.

    StackPanel will calculate it's width according to it's content, then no text wrapping will ever occur, at least as far as the stack could become wider.

    Using a grid will probably achieve the expected behavior.

    I already had the same problem and since then, I mainly use grid over stackPanel.

     

    Good luck,

    Eric


    Eric Ouellet
    Friday, November 04, 2011 6:30 PM
  • My problem comes when putting wrapping text in a listbox.  Since the underlying layout is a stackpanel, the text block doesn't wrap.
    Tuesday, May 15, 2012 5:26 PM
  • Currently having the same issue with a ListView, no StackPanels involved. The TextBlock width is greedy, really annoying :(

            <ListView Margin="5,0,10,45">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            
                            <RadioButton Grid.Row="0" x:Name="PART_RadioButton" IsChecked="{Binding IsSelected}">
                                <TextBlock>
                                    <TextBlock Text="{Binding Alternative, StringFormat=k}" />
                                    <TextBlock Visibility="{Binding Description, Converter={windows:BooleanToVisibilityConverter}}" Text="{Binding Description, StringFormat={} ({0})}" />
                                </TextBlock>
                            </RadioButton>
                            <TextBlock Grid.Row="1" Margin="16,0,0,6" Text="{Binding Notiz}" TextWrapping="Wrap" Visibility="{Binding Notiz, Converter={windows:BooleanToVisibilityConverter}}" />
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

    Thursday, June 28, 2012 8:53 AM
  • As you can see from this Stack question, the issue is with your use of "auto" vs "*". Try adding a ColumnDefinition using "*"
    Tuesday, May 20, 2014 8:21 PM