gpt4 book ai didi

c# - RichTextBlock 选定文本 UWP

转载 作者:行者123 更新时间:2023-11-30 18:14:05 24 4
gpt4 key购买 nike

我想在 RichTextBlock 中高亮选中的文本,但是当我在选择文本后单击“btnHighlight”按钮时,高亮的文本与选择不匹配(可能是因为超链接,但如何解决它?)。我哪里错了?

主页.xaml:

<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:

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();
}

提前致谢...!

最佳答案

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

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

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

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();
}
}

现在……对于原来的问题,我们可以这样做:

    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();
}

关于c# - RichTextBlock 选定文本 UWP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51243602/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com