WPF RichTextBox文本导航[已关闭]

50pmv0ei  于 2023-04-22  发布在  其他
关注(0)|答案(1)|浏览(119)

**已关闭。**此问题正在寻求书籍,工具,软件库等的建议。它不符合Stack Overflow guidelines。目前不接受答案。

我们不允许您提问有关书籍、工具、软件库等方面的建议。您可以编辑问题,以便您可以通过事实和引用来回答问题。
4天前关闭。
Improve this question
我正在开发测试应用程序,其中有RichTextBox和几个按钮。该控件包含文本,每当插入符号位置位于当我单击按钮,我想从当前插入符号位置和第三个字后,插入一些文本计数下3个字。
当我试图用WPF RichTextBox来做这件事时,它变得复杂了。在调查过程中,我发现Winfroms命名空间的RichTextBox更容易处理这个任务。
有没有人知道有一个扩展,WPF RichTextBox的包,其工作方式与Winforms的RichTextBox类似?
P.S.如果没有这样的解决方案,请分享我可以深入学习如何使用WPF RichTextBox的位置。
请不要建议在WPF中使用Winforms中的RichTextBox

km0tfn4u

km0tfn4u1#

请参见下面的InsertSomeText(this RichTextBox rtb, int skip, string text)扩展方法。
示例如何使用它:

rtb.InsertSomeText(3, "<Text>");

rtb是对RichTextBox控件的引用。第一个参数skip定义了从当前插入符号位置开始传递多少单词,然后由text参数指定的一些文本将插入到最后一个单词之后。
正则表达式用于分析文本。目前定义了以下字符作为单词分隔符:,.;\s(空格)和\t(制表符)。此列表可根据要求进行更新。有关此模式的其他信息,请参见此处:https://regexr.com/7c53c

public static class RichTextBoxEx
{
    public static void InsertSomeText(this RichTextBox rtb, int skip, string text)
    {
        var textRange = new TextRange(rtb.CaretPosition, rtb.Document.ContentEnd);

        // Build list of Word/TextRange pairs
        var words = CalculateTextRange(textRange, @"[^,.;\s\t]+", skip);

        if (words.Count >= skip)
        {
            var required = words[skip - 1];
            if (required.Item2 is TextRange tr && required.Item1 is string word)
            {                  
                var position = tr.Start.GetPositionAtOffset(word.Length);
                position.InsertTextInRun(text);
                rtb.CaretPosition = position.GetPositionAtOffset(text.Length);
            }
        }
    }

    private static IList<(string, TextRange)> CalculateTextRange(TextRange range, string pattern, int maxwords)
    {
        TextRange search = range;
        int correction = 0;
        var result = new List<(string, TextRange)>();

        // Enumerate all found mathes and creating list of Word/TextRange pairs
        var regExp = new Regex(pattern.ToString(), RegexOptions.IgnoreCase);
        foreach (Match match in regExp.Matches(range.Text))
        {
            if (CalculateTextRange(search, match.Index - correction, match.Length) is TextRange tr)
            {
                result.Add((match.Value, tr));
                correction = match.Index + match.Length;
                search = new TextRange(tr.End, search.End);
                if (--maxwords <= 0)
                    break;
            }
        }
        return result;
    }

    // Returns a `TextRange` of the string started from `iStart` index
    // and having `length` characters or `null` if no string found.
    private static TextRange CalculateTextRange(TextRange search, int iStart, int length)
    {
        return (GetTextPositionAtOffset(search.Start, iStart) is TextPointer start)
            ? new TextRange(start, GetTextPositionAtOffset(start, length))
            : null;
    }

    private static TextPointer GetTextPositionAtOffset(TextPointer position, int offset)
    {
        for (TextPointer current = position; current != null; current = position.GetNextContextPosition(LogicalDirection.Forward))
        {
            position = current;
            var adjacent = position.GetAdjacentElement(LogicalDirection.Forward);
            var context = position.GetPointerContext(LogicalDirection.Forward);
            switch (context)
            {
                case TextPointerContext.Text:
                    int count = position.GetTextRunLength(LogicalDirection.Forward);
                    if (offset <= count)
                    {
                        return position.GetPositionAtOffset(offset);
                    }
                    offset -= count;
                    break;
                case TextPointerContext.ElementStart:
                    if (adjacent is InlineUIContainer)
                        offset--;
                    break;
                case TextPointerContext.ElementEnd:
                    if (adjacent is Paragraph)
                        offset -= 2;
                    break;
                default:
                    break;
            }
        }
        return position;
    }
}

相关问题