none
Прокрутка в положение CaretPosition для RichTextBox WPF RRS feed

  • Вопрос

  • Не пойму, почему RichTextBox при установке свойства CaretPosition не прокручивается в это положение, если оно выходит за пределы отображаемого в текущий момент содержимого RichTextBox.

    Методы прокрутки в начало и в конец есть (ScrollToEnd, ScrollToHome соответственно).

    А как прокрутить в позицию, где установлен текстовый курсор?

    23 июля 2012 г. 6:28

Ответы

  • Итоговый работоспособный вариант:

    double offset = position.GetCharacterRect(LogicalDirection.Forward).Top;
    richTextBox1.ScrollToVerticalOffset(offset + richTextBox1.VerticalOffset - 5); // 5 - чтобы не в самый верх упирался текст

    • Помечено в качестве ответа tulosba 23 июля 2012 г. 13:18
    23 июля 2012 г. 13:17
  • Делаю, как и в предыдущих моих темах, поиск и выделение текста внутри документа.

    1. Ваш пример модифицировал, перенеся код наполнения в загрузку формы и все стало работать.

    2. Из документации следует, что одним из главных недостатков RichTextBox это отсутствие встроенных возможностей поиска и выделения, из за чего часто приходится изобретать велосипед. Возможно тут уже есть изобретенный. Задавайте в поиск WPF RichTextBox


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Помечено в качестве ответа Abolmasov Dmitry 27 июля 2012 г. 11:16
    23 июля 2012 г. 9:18
    Отвечающий
  • 1. Ваш пример модифицировал, перенеся код наполнения в загрузку формы и все стало работать.

    Получается есть какая-то связь между фокусом и изменением документа RichTextBox.

    Нашел ещё вот такой метод позиционирования:

    TextPointer position = richTextBox1.CaretPosition;
    double offset = position.GetCharacterRect(LogicalDirection.Forward).Top;
    richTextBox1.ScrollToVerticalOffset(offset);
    Работает без необходимости вызова фокуса, но если не скроллить RichTextBox в начало ручками, то происходит какое-то подёргивание и после нескольких итераций позиция уползает с экрана.


    • Помечено в качестве ответа Abolmasov Dmitry 27 июля 2012 г. 11:16
    23 июля 2012 г. 12:39

Все ответы

  • Получилось заставить сделать автопрокрутку добавив перед установкой CaretPosition сроку:

    rtb.Focus();


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    23 июля 2012 г. 7:47
    Отвечающий
  • Получилось заставить сделать автопрокрутку добавив перед установкой CaretPosition сроку:

    rtb.Focus();

    Какая-то залепуха, если честно. ScrollToEnd(), ScrollToHome() работают из без передачи фокуса. Получается надо сначала установить фокус, а потом вернуть его в прежнее место.

    В любом случае, спасибо за ответ.

    23 июля 2012 г. 8:07
  • А есть ли какие-то ограничения на установку фокуса для элемента по времени между вызовами или какие-то другие? Если например из обработчика нажатия кнопки вызываю такой код:

    richTextBox1.Focus();
    richTextBox1.CaretPosition = newPosition;
    ((UIElement)sender).Focus(); // Возвращаем фокус
    то не происходит прокрутка на CaretPosition, несмотря на предварительный вызов Focus().
    23 июля 2012 г. 8:19
  • Какая-то залепуха, если честно. ScrollToEnd(), ScrollToHome() работают из без передачи фокуса. Получается надо сначала установить фокус, а потом вернуть его в прежнее место.

    В любом случае, спасибо за ответ.

    Есть еще ScrollToVerticalOffsetкоторый скорее всего и вызывается внутренним кодом при установке CaretPosition, но не работает при отсутствии фокуса. Специально так сделано или это внутренние заморочки мы не узнаем, но решение найдено и это хорошо.

    Не забывайте отметить ответ, решивший вашу проблему.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    23 июля 2012 г. 8:19
    Отвечающий
  • А есть ли какие-то ограничения на установку фокуса для элемента по времени между вызовами или какие-то другие? Если например из обработчика нажатия кнопки вызываю такой код:

    richTextBox1.Focus();
    richTextBox1.CaretPosition = newPosition;
    ((UIElement)sender).Focus(); // Возвращаем фокус
    то не происходит прокрутка на CaretPosition, несмотря на предварительный вызов Focus().
    Откровенно говоря не догадываюсь какие факторы тут могут влиять. У меня даже при воспроизведении вашей ситуации все равно происходит прокрутка.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    23 июля 2012 г. 8:31
    Отвечающий
  • Да и еще - CaretPosition это каретка ввода и логично, что элемент должен иметь фокус для ввода в данном месте. Может есть альтернатива CaretPosition в вашей ситуации. Что именно вы делаете?

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    23 июля 2012 г. 8:35
    Отвечающий
  • Откровенно говоря не догадываюсь какие факторы тут могут влиять. У меня даже при воспроизведении вашей ситуации все равно происходит прокрутка.

    Попробуйте проверить элементарный пример:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        for( int i=0; i<300; ++i )
        {
            richTextBox1.AppendText( i.ToString() );
        }
        richTextBox1.Focus();
        richTextBox1.CaretPosition = richTextBox1.Document.ContentEnd;
        ((UIElement)sender).Focus(); // Если убрать, то скроллит. Иначе - нет.
    }

    Форма

    <Window x:Class="CaretPositionTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <RichTextBox Height="152" HorizontalAlignment="Left" Margin="12,12,0,0" Name="richTextBox1" VerticalAlignment="Top" Width="280" />
            <Button Content="FillAndScroll" Height="23" HorizontalAlignment="Left" Margin="12,178,0,0" Name="button1" VerticalAlignment="Top" Width="280" Click="button1_Click" />
        </Grid>
    </Window>

    23 июля 2012 г. 9:00
  • Да и еще - CaretPosition это каретка ввода и логично, что элемент должен иметь фокус для ввода в данном месте. Может есть альтернатива CaretPosition в вашей ситуации. Что именно вы делаете?
    Делаю, как и в предыдущих моих темах, поиск и выделение текста внутри документа.
    23 июля 2012 г. 9:02
  • Делаю, как и в предыдущих моих темах, поиск и выделение текста внутри документа.

    1. Ваш пример модифицировал, перенеся код наполнения в загрузку формы и все стало работать.

    2. Из документации следует, что одним из главных недостатков RichTextBox это отсутствие встроенных возможностей поиска и выделения, из за чего часто приходится изобретать велосипед. Возможно тут уже есть изобретенный. Задавайте в поиск WPF RichTextBox


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Помечено в качестве ответа Abolmasov Dmitry 27 июля 2012 г. 11:16
    23 июля 2012 г. 9:18
    Отвечающий
  • 1. Ваш пример модифицировал, перенеся код наполнения в загрузку формы и все стало работать.

    Получается есть какая-то связь между фокусом и изменением документа RichTextBox.

    Нашел ещё вот такой метод позиционирования:

    TextPointer position = richTextBox1.CaretPosition;
    double offset = position.GetCharacterRect(LogicalDirection.Forward).Top;
    richTextBox1.ScrollToVerticalOffset(offset);
    Работает без необходимости вызова фокуса, но если не скроллить RichTextBox в начало ручками, то происходит какое-то подёргивание и после нескольких итераций позиция уползает с экрана.


    • Помечено в качестве ответа Abolmasov Dmitry 27 июля 2012 г. 11:16
    23 июля 2012 г. 12:39
  • Итоговый работоспособный вариант:

    double offset = position.GetCharacterRect(LogicalDirection.Forward).Top;
    richTextBox1.ScrollToVerticalOffset(offset + richTextBox1.VerticalOffset - 5); // 5 - чтобы не в самый верх упирался текст

    • Помечено в качестве ответа tulosba 23 июля 2012 г. 13:18
    23 июля 2012 г. 13:17