首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从RichTextBlock获取可见文本

从RichTextBlock获取可见文本
EN

Stack Overflow用户
提问于 2017-01-24 00:31:23
回答 1查看 316关注 0票数 0

在UWP应用程序中,我使用的是一个RichTextBlock,它可以填充一些内容。它启用了单词包装,并设置了最大行,因此不管内容的长度如何,它只会显示一定数量的丰富文本。

我想知道是否有办法找出什么是可见的文本?

所以如果我有:

代码语言:javascript
复制
<RichTextBlock TextWrapping="Wrap" MaxLines="2">
    <RichTextBlock.Blocks>
        <Paragraph>
            <Paragraph.Inlines>
                A bunch of runs go in here with text that are several lines
            </Paragraph.Inlines>
        </Paragraph>
    </RichTextBlock.Blocks>
</RichTextBlock>

我想知道有多少文本是可见的。

我正在尝试检测文本长度超过设定行数的情况,并在最后一行的末尾添加“.阅读更多”(将最后13个字符替换为“.阅读更多”)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-26 19:11:27

所以我编写了一些代码来得到我想要的行为,但不幸的是,这是相当缓慢和低效的。因此,如果您在一个应用程序中使用它,主要是显示大量需要截断的文本(比如包含大量文本项的ListView ),那么这会减慢应用程序的运行速度。我仍然想知道是否有更好的方法来做到这一点。

下面是我的代码(它只处理运行和超链接内联,因此您必须修改以处理您需要的其他类型):

代码语言:javascript
复制
private static void TrimText_Slow(RichTextBlock rtb)
{
    var paragraph = rtb?.Blocks?.FirstOrDefault() as Paragraph;
    if (paragraph == null) { return; }

    // Ensure RichTextBlock has passed a measure step so that its HasOverflowContent is updated.
    rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
    if (rtb.HasOverflowContent == false) { return; }


    // Start from end and remove all inlines that are not visible
    Inline lastInline = null;
    var idx = paragraph.Inlines.Count - 1;
    while (idx >= 0 && rtb.HasOverflowContent)
    {
        lastInline = paragraph.Inlines[idx];
        paragraph.Inlines.Remove(lastInline);
        idx--;
        // Ensure RichTextBlock has passed a measure step now with an inline removed, so that its HasOverflowContent is updated.
        rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
    }

    // The last inline could be partially visible. The easiest thing to do here is to always
    // add back the last inline and then remove characters from it until everything is in view.
    if (lastInline != null)
    {
        paragraph.Inlines.Add(lastInline);
    }

    // Make room to insert "... Read More"
    DeleteCharactersFromEnd(paragraph.Inlines, 13);

    // Insert "... Continue Reading"
    paragraph.Inlines.Add(new Run { Text = "... " });
    paragraph.Inlines.Add(new Run { Text = "Read More", Foreground = new SolidColorBrush(Colors.Blue) });

    // Ensure RichTextBlock has passed a measure step now with the new inlines added, so that its HasOverflowContent is updated.
    rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));

    // Keep deleting chars until "... Continue Reading" comes into view
    idx = paragraph.Inlines.Count - 3; // skip the last 2 inlines since they are "..." and "Read More"
    while (idx >= 0 && rtb.HasOverflowContent)
    {
        Run run;

        if (paragraph.Inlines[idx] is Hyperlink)
        {
            run = ((Hyperlink)paragraph.Inlines[idx]).Inlines.FirstOrDefault() as Run;
        }
        else
        {
            run = paragraph.Inlines[idx] as Run;
        }

        if (string.IsNullOrEmpty(run?.Text))
        {
            paragraph.Inlines.Remove(run);
            idx--;
        }
        else
        {
            run.Text = run.Text.Substring(0, run.Text.Length - 1);
        }

        // Ensure RichTextBlock has passed a measure step now with the new inline content updated, so that its HasOverflowContent is updated.
        rtb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
    }
}

private static void DeleteCharactersFromEnd(InlineCollection inlines, int numCharsToDelete)
{
    if (inlines == null || inlines.Count < 1 || numCharsToDelete < 1) { return; }

    var idx = inlines.Count - 1;

    while (numCharsToDelete > 0)
    {
        Run run;

        if (inlines[idx] is Hyperlink)
        {
            run = ((Hyperlink)inlines[idx]).Inlines.FirstOrDefault() as Run;
        }
        else
        {
            run = inlines[idx] as Run;
        }

        if (run == null)
        {
            inlines.Remove(inlines[idx]);
            idx--;
        }
        else
        {
            var textLength = run.Text.Length;
            if (textLength <= numCharsToDelete)
            {
                numCharsToDelete -= textLength;
                inlines.Remove(inlines[idx]);
                idx--;
            }
            else
            {
                run.Text = run.Text.Substring(0, textLength - numCharsToDelete);
                numCharsToDelete = 0;
            }
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41818094

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档