简体   繁体   中英

how to make wpf textblock autosize

i have a textblock where i dynamically add string.. even if i add string width and update the textblock the textblock is not showing appropriate width, still some text are cut..

how to measure width that has to be displayed in textblock? and how to make it autosize?

You can get the size of a text using these solutions :

Solution 1

You could FormattedText to measure the size of text, here is an example:

String text = "Here is my text";
Typeface myTypeface = new Typeface("Helvetica");
FormattedText ft = new FormattedText(text, CultureInfo.CurrentCulture, 
        FlowDirection.LeftToRight, myTypeface, 16, Brushes.Red);

Size textSize = new Size(ft.Width, ft.Height);

Solution 2

Use the Graphics class (found here ):

System.Drawing.Font font = new System.Drawing.Font("Calibri", 12, FontStyle.Bold);
Bitmap bitmap = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(bitmap);
SizeF measureString = g.MeasureString(text, font);

Here you are !

Textblocks that have no height or width specified will expand automatically until they fill their container. So try that.

Here's a class i've written that does this. It only AutoShrinks but you can add the functionality you need. It uses the parent bounds OR MaxHeight / MaxWidth if they are set.

public class TextBlockAutoShrink : TextBlock
{
    // private Viewbox _viewBox;
    private double _defaultMargin = 6;
    private Typeface _typeface;

    static TextBlockAutoShrink()
    {
        TextBlock.TextProperty.OverrideMetadata(typeof(TextBlockAutoShrink), new FrameworkPropertyMetadata(new PropertyChangedCallback(TextPropertyChanged)));
    }

    public TextBlockAutoShrink() : base() 
    {
        _typeface = new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch, this.FontFamily);
        base.DataContextChanged += new DependencyPropertyChangedEventHandler(TextBlockAutoShrink_DataContextChanged);
    }

    private static void TextPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        var t = sender as TextBlockAutoShrink;
        if (t != null)
        {
            t.FitSize();
        }
    }

    void TextBlockAutoShrink_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        FitSize();
    }

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
    {
        FitSize();

        base.OnRenderSizeChanged(sizeInfo);
    }

    private void FitSize()
    {
        FrameworkElement parent = this.Parent as FrameworkElement;
        if (parent != null)
        {
            var targetWidthSize = this.FontSize;
            var targetHeightSize = this.FontSize;

            var maxWidth = double.IsInfinity(this.MaxWidth) ? parent.ActualWidth : this.MaxWidth;
            var maxHeight = double.IsInfinity(this.MaxHeight) ? parent.ActualHeight : this.MaxHeight;

            if (this.ActualWidth > maxWidth)
            {
                targetWidthSize = (double)(this.FontSize * (maxWidth / (this.ActualWidth + _defaultMargin)));
            }

            if (this.ActualHeight > maxHeight)
            {
                var ratio = maxHeight / (this.ActualHeight);

                // Normalize due to Height miscalculation. We do it step by step repeatedly until the requested height is reached. Once the fontsize is changed, this event is re-raised
                // And the ActualHeight is lowered a bit more until it doesnt enter the enclosing If block.
                ratio = (1 - ratio > 0.04) ? Math.Sqrt(ratio) : ratio;

                targetHeightSize = (double)(this.FontSize *  ratio);
            }

            this.FontSize = Math.Min(targetWidthSize, targetHeightSize);
        }
    }
}

Here is a different way of solving this issue.

Set yourTextBlock.Width = double.NaN and same with Height .

By default, elements have an HorizontalAligment and VerticalAligment properties that are set to Stretch , so they will adapt to their parent.

But if you set these to Center , the element will keep its natural size, so you can test this (or setting properties using code instead of XAML):

<TextBlock Text="This is my text"
      HorizontalAlignment="Center"
      VerticalAlignment="Center"
/>

It worked in my case, maybe not in every case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM