Sean's profileBelow ZBBBlog Tools Help

Blog


    April 20

    Scrolling a WPF Textbox to a Particular Word

    I need to build a concordance analysis control in WPF for a consulting project I'm working on. In order to do this, I'm using a series of WPF TextBoxes that will be scrolled to center a particular word. Unfortunately, I couldn't find any good tutorials on how to programmatically scroll a text box to a particular point. After playing around with the framework, I've finally figured out how to do this.

    For some reason, the TextBox's BringIntoView() method doesn't seem to actually do anything. I'm really not sure why. What does work, however, is the ScrollToHorizontalOffset(double offset) method. Unfortunately, the MSDN documentation doesn't give a lot of guidance as to what the double parameter is and how to go about correlating this with a character offset in the text of your text box. It turns out that this double parameter is a WPF Point measurement.

    So, how do you go about correlating this offset with a character position? The GetRectFromCharacterIndex(int) method will give you a rectangle (basically a left, top, right, and bottom set of doubles) that indicates the position of a character in the TextBox.

    If you start with your textbox scrolled all the way to the left, and then call Rectangle rectStartChar = GetRectFromCharacterIndex(143), for example, you will get a rectangle representing the position of the 143rd character in your textbox.

    You can then take the rectangle's left point and feed that into the TextBox.ScrollToHorizontalOffset's method. This would look like:

    txtBox.ScrollToHorizontalOffset(txtBox.GetRectFromCharacterIndex(143).Left);

    This will work assuming that you always start scrolling from the leftmost position in the textbox. What gets confusing is if your text box is has already been scrolled (by say your user or another call to this scroll code) and you then want to scroll to a new location. Calls to GetRectFromCharacterIndex will actually return point values that are relative to the current scroll position on the textbox. That is, if you have the text "The quick brown fox jumped over the lazy dog," the first time you try to get the Leftmost point on the Rectangle that covers the letter j (GetRectFromCharacterIndex(20)), you will get a value like 1433. If you scroll to this value (txtBox.ScrollToHorizontalOffset(1433)), and then call GetRectFromCharacterIndex(20) again, you'll get 0, not 1433. However, if you programmatically scroll to position 0 (txtBox.ScrollToHorizontalOffset(0)), your textbox will scroll all the way to the left. Not desired behavior. It turns out that TextBox.GetRectFromCharacterIndex(int), actually returns relative positions (including negative values) even though the MSDN documentation says it returns a value based on a 0 based index. So, to correctly scroll, you need to compute how far you are from the start of the textbox and then subtract that from the value you want to scroll to. All said, your code would look like this:

    C#

    //Get the index of the character you want to scroll to

    int startChar = 142;

     

    //Get a rectangle that represents this character's position in the box

    Rect start = txtBox.GetRectFromCharacterIndex(startChar, false);

     

    //Get a rectangle that represents the leftmost corner of the box. This may be a negative value like (-1832.234)

    Rect farLeft = txtBox.GetRectFromCharacterIndex(0, false);


    //Scroll the textbox to the correct left point of rectangle of the character I'd like to start from + however far in from the start of the text I'm currently scrolled in
    txtBox.ScrollToHorizontalOffset(start.Left + Math.Abs(farLeft.Left));

     

    XAML:

    <TextBox Name="txtBox"> The quick brown fox jumped over the lazy dog. I need some more characters to fill up text in this box. I really wish there was a button in Visual Studio to just type a bunch of dummy values. I could write a code snippet I suppose, but that's too much work for right now. </TextBlock>

    Comments

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Trackbacks

    The trackback URL for this entry is:
    http://belowzbb.spaces.live.com/blog/cns!13290BC9C96A12C!183.trak
    Weblogs that reference this entry
    • None