3
votes

I have got multiple TextBlocks whose Text is inserted through DynamicResource. They are all set to TextWrapping="Wrap". But inside those Text-strings I have words which are not allowed to be split up. Those words must be kept as a whole word.

With hardcoded Text in Xaml it's quite easy solved via a TextBlock inside a Textblock:

<TextBlock TextWrapping="Wrap">
Example text with wrap and <TextBlock TextWrapping="NoWrap" Text=" example text without wrap"/
</TextBlock>

But this solution does not work when Text the is inserted through DynamicResource, because the text is not getting parsed.

How can I combine nowrap and wrap inside a DynamicResource Text without splitting it into multiple TextBlocks one after another?

PS: I have now created an example to demonstrate the behavior I would like (green) and the failed attempts (red, orange, darkred) of solving it:

<StackPanel HorizontalAlignment="Center" Width="80" Orientation="Vertical">
            <TextBlock TextWrapping="Wrap" Foreground="green">
                bla1 bla2 bla3 bla4 <TextBlock TextWrapping="NoWrap" Text="Together(en)"/> bla5 bla6 longWordWhichShouldBreak
            </TextBlock>
            <TextBlock TextWrapping="Wrap" Foreground="red">
                bla1 bla2 bla3 bla4 Together(en) bla5 bla6 longWordWhichShouldBreak
            </TextBlock>
            <TextBlock TextWrapping="Wrap" Foreground="orange">
                bla1 bla2 bla3 bla4&#160;Together(en)&#160;bla5 bla6 longWordWhichShouldBreak
            </TextBlock>
            <TextBlock TextWrapping="WrapWithOverflow" Foreground="DarkRed">
                bla1 bla2 bla3 bla4&#160;Together(en)&#160;bla5 bla6 longWordWhichShouldBreak
            </TextBlock>
        </StackPanel>

Result

4
Sounds like your so called "DynamicResource" is not suitable structured for usage in WPF. How about some preprocessing into a sequence of text chunks where each chunk has its display options?grek40
Yes preprocessing into multiple sequence of text, in nowrap and wrap pieces is a solution. But it's relatively costly. I thought that there is a better solution of keeping just a single word together in wrap textblock.CR500
Generally, you may have better luck with the TextBlock.Inlines property than the TextBlock.Text property. You can't expect the Text property to do anything else than just eating your text as... well text.grek40
Thank your for this hint with Inlines! But Inlines is not bindable and can not be injected with a DynamicResource I think.CR500
Uh, surprise... but the point is, when you write <TextBlock Text="X"/> you use Text, but when you write <TextBlock>X</TextBlock> the TextBlock.Inlines collection is used, not the Text property. So don't hope to emulate your written XAML without using the inlines.grek40

4 Answers

2
votes

Use NO-BREAK SPACE in your dynamic text. For example:

<TextBlock TextWrapping="Wrap">
        Example text with wrap and example text&#160;without&#160;wrap
</TextBlock>

You can replace space with this char in those parts that you need this behaviour:

  Replace(" ", System.Convert.ToChar(160))
1
votes

Have you considered using 'WrapWithOverflow' instead of 'Wrap'? This will only break the line if a space appears.

You can then set the words that must appear together with dashes,e.g.- 'regular line and words-that-shouldn't-break'

0
votes

You should use Run:

<TextBlock>
    <Run Text={x:static SomeText} />
    <Run Text={x:static SomeNoWrapText}
         TextWrapping="NoWrap"/>
    <Run Text={x:static SomeMoreText} />
</TextBlock>
0
votes

It's a bit much for a comment, but also not a complete answer.

Lets translate your example piece of XAML from all the implicit contents to a full qualified structure.

Your simplified XAML, using the implicit content properties and so on:

<TextBlock TextWrapping="Wrap" Foreground="green">
    bla1 bla2 bla3 bla4 <TextBlock TextWrapping="NoWrap" Text="Together(en)"/> bla5 bla6 longWordWhichShouldBreak
</TextBlock>

Equivalent actual structure:

<TextBlock TextWrapping="Wrap" Foreground="green">
    <TextBlock.Inlines>
        <Run Text="bla1 bla2 bla3 bla4 "/>
        <InlineUIContainer>
            <InlineUIContainer.Child>
                <TextBlock TextWrapping="NoWrap" Text="Together(en)"/>
            </InlineUIContainer.Child>
        </InlineUIContainer>
        <Run Text=" bla5 bla6 longWordWhichShouldBreak"/>
    </TextBlock.Inlines>
</TextBlock>

This should give you some idea about the complexity of what you have in your XAML. You can't archieve the same result by simply setting the Text property.

Currently I can't answer how to solve this issue, since DynamicResource is not enough information to start transforming into above structure.

You may want to have a look at this question: Data binding the TextBlock.Inlines