2013-02-15 2 views
1

Мне нужно добавить некоторое украшение в содержимое элемента управления TextBox WPF. Это прекрасно работает в принципе, я могу получить положение указанных индексов символов и компоновку моих других элементов соответственно. Но все это ломается при прокрутке TextBox. Мои позиции макета больше не совпадают с отображаемым текстом, потому что он переместился в другое место.Получить позицию прокрутки текстового поля WPF

Теперь я очень удивлен тем, что класс TextBox не предоставляет никакой информации о его состоянии прокрутки и каких-либо событиях, когда скроллинг изменился. Что я могу сделать сейчас?

Я использовал Snoop, чтобы узнать, есть ли какой-то прокрутки прокрутки, которые я мог бы задать, но ScrollContentPresenter также не имеет доступной информации прокрутки. Я бы очень хотел поместить элементы оформления прямо в прокрученную область, чтобы прокрутка также могла повлиять на них, но может быть только один элемент управления содержимым, и это уже один из внутренних элементов TextBox.

+0

Возможно, попробуйте подписаться на прокручиваемое событие ScrollViewer.ScrollChanged? Он предоставляет информацию, такую ​​как высота экстента, смещение прокрутки, размер видового экрана (все в горизонтальном и вертикальном размерах), возможно, это поможет. Я не совсем уверен, что понимаю вашу задачу полностью. Но попробуй. – Haspemulator

ответ

1

Вы можете получить ScrollViewer с помощью этого метода, передав в текстовое поле как аргумент и тип ScrollView. Затем вы можете подписаться на событие ScrollChanged.

public static T FindDescendant<T>(DependencyObject obj) where T : DependencyObject 
{ 
    if (obj == null) return default(T); 
    int numberChildren = VisualTreeHelper.GetChildrenCount(obj); 
    if (numberChildren == 0) return default(T); 

    for (int i = 0; i < numberChildren; i++) 
    { 
     DependencyObject child = VisualTreeHelper.GetChild(obj, i); 
     if (child is T) 
     { 
      return (T)(object)child; 
     } 
    } 

    for (int i = 0; i < numberChildren; i++) 
    { 
     DependencyObject child = VisualTreeHelper.GetChild(obj, i); 
     var potentialMatch = FindDescendant<T>(child); 
     if (potentialMatch != default(T)) 
     { 
      return potentialMatch; 
     } 
    } 

    return default(T); 
} 

Пример:

public MainWindow() 
{ 
    InitializeComponent(); 
    Loaded += new RoutedEventHandler(MainWindow_Loaded); 
} 

void MainWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    ScrollViewer s = FindDescendant<ScrollViewer>(txtYourTextBox); 
    s.ScrollChanged += new ScrollChangedEventHandler(s_ScrollChanged); 
} 

void s_ScrollChanged(object sender, ScrollChangedEventArgs e) 
{ 
    // check event args for information needed 
} 
4

Я не уверен, как захватить событие, когда текстовое поле прокручивается (возможно использовать ответ narohi в для этого), но есть простой способ увидеть, что текущая позиция прокрутки:

// Gets or sets the vertical scroll position. 
textBox.VerticalOffset 

(От http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.textboxbase.verticaloffset(v=vs.100).aspx)

Я использую его посмотрите, прокручивается ли текстовое поле до конца, например:

public static bool IsScrolledToEnd(this TextBox textBox) 
{ 
    return textBox.VerticalOffset + textBox.ViewportHeight == textBox.ExtentHeight; 
} 
+0

Джон, спасибо, я попробовал свой IsScrolledToEnd. Обычно это работает, но не всегда. Проблема в том, что вы сравниваете удвоения с оператором ==. Я думаю, что в этом сравнении должно быть 1 терминирование, например: 'bool scrollToEnd = Memo.VerticalOffset> Memo.ExtentHeight - Memo.ViewportHeight - fontHeight;' – Aleksandr

Смежные вопросы