Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在wpfrichtextbox控件中,获取单词cursor的方法是打开的_C#_Wpf_Cursor_Richtextbox_Selection - Fatal编程技术网

C# 在wpfrichtextbox控件中,获取单词cursor的方法是打开的

C# 在wpfrichtextbox控件中,获取单词cursor的方法是打开的,c#,wpf,cursor,richtextbox,selection,C#,Wpf,Cursor,Richtextbox,Selection,我想知道如何在WPF RichTextBox中获取当前光标所在的单词。我知道RichTextBox具有Selection属性。但是,这只提供RichTextBox中突出显示的文本。相反,我想知道光标所在的单词,即使整个单词没有突出显示。 任何提示都将不胜感激。 非常感谢。您可以通过获取光标的当前位置 不幸的是,没有简单的方法将字符置于插入符号位置的左/右。我所知道的从RichTextBox中获取文本的唯一方法是in,这有点复杂。但它会完成必要的任务。好吧,为了解决这个问题,我用蛮力强迫它。



我想知道如何在WPF RichTextBox中获取当前光标所在的单词。我知道RichTextBox具有Selection属性。但是,这只提供RichTextBox中突出显示的文本。相反,我想知道光标所在的单词,即使整个单词没有突出显示。

任何提示都将不胜感激。


非常感谢。

您可以通过获取光标的当前位置


不幸的是,没有简单的方法将字符置于插入符号位置的左/右。我所知道的从RichTextBox中获取文本的唯一方法是in,这有点复杂。但它会完成必要的任务。

好吧,为了解决这个问题,我用蛮力强迫它。

我曾经
curCaret.get运行(LogicalDirection.Backward)
curCaret.get运行(LogicalDirection.Forward)


以及
precretstring.LastIndexOf(“”)和
postaretString.IndexOf(“”)以及其他分隔单词和获取子字符串的分隔符。

最后,我添加了字符串的前半部分和后半部分,以获得当前被诅咒的单词。


我打赌有更聪明的方法可以做到这一点,但至少解决了这个问题

将此函数附加到任意RichTextBox(现在称为testRTB)上,并查看输出窗口以获取结果:

private void testRTB_MouseUp(object sender, MouseButtonEventArgs e)
{
        TextPointer start = testRTB.CaretPosition;  // this is the variable we will advance to the left until a non-letter character is found
        TextPointer end = testRTB.CaretPosition;    // this is the variable we will advance to the right until a non-letter character is found

        String stringBeforeCaret = start.GetTextInRun(LogicalDirection.Backward);   // extract the text in the current run from the caret to the left
        String stringAfterCaret = start.GetTextInRun(LogicalDirection.Forward);     // extract the text in the current run from the caret to the left

        Int32 countToMoveLeft = 0;  // we record how many positions we move to the left until a non-letter character is found
        Int32 countToMoveRight = 0; // we record how many positions we move to the right until a non-letter character is found

        for (Int32 i = stringBeforeCaret.Length - 1; i >= 0; --i)
        {
            // if the character at the location CaretPosition-LeftOffset is a letter, we move more to the left
            if (Char.IsLetter(stringBeforeCaret[i]))
                ++countToMoveLeft;
            else break; // otherwise we have found the beginning of the word
        }


        for (Int32 i = 0; i < stringAfterCaret.Length; ++i)
        {
            // if the character at the location CaretPosition+RightOffset is a letter, we move more to the right
            if (Char.IsLetter(stringAfterCaret[i]))
                ++countToMoveRight;
            else break; // otherwise we have found the end of the word
        }



        start = start.GetPositionAtOffset(-countToMoveLeft);    // modify the start pointer by the offset we have calculated
        end = end.GetPositionAtOffset(countToMoveRight);        // modify the end pointer by the offset we have calculated


        // extract the text between those two pointers
        TextRange r = new TextRange(start, end);
        String text = r.Text;


        // check the result
        System.Diagnostics.Debug.WriteLine("[" + text + "]");
}
private void testRTB_MouseUp(对象发送器,MouseButtonEventArgs e)
{
TextPointer start=testRTB.CaretPosition;//这是我们将向左推进的变量,直到找到非字母字符为止
TextPointer end=testRTB.CaretPosition;//这是我们将向右推进的变量,直到找到非字母字符为止
String stringBeforeCaret=start.getterimeran(LogicalDirection.Backward);//从左边的插入符号中提取当前运行中的文本
String stringAfterCaret=start.getTerimeRun(LogicalDirection.Forward);//从左边的插入符号中提取当前运行中的文本
Int32 countToMoveLeft=0;//记录在找到非字母字符之前向左移动的位置数
Int32 counttomoryRight=0;//我们记录在找到非字母字符之前向右移动的位置
对于(Int32 i=stringBeforeCaret.Length-1;i>=0;--i)
{
//如果CaretPosition LeftOffset位置处的字符是一个字母,我们将向左移动更多
if(字符Isleter(stringBeforeCaret[i]))
++倒计时;
else break;//否则我们找到了单词的开头
}
对于(Int32 i=0;i
根据您是否希望保留数字,将Char.IsLetter(…)更改为Char.IsLetterOrDigit(…)或任何其他适当的选项


提示:将其提取到单独程序集中的扩展方法中,以便在需要时对其进行访问。

因为单词是由空格分割的,所以您可以在插入符号周围循环,直到找到空格为止。即使您的
RichTextBox
包含不同的字体和字体大小,此功能也应该可以工作

    public string GetWordByCaret(LogicalDirection direction)
    {
        // Get the CaretPosition
        TextPointer position = this.CaretPosition;
        TextPointerContext context = position.GetPointerContext(direction);

        string text = string.Empty;

        // Iterate through the RichTextBox based on the Start, Text and End of nearby inlines
        while (context != TextPointerContext.None)
        {
            // We are only interested in the text here
            //, so ignore everything that is not text
            if (context == TextPointerContext.Text)
            {
                string current = position.GetTextInRun(direction);

                // The strings appended based on whether they are before the caret or after it...
                // And well...I love switches :)
                switch (direction)
                {
                    case LogicalDirection.Backward:
                        {
                            int spaceIndex = current.LastIndexOf(' ');

                            // If space is found, we've reached the end
                            if (spaceIndex >= 0)
                            {
                                int length = current.Length - 1;

                                if (spaceIndex + 1 <= length)
                                {
                                    text = current.Substring(spaceIndex + 1, length - spaceIndex) + text;
                                }

                                return text;
                            }

                            else
                                text = current + text;
                        }
                        break;

                    default:
                        {
                            int spaceIndex = current.IndexOf(' ');

                            // If space is found, we've reached the end
                            if (spaceIndex >= 0)
                            {
                                int length = current.Length;

                                if (spaceIndex <= length)
                                {
                                    text += current.Substring(0, spaceIndex);
                                }

                                return text;
                            }

                            else
                                text += current;
                        }
                        break;
                }
            }

            // Move to the next position
            position = position.GetNextContextPosition(direction);

            // Get the next context
            if (position != null)
                context = position.GetPointerContext(direction);
            else
                context = TextPointerContext.None;
        }
        return text;
    }

下面是我使用LINQ和Dependency属性的替代解决方案:

public class SelectionRichTextBox : RichTextBox
{
    public SelectionRichTextBox()
    {
        // Use base class style
        SetResourceReference(StyleProperty, typeof(RichTextBox));
    }

    public static readonly DependencyProperty SelectedWordProperty =
        DependencyProperty.Register(
                "SelectedWord",
                typeof(string),
                typeof(SelectionRichTextBox),
                new PropertyMetadata("")
                );

    public string SelectedWord
    {
        get
        {
            return (string)GetValue(SelectedWordProperty);
        }
        set
        {
            SetValue(SelectedWordProperty, value);
        }
    }

    protected override void OnMouseUp(MouseButtonEventArgs e)
    {
        TextPointer cursorPosition = CaretPosition;

        string strBeforeCursor = cursorPosition.GetTextInRun(LogicalDirection.Backward);
        string strAfterCursor = cursorPosition.GetTextInRun(LogicalDirection.Forward);

        string wordBeforeCursor = strBeforeCursor.Split().Last();
        string wordAfterCursor = strAfterCursor.Split().First();

        string text = wordBeforeCursor + wordAfterCursor;

        SelectedWord = string.Join("", text
            .Where(c => char.IsLetter(c))
            .ToArray());

        base.OnMouseUp(e);
    }
}
之后,您可以在绑定中使用它,如下所示:

    <custom:SelectionRichTextBox
            SelectedWord="{Binding SelectedWord, Mode=OneWayToSource}"/>


非常感谢您的回复。我真的很感激你给我的建议。但是,正如您所描述的,似乎没有简单的方法来确定光标所在单词的开头,如Document.ContentStart和Document.ContentEnd指向句子的开头和结尾。可能我需要从TextPointer位置搜索空白。(但接下来我会与没有空间来确定单独单词的2字节单词进行斗争)我猜这个问题已经讨论了很长一段时间了。。。
    <custom:SelectionRichTextBox
            SelectedWord="{Binding SelectedWord, Mode=OneWayToSource}"/>