首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RichTextBlock选定文本UWP

RichTextBlock选定文本UWP
EN

Stack Overflow用户
提问于 2018-07-09 18:40:20
回答 1查看 423关注 0票数 3

我想在RichTextBlock中突出显示所选文本,但当我在选择文本后单击"btnHighlight“按钮时,突出显示的文本与所选内容不匹配(可能是因为超链接,但您如何解决它?)。我哪里错了?

MainPage.xaml:

代码语言:javascript
复制
<Grid>
    <RichTextBlock Name="Rtb" Margin="0,150,0,150" Width="300">
        <Paragraph TextIndent="0">
            <Hyperlink UnderlineStyle="None" CharacterSpacing="0">
                <Run Text="1" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text a" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="2" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text b" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="3" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text c" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="4" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text d" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="5" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text e" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="6" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text f" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="7" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text g" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="8" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text h" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="9" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text i" FontSize="20"/>
            <Hyperlink UnderlineStyle="None">
                <Run Text="10" FontSize="20" FontWeight="Bold"/>
            </Hyperlink>
            <Run Text="Text l" FontSize="20"/>
        </Paragraph>
    </RichTextBlock>
    <Button x:Name="btnHighlight" Click="btnHighlight_Click" Content="Highlight" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
    <Button x:Name="btnRemoveHighlight" Click="btnRemoveHighlight_Click" Content="Remove" HorizontalAlignment="Left" Margin="110,10,0,0" VerticalAlignment="Top"/>
</Grid>

MainPage.xaml.cs:

代码语言:javascript
复制
private void btnHighlight_Click(object sender, RoutedEventArgs e)
{
    int selectionStart = Rtb.SelectionStart.Offset;
    int selectionEnd = Rtb.SelectionEnd.Offset;
    int lenght = selectionEnd - selectionStart;

    TextRange textRange = new TextRange() { StartIndex = selectionStart, Length = lenght };
    TextHighlighter highlighter = new TextHighlighter();
    highlighter.Background = new SolidColorBrush(Colors.Yellow);
    highlighter.Ranges.Add(textRange);
    Rtb.TextHighlighters.Add(highlighter);
}

private void btnRemoveHighlight_Click(object sender, RoutedEventArgs e)
{
    Rtb.TextHighlighters.Clear();
}

提前感谢..!

EN

回答 1

Stack Overflow用户

发布于 2019-03-04 11:25:45

这里的问题是,TextPointer指向富文本结构;它不仅仅是字符串的纯文本版本的索引。富文本的组织方式如下: RichTextBlock有一个Block集合,每个Block是一个具有Inline集合的段落,每个Inline要么是Run (包含文本),要么是Span (包含Inline集合),要么是LineBreak (表示换行符),要么是InlineUIContainer (表示UI内容)。

RichTextBlock也被表示为序列,该序列是通过按顺序遍历该树而获得的。我们为每个元素的开始计算一个偏移量单位(它可以被认为是一个特殊字符),然后我们计算子元素或文本内容所需的偏移量单位,然后为元素的闭合添加一个偏移量单位。为了方便起见,TextPointer中的“偏移”是指直到选定点的偏移单位数。

下面展示了如何遍历富文本并拾取TextPointer之前的文本。树中的每个元素都有ElementStart/ElementEnd和ContentStart/ContentEnd,其中ElementStart/ElementEnd指示其位置,ContentStart/ContentEnd指示内容在其中的位置。字符串中包括位于TextPointer.Offset左侧的内容,例如来自运行的文本。注意事项:未使用换行符或inlineUIContainer进行测试;不处理从右向左的文本;并且效率不是特别高。

代码语言:javascript
复制
static class DocumentHelper
{
    static public string TextUpTo(this InlineCollection inlines, TextPointer pointer)
    {
        StringBuilder textUpTo = new StringBuilder();
        foreach (Inline inline in inlines) {
            if (inline.ElementStart.Offset > pointer.Offset) {
                break;
            }
            if (inline is Run run) {
                // Need some more work here to take account of run.FlowDirection and pointer.LogicalDirection.
                textUpTo.Append(run.Text.Substring(0, Math.Max(0, Math.Min(run.Text.Length, pointer.Offset - run.ContentStart.Offset))));
            } else if (inline is Span span) {
                string spanTextUpTo = span.Inlines.TextUpTo(pointer);
                textUpTo.Append(spanTextUpTo);
            } else if (inline is LineBreak lineBreak) {
                textUpTo.Append((pointer.Offset >= lineBreak.ContentEnd.Offset) ? Environment.NewLine : "");
            } else if (inline is InlineUIContainer uiContainer) {
                textUpTo.Append(" "); // empty string replacing the UI content. 
            } else {
                throw new InvalidOperationException($"Unrecognized inline type {inline.GetType().Name}");
            }
        }
        return textUpTo.ToString();
    }

    static public string TextUpTo( this RichTextBlock rtb, TextPointer pointer)
    {
        StringBuilder textUpTo = new StringBuilder();
        foreach (Block block in rtb.Blocks) {
            if (block is Paragraph paragraph) {
                textUpTo.Append(paragraph.Inlines.TextUpTo( pointer)); 
            } else {
                throw new InvalidOperationException($"Unrecognized block type {block.GetType().Name}");
            }
        }
        return textUpTo.ToString();
    }
}

现在是…至于原问题,我们可以这样做:

代码语言:javascript
复制
    private void BtnHighlight_Click(object sender, RoutedEventArgs e)
    {
        string textUpToStart = this.Rtb.TextUpTo(this.Rtb.SelectionStart);
        string textUpToEnd = this.Rtb.TextUpTo(this.Rtb.SelectionEnd);
        Debug.WriteLine($"Text up to start: '{textUpToStart}'; text up to end: '{textUpToEnd}'");

        TextRange textRange = new TextRange { StartIndex = textUpToStart.Length, Length = (textUpToEnd.Length - textUpToStart.Length) };
        TextHighlighter highlighter = new TextHighlighter() { Ranges = { textRange }, Background = new SolidColorBrush(Colors.Yellow) };
        this.Rtb.TextHighlighters.Add(highlighter);
    }

    private void BtnRemoveHighlight_Click(object sender, RoutedEventArgs e)
    {
        this.Rtb.TextHighlighters.Clear();
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51243602

复制
相关文章

相似问题

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