How to reduce font size based on Textblock size

Pratham Jain 311 Reputation points
2023-10-02T14:32:18.0866667+00:00

Hi All, I have a Textblock inside WPF grid which can span to 1 to n rows based on some conditions. When Textblock is spanned to two or more rows it mostly displays the text completely due to textwrapping set to "wrap". But when Textblock is positioned in only one row in grid the longer text gets cutted which really makes the UI look bad. So, please advise how can I reduce the font size for textblocks having longer texts. Regards, Pratham

Developer technologies | Windows Presentation Foundation
0 comments No comments
{count} votes

Answer accepted by question author
  1. Hui Liu-MSFT 48,706 Reputation points Microsoft External Staff
    2023-10-03T02:33:37.3033333+00:00

    Hi,@Pratham Jain .Welcome Microsoft Q&A.

    You could try to refer to the code below to see if it works for you. Please let me know if the problem persists.

    Method 1: You could wrap your TextBlock with a Viewbox in your XAML to allow dynamic resizing.

      
        <Grid ShowGridLines="True">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto" />
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>
            <Viewbox Stretch="Uniform">
                <TextBlock  Text="Your long text here your long text here Your long text hereYour long text hereYour long text hereYour long text hereYour long text hereYour lt here1" TextWrapping="Wrap"/>
            </Viewbox>
            <Viewbox Stretch="Uniform" Grid.RowSpan="2"      Grid.Row="1">
                <TextBlock  Text="Your long text here your long text here Your long text hereYour long text hereYour long text hereYour long text hereYour long text hereYour long text here  Your long text hereYour long text here2" TextWrapping="Wrap"/>
            </Viewbox>
            <Viewbox Stretch="Uniform"       Grid.Row="3">
                <TextBlock  Text="Your long text here your long text here Your long text hereYour long text hereYour long text hereYour long text herext hereYour long text herext hereYour long text hereYour long text hereYour long text here  Your long text hereYour long text here3" TextWrapping="Wrap"/>
            </Viewbox>
         
        </Grid>
    
    

    User's image

    Method 2: Create a class for your attached property. This class should define the attached property and handle changes to the TextBlock's content and size. You can use this attached property in your XAML code to automatically resize a TextBlock:

    
      <Grid ShowGridLines="True">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto" />
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>
          
            <TextBlock local:AutoSizeTextBlockProperty.EnableAutoSize="True" Text="Your long text here your long text here Your long text hereYour long text hereYour long text hereYour long text hereYour long text hereYour long text here  Your long text hereYour long text here1" TextWrapping="Wrap"/>
            <TextBlock Grid.RowSpan="2"      Grid.Row="1" local:AutoSizeTextBlockProperty.EnableAutoSize="True" Text="Your long text here your long text here Your long text hereYour long text hereYour long t long text hereYour long text here2" TextWrapping="Wrap"/>
            <TextBlock       Grid.Row="3" local:AutoSizeTextBlockProperty.EnableAutoSize="True" Text="Your long text here your long text here Your long text hereYour long text hereYour long t long text hereYour long text herehere Your long text hereYour long text hereYour long t long text hereYour lor long text here3" TextWrapping="Wrap"/>
        </Grid>
    

    Codebehind:

    
      public static class AutoSizeTextBlockProperty
        {
            public static readonly DependencyProperty EnableAutoSizeProperty =
                DependencyProperty.RegisterAttached("EnableAutoSize", typeof(bool), typeof(AutoSizeTextBlockProperty), new UIPropertyMetadata(false, OnEnableAutoSizeChanged));
    
            public static bool GetEnableAutoSize(DependencyObject obj)
            {
                return (bool)obj.GetValue(EnableAutoSizeProperty);
            }
    
            public static void SetEnableAutoSize(DependencyObject obj, bool value)
            {
                obj.SetValue(EnableAutoSizeProperty, value);
            }
    
            private static void OnEnableAutoSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                if (d is TextBlock textBlock)
                {
                    if ((bool)e.NewValue)
                    {
                        textBlock.SizeChanged += TextBlockSizeChanged;
                    }
                    else
                    {
                        textBlock.SizeChanged -= TextBlockSizeChanged;
                    }
                }
            }
    
            private static void TextBlockSizeChanged(object sender, SizeChangedEventArgs e)
            {
                if (sender is TextBlock textBlock)
                {
                    if (textBlock.TextWrapping == TextWrapping.Wrap)
                    {
                        // Calculate the available space (width and height)
                        double availableWidth = textBlock.ActualWidth;
                        double availableHeight = textBlock.ActualHeight;
    
                        // Calculate the desired font size based on the available space
                        double fontSize = CalculateFontSize(textBlock.Text, textBlock.FontFamily, textBlock.FontWeight, textBlock.FontStyle, textBlock.FontStretch, availableWidth, availableHeight);
    
                        // Set the new font size
                        textBlock.FontSize = fontSize;
                    }
                }
            }
    
            private static double CalculateFontSize(string text, FontFamily fontFamily, FontWeight fontWeight, FontStyle fontStyle, FontStretch fontStretch, double availableWidth, double availableHeight)
            {
                // Start with a reasonable font size
                double fontSize = 12.0;
    
                // Create a formatted text object to measure text size
                FormattedText formattedText = new FormattedText(text,
                    System.Globalization.CultureInfo.CurrentUICulture,
                    FlowDirection.LeftToRight,
                    new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
                    fontSize,
                    Brushes.Black);
    
                // Adjust font size until it fits within the available space
                while (formattedText.Width > availableWidth || formattedText.Height > availableHeight)
                {
                    fontSize -= 1.0;
    
                    formattedText = new FormattedText(text,
                        System.Globalization.CultureInfo.CurrentUICulture,
                        FlowDirection.LeftToRight,
                        new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
                        fontSize,
                        Brushes.Black);
                }
    
                return fontSize;
            }
        }
    

    The result:

    User's image


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.