开发者

WPF TextBox ScrollToLine not updating if visible

I have a Navigation-bar in my program that allows you to navigate the different sections in my TextBox, but the problem I have is that this doesn't work if the Text I am scrolling to is already visible on the screen.

Like in this example, if I try to jump from Section 1 to Section 3, it won't work as it's already visible.

WPF TextBox ScrollToLine not updating if visible

But, in this example if I jump to Section 3, it works fine as it's not already visible.

WPF TextBox ScrollToLine not updating if visible

The scrolling function I use is very simple:

if (nLine > 0 && nLine <= textBox.LineCount)
    textBox.ScrollToLine(nLine - 1); 

I hope that someone can shed some light on an alternative solution that allows me to scroll even if the text is already visible.

Edit: Added solution.

This is a code snippet from my project.

private static void ScrollToLineCallback(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
    var textBox = (TextBox)target;

    int newLineValue;
    if (Int32.TryParse(e.NewValue.ToString(), out newLineValue))
    {
        if (newLineValue > 0 && newLineValue <= textBox.LineCount) // Validate
        {
            textBox.ScrollToLine(newLineValue - 1); // Scroll to Line

            /开发者_开发知识库/ Check and see if we are at the line we want.
            if (textBox.GetFirstVisibleLineIndex() <= newLineValue && textBox.GetLastVisibleLineIndex() >= newLineValue)
            {
                // If not lets move to the desired location
                int newLineCorrectionValue = newLineValue - textBox.GetFirstVisibleLineIndex() - 2; // How much further do we need to scroll down?

                for (int i = 0; i < newLineCorrectionValue; i++)
                {
                    textBox.LineDown(); // Scroll down
                }
            }
        }
    }
}


You could use GetCharacterIndexFromLineIndex to get the index of the beginning of the desired line and then set the CaretIndex to that value.

Because I don't really know, what you are trying to achieve, another possibility is to use LineUp and LineDown in conjunction with GetFirstVisibleLineIndex and GetLastVisibleLineIndex.


private void TextBoxGotoLine(
    TextBox textbox1, 
    int linenum)
{
  var target_cpos = textbox1.GetCharacterIndexFromLineIndex(linenum);
  var target_char_rect = textbox1.GetRectFromCharacterIndex(target_cpos);
  var first_char_rect = textbox1.GetRectFromCharacterIndex(0);
  textbox1.ScrollToVerticalOffset(
   target_char_rect.Top - 
   first_char_rect.Top
 );
}

I found out if Wrapping is enabled its more complications:

private void TextBoxGotoLine(TextBox textbox1, int linenum)
{
  // int Linenum is the Absolute Line, not including
  //   effect of Textbox Wrapping.

 if (textbox1.TextWrapping == TextWrapping.Wrap)
 {
   // If textbox Wrapping is on, we need to
   // Correct the Linenum for Wrapping which adds extra lines
   int cidx = 0;
   bool found = false;
   int ln = 0;
   char[] tmp = textbox1.Text.ToCharArray();
   for (cidx = 0; cidx < tmp.Length; cidx++)
   {
     if (tmp[cidx] == '\n')
     {
       ln++;
     }
     if (ln == linenum)
     {
       found = true;
       break;
     }
   }
   if (!found) 
     return;

   linenum = textbox1.GetLineIndexFromCharacterIndex(cidx+1);
 }

 // Non-Wrapping TextBox
 var target_cpos = textbox1.GetCharacterIndexFromLineIndex(linenum);
 var target_char_rect = textbox1.GetRectFromCharacterIndex(target_cpos);
 var first_char_rect = textbox1.GetRectFromCharacterIndex(0);
            textbox1.ScrollToVerticalOffset(target_char_rect.Top - first_char_rect.Top);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜