lentinant
lentinant

Reputation: 832

Pick font size to fit string to width

There is method MeasureString in Graphics class, which helps user to find out, what size string has for specified font. But what if I want to know opposite - pick proper font size to fit text to width?

Actual use-case: I have multiple TextBlocks, which should have same font size. I'd like to reduce size of text of all blocks, if width of any TextBlock content exceeds certain value (for example, width of TextBlock and some margin). For now, I'm using MeasureString, to calculate some multiplier, which affects font size, but it seems, that it works not as I wanted it to - it leaves way too big gaps.

For example, I have limit of width 75 px, default font size 13, and string with width 125 px. (75/125) * 13 gives me 7.8 font size, which causes string to have 52 px in width (way much smaller than 75).

So, any good ways to do this?

Code In ViewModel:

private int _defaultFontSize = 13;
private int _maxStringSize = 75;
private string _text = "MoreMoreMore"; //test text, which exceeds 75 px

public double NameFontSize
{
    get
    {
        var font = new Font("Segoe UI Light", _defaultNameFontSize);
        double size;
        using (var graphics = Graphics.FromImage(new Bitmap(1, 1)))
        {
            size = graphics.MeasureString(_text, font);
        }

        return Math.Min(1, _maxStringSize/size) * _defaultFontSize;
    }
}

public string Text
{
    get { return _text; }
}

In XAML

<TextBlock Text = "{Binding Text}" FontSize = "{Binding NameFontSize}"/>

Upvotes: 2

Views: 1118

Answers (2)

Clemens
Clemens

Reputation: 128070

You're measuring with different font size units.

The System.Drawing.Font constructor takes an em-size in points, which are 1/72 of an inch

emSize: ... The em-size, in points, of the new font.

while TextBlock.FontSize is given in WPF units, which are 1/96 inch:

... An unqualified value is measured in device independent pixels. ...

Upvotes: 1

larsbw
larsbw

Reputation: 61

What about putting the TextBlock inside a ViewBox and let that take care of the scaling?

<Viewbox Width="75">
    <TextBlock Text="{Binding Text}"/>
</Viewbox>

Upvotes: 1

Related Questions