Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Fontsize for TextBlock with wrapping

Tags:

c#

windows-8

xaml

I have a TextBlock with a fixed size thats wrapping text. sometimes short sometimes long.

If the text is getting to long it isnt displayed entirely like this

enter image description here

How can i make the Fontsize flexible to make the text fit the TextBox with static size?

like image 326
Ostkontentitan Avatar asked Dec 20 '22 11:12

Ostkontentitan


1 Answers

My solution is the following:

Set the fontsize to a value, than which you don't want any bigger. The ActualHeight of the TextBlock changes, when you change the font size or when the content is changed. I built the solution based upon this. You should create an event handler for the SizeChanged event and write the following code to it.

private void MyTextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
    double desiredHeight = 80; // Here you'll write the height you want the text to use

    if (this.MyTextBlock.ActualHeight > desiredHeight)
    {
        // You want to know, how many times bigger the actual height is, than what you want to have.
        // The reason for Math.Sqrt() is explained below in the text.
        double fontsizeMultiplier = Math.Sqrt(desiredHeight / this.MyTextBlock.ActualHeight);

        // Math.Floor() can be omitted in the next line if you don't want a very tall and narrow TextBox.
        this.MyTextBlock.FontSize = Math.Floor(this.MyTextBlock.FontSize * fontsizeMultiplier);
    }

    this.MyTextBlock.Height = desiredHeight; // ActualHeight will be changed if the text is too big, after the text was resized, but in the end you want the box to be as big as the desiredHeight.
}

The reason why I used the Math.Sqrt() is that if you set the font size to half as big as before, then the area that the font will use, will be one quarter the size, then before (because it became half as wide and half as tall as before). And you obviously want to keep the width of the TextBox and only change the height of it.

If you were lucky, the font size will be appropriate after this method gets executed once. However, depending on the text that gets re-wrapped after the font size change, you might be so "unlucky", that the text will be one line longer than you would want it to be. Luckily the event handler will be called again (because you changed the font size) and the resizing will be done again if it is still too big.

I tried it, it was fast and the results looked good. However, I can imagine, that in a really unlucky choice of text and height, the correct font size would be reached after several iterations. This is why I used Math.Floor(). All in all, it doesn't matter much if the font size is in the end 12.34 or 12 and this way I wouldn't be concerned about an "unlucky" text, which will take too long to render. But I think Math.Floor() can be omitted if you don't want to have a really tall text box (like 2000 pixels) with a lot of text.

like image 142
Zoltan Toth Avatar answered Dec 29 '22 19:12

Zoltan Toth