Обтекание текста в TextBlock

Есть ли какие-либо возможности предоставить предложение wordwrap для Textblock как вы можете сделать в HTML с <SHY> (soft hyphen) или <WBR> (word break), или еще более сложный и менее обслуживаемый zero-width-space &#8203;

В настоящий момент Textblock разбивает слова так же, как видит необходимость, заканчивающийся переносом слов, например

Stackoverflo
ш

Я хочу:

Stackover-
Поток

или по крайней мере:

Stackover
Поток

Если есть рекомендации по достижению необходимого, пожалуйста, дайте мне знать.

Ответы

Ответ 1

Настройка TextBlock.IsHypenationEnabled на true действительно сделает что-то подобное этому, но если вы хотите использовать теги, вы можете использовать такой метод:

    /// <summary>
    /// Adds break to a TextBlock according to a specified tag
    /// </summary>
    /// <param name="text">The text containing the tags to break up</param>
    /// <param name="tb">The TextBlock we are assigning this text to</param>
    /// <param name="tag">The tag, eg <br> to use in adding breaks</param>
    /// <returns></returns>
    public string WordWrap(string text, TextBlock tb, string tag)
    {
        //get the amount of text that can fit into the textblock
        int len = (int)Math.Round((2 * tb.ActualWidth / tb.FontSize));
        string original = text.Replace(tag, "");
        string ret = "";
        while (original.Length > len)
        {
            //get index where tag occurred
            int i = text.IndexOf(tag);
            //get index where whitespace occurred
            int j = original.IndexOf(" ");
            //does tag occur earlier than whitespace, then let use that index instead!
            if (j > i && j < len)
                i = j;
            //if we usde index of whitespace, there is no need to hyphenate
            ret += (i == j) ? original.Substring(0, i) + "\n" : original.Substring(0, i) + "-\n";
            //if we used index of whitespace, then let remove the whitespace
            original = (i == j) ? original.Substring(i + 1) : original.Substring(i);
            text = text.Substring(i + tag.Length);
        }
        return ret + original;
    }

Теперь вы можете сказать:

textBlock1.Text = WordWrap("StackOver<br>Flow For<br>Ever", textBlock1, "<br>");

Это выведет:

Just tested

Однако, используя только IsHyphenated без тегов, это будет:

IsHypehnated Scenario1

В то время как:

textBlock1.Text = WordWrap("StackOver<br>Flow In<br> U", textBlock1, "<br>");

выведет:

Doesn't add <brs> here

И IsHyphenated без тегов:

IsHyphenated Scenario 2

EDIT: При уменьшении размера шрифта я обнаружил, что первый код, который я разместил, не предпочитает добавлять разрывы, когда пробелы встречаются с указанными пользователем перерывами.

Ответ 2

Используйте TextFormatter в сочетании с пользовательским TextSource, чтобы управлять тем, как текст разбивается и заверяется.

Вам нужно получить класс из TextSource и в вашей реализации проанализировать ваш контент/строку и предоставить свои правила обертывания, например. ищет ваш <wbr> тег... когда вы видите тег, вы возвращаете TextEndOfLine else, вы возвращаете TextCharacters.

Пример, который может помочь в реализации TextSource, приведен ниже:

Для очень продвинутого примера посмотрите на "AvalonEdit", который также использует его:

Вы также можете исследовать GlyphRun, если вам не требуется форматирование.