RichTextBox получает полное слово после щелчка по нему мышью

#c# #wpf #richtextbox

#c# #wpf #richtextbox ричтекстбокс

Вопрос:

Как получить все слово по щелчку мыши? Я знаю, что подобные вопросы уже были, и я смотрел, но по какой-то причине есть странные и очень старые решения для 40 строк кода. Может быть, есть что-то более современное?

Комментарии:

1. Для элемента RichTextBox управления, который имеет несколько типов строк , и их следует анализировать во время сканирования, код в 40 строк — не такое уж плохое решение. Можете ли вы хотя бы показать нам этот код, чтобы мы попытались его улучшить?

2. @Jackdaw Спасибо, что обратили внимание на вопрос. Я прочитал документацию MSDN, ознакомился с предметной областью и обнаружил, что RichTextBox бесполезен в 2021 году. Это тот же ненужный компонент, что и WebBrowser.

Ответ №1:

Приведенный ниже код демонстрирует, как получить слово в текущей позиции курсора в элементе RichTextBox управления.

XAML:

 <Window ... >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <RichTextBox Grid.Row="0" x:Name="rtb" AllowDrop="True" VerticalScrollBarVisibility="Auto" Padding="2"
                    PreviewMouseUp="rtb_PreviewMouseUp" >
            <FlowDocument>
                <Paragraph FontSize="18" TextAlignment="Left" >

                   <!-- The RichTextBox control content should defined be here
                        or use the PASTE command to add some content... -->

                </Paragraph>
            </FlowDocument>
        </RichTextBox> 
        <Button Grid.Row="2" Click="Button_Click">Mark Current Word</Button>                   
    </Grid>
</Window>
 

Приведенная ниже функция получает указатель на позицию, с которой анализируется текст в указанном направлении, чтобы определить границу слова. pattern Переменная определяет набор возможных разделителей слов.

 public static class TextPointerExt
{
    public static TextPointer GetEdgeTextPointer(this TextPointer position, LogicalDirection direction)
    {
        string pattern = @" ,;.!""?"; // Delimiters 
        int step = direction == LogicalDirection.Forward ? 1 : -1;    
        for (; position != null;)
        {
            var text = position.GetTextInRun(direction);    
            int offset = 0;
            int i = direction == LogicalDirection.Forward ? 0 : text.Length - 1;

            for (; i >= 0 amp;amp; i < text.Length; offset  , i  = step)
            {
                if (pattern.Contains(text[i]))
                {
                    return position.GetPositionAtOffset(offset * step, LogicalDirection.Forward);
                }
            }

            position = position.GetPositionAtOffset(offset * step, LogicalDirection.Forward);
            for (TextPointer latest = position; ;)
            {
                if ((position = position.GetNextContextPosition(direction)) == null)
                    return latest;

                var context = position.GetPointerContext(direction);
                var adjacent = position.GetAdjacentElement(direction);    
                if (context == TextPointerContext.Text)
                {
                    if (position.GetTextInRun(direction).Length > 0)
                        break;
                }
                else if (context == TextPointerContext.ElementStart amp;amp; adjacent is Paragraph)
                {
                    return latest;
                }
            }
        }
        return position;
    }
}
 

Пример использования GetEdgeTextPointer() метода для определения текущего выделенного слова:

 public void GetCurrentWord()
{          
    TextPointer current = rtb.CaretPosition;
    var start = current.GetEdgeTextPointer(LogicalDirection.Backward); // Word position before caret
    var end = current.GetEdgeTextPointer(LogicalDirection.Forward); // Word position after caret

    if (start is TextPointer amp;amp; end is TextPointer amp;amp; start.CompareTo(end) != 0)
    {
        TextRange textrange = new TextRange(start, end);
        // Print the found word to the debug window.
        System.Diagnostics.Debug.WriteLine(textrange.Text);

        // Select the found word
        rtb.Selection.Select(start, end);
    }
    rtb.Focus();
}

private void rtb_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    GetCurrentWord();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    GetCurrentWord();
}
 

Ответ №2:

Используйте событие PreviewMouseDown , чтобы выделить все слово целиком. Конечно, в зависимости от функции, которую вы хотите, вы можете использовать аналогичные события

 private void richTextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    TextSelection ts = richTextBox.Selection;
    string text = ts.Text;
    if (!string.IsNullOrEmpty(text))
        MessageBox.Show(text);
}