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>

    October 27

    PDC 2008

    I'm at PDC at the LA convention center!

    September 27

    Install RAM in the HP 2710P

    This is a how-to guide for installing RAM in the HP 2710P Tablet PC. I purchased 4GB of RAM in 1 GB DIMMS (the sticks that RAM comes in from Crucial at http://www.crucial.com/store/mpartspecs.aspx?mtbpoid=DB47506FA5CA7304).

    Tools Needed:
    • Philips head screwdriver
    • The RAM you want to add J

    clip_image002

    Steps

    1. Shut down the computer and unplug it from the wall. Then, remove the battery. You must remove the battery because if there is current flowing through the motherboard when you install the RAM, you could easily electrocute yourself and/or permanently damage the laptop.

    2. Lay the computer on its back. It should look like this:
    clip_image004

    3. Unscrew the 6 screws from the large panel on the bottom.
    clip_image006

    4. Gently pull the cover up and towards the hinge edge of the computer until it comes off.
    clip_image008

    5. My unit came with a 1GB DIMM installed in the slot on the right. Because I was installing 2, 2GB DIMMS and there are only 2 slots total, I had to remove this 1GB DIMM first. 
    If you are installing 2 DIMM's, you must first remove one the preinstalled DIMM. If you are installing only 1 DIMM, skip to step 8. 
     To remove the DIMM, you need to pull the two metal tabs on the left and right sides of the RAM so that the entire stick will pop up to a 45 degree angle.
    clip_image010

    6. Once the RAM is sticking up like this, you should be able to pull the DIMM out by pulling straight back.
    clip_image012

    7. With the RAM removed, your computer should look like this:
    clip_image014

    8. Install the first new memory module.
    Orient the memory module so that the indent in the pins lines up with the indent in the slot. Then, slide the memory module into the slot at a 45 degree angle.
    clip_image016
    Note the slot in the pins on the DIMM.

    9. When the module is fully inserted, it should still be at a 45 degree angle, and most of the copper pins should be covered up. clip_image018

    10. Push down on the back of the memory module so that it lays flat with the computer. This little metal retention bars should snap into place around the memory module.
    clip_image020

    11. If you are installing more than one module, repeat the 8-10 with the other memory module.
    clip_image022

    12. You have now finished installing the RAM. Slide the computer’s cover back into position at a 45 degree angle.
    clip_image024

    13. Push the top of the panel down and tighten up all of the screws.

    14. Boot the system and make sure it reports the correct amount of RAM.
    To check in Vista, click Start -> Right Click "Computer" ->Select "Properties".
    clip_image026

    September 26

    Musings of a MySpace Database Designer

    It always amazes me how different the rules of the game become when you are dealing with massively scalable data backed applications. According to ComScore, MySpace received 45.4 billion page views for the month of May 2008. That's over 17,000 page views per second. I can't imagine any database system handling that number of simultaneous queries.

    Granted, MySpace's Microsoft SQL Server 2005 databases don't handle that many direct queries. MySpace explained how they have used SQL Server Service Broker along with a strong middle tier caching layer to spread the load over 200 separate MSSQL database servers and many more caching servers. While the technical configuration was amazing, what surprised me more were the normal assumptions that went out the window in building this data layer.

    First, the one cardinal rule of any computer based system that deals with a user's data is that you can't lose/corrupt any of this data—every step should be taken to ensure that the data is in a consistent state even in the case of hardware failure. If, for example, you're a bank, this is really important. You don't want a transfer of money to die in the milliseconds between when money is subtracted from one account and added to another. However, one of the first things the MySpace dev said was, "We're not a bank. If some 15 year old or pedophile loses a friend it's really not a big deal. He's not gonnna jump in front of a bus and kill himself as a result." Actually though… considering some of the emo kids that use MySpace someone just might….

    Anyway, because of this assumption, MySpace has turned off a lot of features such as check constraints on foreign keys simply because they cannot afford the compute cycles to enforce these constraints. If data is inconsistent, that's okay.

    MySpace also buys the standard, not enterprise edition of SQL to save money. As a result, they don't have the clustering and availability features offered by enterprise, but for them, this is an acceptable trade off.

    They don't have any sort of data mirroring strategy. The MySpace profiles are stored across many different databases, with each database holding about 1 million profiles. The dev explained that for performance and cost reasons, they can't afford to do data mirroring or clustering for the profile data. If a million profiles go offline for a couple of hours due to a server crash, that's acceptable. The dev said that on his third week into the job, he accidentally deleted all of the blog entries on the MySpace Japan site. They were able to restore some of the data from backups, but they had turned off transaction logs for cost/performance reasons. As a result, they had lost about 6 hours of blog entries which amounted to about 20,000 posts. His response: "Whoops. My bad." I don't think I'd be able to show my face anywhere near a T-SQL statement after an incident like that…

    I'm fascinated by systems that have to scale to insane loads. I know that MySpace's highly dynamic nature doesn't lend itself well to being bound by stringent processes and laborious load testing. I understand that they have a need to continuously push out new features because they have to offer more compelling features than Facebook and a 3 week QA process is too long. But, I have to wonder if you could design a database that enforces constraints and provides complete transactional integrity that can service the load for a site like MySpace…