The following forum(s) have migrated to Microsoft Q&A (Preview): Developing Universal Windows apps!
Visit Microsoft Q&A (Preview) to post new questions.

Learn More

Reliabily measuring string length in Silverlight RRS feed

  • General discussion

  • I need to perform custom layout of text in my Silverlight app, and to do that I need to be able to measure the length of a string in pixels, using a given font family and size.

    In XNA we could use SpriteFont.MeasureString; is there any reliable way to do the same thing in Silverlight?
    Saturday, May 14, 2011 10:54 AM

All replies

  • I don't know of a way to do this in Silverlight. I haven't tried it, but there's a method posted here which seems to create an empty Textblock, fill that Textblock with the and then measure the size of the Textblock. Seems like a good workaround.
    Saturday, May 14, 2011 1:56 PM
  • That's similar to what I ended up doing. The problem is that layout for a TextBlock isn't guaranteed to be completed right after you create it, so in some cases ActualWidth/ActualHeight will return zero.

    Every frame Silverlight will perform a Measure/Arrange pass on all controls that need it, and it's during this layout pass that ActualWidth/Height are actually updated. Worse, it can take multiple frames for Silverlight to find the final ActualWidth/Height of the control. So the only way to reliably get ActualWidth/ActualHeight is to wait a number of frames for Silverlight to complete layout.

    Essentially what you have to do is:

    1. Create a TextBlock and fill it with the text and font you want to measure.
    2. Call Dispatcher.BeginInvoke to get ActualWidth and ActualHeight of the TextBlock on the UI thread, and wait for it to return
    3. Go to 2. until ActualWidth and ActualHeight stop changing

    It's possibly the most convoluted solution to a simple problem that I've ever seen. It also means that if your code is running on the UI thread, you can't reliably get ActualWidth/ActualHeight becuase Silverlight performs layout on the UI thread as well - there's no way to wait for the UI thread to perform layout if you're currently on the UI thread in the first place.

    Surely there's a more sane solution to this problem?

    Sunday, May 15, 2011 12:56 AM
  • We were using the old CTP at this point, but I'm not sure if the issue got fixed. However, you might find this thread interesting regarding why ActualHeight and ActualWidth return zero, and how to fix it.
    Sunday, May 15, 2011 1:06 AM
  • Get the value of ActualWidth property inside the event handler of the SizeChanged event.

    var textWidth;
    textBlock1.SizeChanged += ((sender, e) => textWidth = this.ActualWidth);

    somthing like that.
    Wednesday, August 31, 2011 6:09 AM