18

In WPF, this was possible using FormattedText, like this:

private Size MeasureString(string candidate)
{
    var formattedText = new FormattedText(
        candidate,
        CultureInfo.CurrentUICulture,
        FlowDirection.LeftToRight,
        new Typeface(this.textBlock.FontFamily, this.textBlock.FontStyle, this.textBlock.FontWeight, this.textBlock.FontStretch),
        this.textBlock.FontSize,
        Brushes.Black);

    return new Size(formattedText.Width, formattedText.Height);
}

But in UWP this class does not exist any more. So how is it possible to calculate text dimensions in universal windows platform?

Justin XL
  • 38,763
  • 7
  • 88
  • 133
Domysee
  • 12,718
  • 10
  • 53
  • 84

3 Answers3

40

In UWP, you create a TextBlock, set its properties (like Text, FontSize), and then call its Measure method and pass in infinite size.

var tb = new TextBlock { Text = "Text", FontSize = 10 };
tb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));

After that its DesiredSize property contains the size the TextBlock will have.

Domysee
  • 12,718
  • 10
  • 53
  • 84
  • 5
    @Reddy I'm not that fast (although I wish I were). There is an "answer your own question" checkbox when asking a question. I did this because I didn't find any question or answer to this problem on SO, so that others will find it (hopefully) and dont have to search hours for it. – Domysee Mar 13 '16 at 10:28
  • 5
    Please note that this isn't specific to UWP. It would as well work in WPF or Silverlight. – Clemens Mar 13 '16 at 13:45
  • @MarcelW Not sure what you mean. That works well for me, also in WPF. – Clemens Apr 28 '16 at 12:52
  • 1
    This is slow to run and has to run on the UI thread. Can anyone find an alternative that can run on a background thread? – Paymon Jan 17 '17 at 10:24
  • @Paymon: Perhaps [this answer](https://stackoverflow.com/a/45937298/426227) can help you. – testing Aug 29 '17 at 10:56
  • You can use this to measure a Button by setting the FontFamily, FontSize, FontStretch, and FontWeight of the TextBlock from the matching properties of the Button, and then adding in the Margin, Padding, and BorderThickness. – sjb-sjb Jan 06 '18 at 03:21
  • UWP this does not work if the TextBlock has styles. These affect the measurement process, so be wary of that. For example MinWidth and MaxWidth can take effect, and your DesiredSize can be 900px Width for a 4 character string! – escape-llc Feb 24 '22 at 15:35
7

Here is an alternative approach using Win2D:

private Size MeasureTextSize(string text, CanvasTextFormat textFormat, float limitedToWidth = 0.0f, float limitedToHeight = 0.0f)
{
    var device = CanvasDevice.GetSharedDevice();

    var layout = new CanvasTextLayout(device, text, textFormat, limitedToWidth, limitedToHeight);

    var width = layout.DrawBounds.Width;
    var height = layout.DrawBounds.Height;

    return new Size(width, height);
}

You can use it like this:

string text = "Lorem ipsum dolor sit amet";

CanvasTextFormat textFormat = new CanvasTextFormat
{
    FontSize = 16,
    WordWrapping = CanvasWordWrapping.WholeWord,
};

Size textSize = this.MeasureTextSize(text, textFormat, 320.0f);

Source

testing
  • 19,681
  • 50
  • 236
  • 417
  • 1
    This is excellent! Unfortunately in some cases it gives my weird results: check my question here https://stackoverflow.com/questions/55801411/uwp-compute-text-height-in-a-richtextblock-gives-weird-results – Cristiano Ghersi Apr 22 '19 at 21:41
  • @CristianoGhersi: If it is a text intendation problem, what if you use a fixed value as workaround? Otherwise I think you have to use another solution ... – testing Apr 23 '19 at 06:54
  • a fixed value could work perfectly fine, could you expand a little bit more on this idea? e.g. where do you envision to place the fixed value? – Cristiano Ghersi Apr 23 '19 at 16:12
  • Intuitively, I would say in `GetRichTextHeight()` before returning `finalH` you take the indentation into account. – testing Apr 24 '19 at 08:30
  • What I came out with is we could "fake" the indentation by adding extra trailing spaces at the beginning of the string. But it is still not clear to me a good function to translate e.g Indentation = 10pt into the number of spaces that I have to add to the string to compute the right finalH. – Cristiano Ghersi Apr 24 '19 at 15:41
  • That is the question. I'd try different values to see, which one would work for most cases. It also depends on the font size and so on I think. Perhaps you can use another (calculated) size and create some kind of formula. – testing Apr 25 '19 at 14:46
  • 1
    Use `layout.LayoutBounds` instead of `layout.DrawBounds`. `LayoutBounds` will give you the expected result. – Mohit Atray Jun 11 '20 at 17:46
1

If you are having issues in UWP with Size not resolving or working properly with double's. It is probably because you are using System.Drawing.Size.

Use Windows.Foundation.Size instead.

Post Impatica
  • 14,999
  • 9
  • 67
  • 78
  • This is a major omission from the original answer. It's important to fully qualify your types in C# answers or add your usings. – wildbagel Apr 18 '22 at 16:45