如何将TextBox控件配置为在文本不再适合一行时自动垂直调整自身大小?

时间:2023-01-29 21:12:15

How do I configure a TextBox control to automatically resize itself vertically when text no longer fits on one line?

如何将TextBox控件配置为在文本不再适合一行时自动垂直调整自身大小?

For example, in the following XAML:

例如,在以下XAML中:

<DockPanel LastChildFill="True" Margin="0,0,0,0">
  <Border Name="dataGridHeader" 
    DataContext="{Binding Descriptor.Filter}"
    DockPanel.Dock="Top"                         
    BorderThickness="1"
    Style="{StaticResource ChamelionBorder}">
  <Border
    Padding="5"
    BorderThickness="1,1,0,0"                            
    BorderBrush="{DynamicResource {ComponentResourceKey TypeInTargetAssembly=dc:NavigationPane, 
    ResourceId={x:Static dc:NavigationPaneColors.NavPaneTitleBorder}}}">
    <StackPanel Orientation="Horizontal">
      <TextBlock                                
        Name="DataGridTitle"                                                                                                
        FontSize="14"
        FontWeight="Bold"                                    
        Foreground="{DynamicResource {ComponentResourceKey 
        TypeInTargetAssembly=dc:NavigationPane, 
        ResourceId={x:Static dc:NavigationPaneColors.NavPaneTitleForeground}}}"/>
      <StackPanel Margin="5,0"  Orientation="Horizontal" 
              Visibility="{Binding IsFilterEnabled, FallbackValue=Collapsed, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"
              IsEnabled="{Binding IsFilterEnabled, FallbackValue=false}"  >                                    
          <TextBlock  />                                                                
          <TextBox    
            Name="VerticallyExpandMe"
            Padding="0, 0, 0, 0"  
            Margin="10,2,10,-1"                                                                                                                                                                                                                     
            AcceptsReturn="True"
            VerticalAlignment="Center"                                    
            Text="{Binding QueryString}"
            Foreground="{DynamicResource {ComponentResourceKey 
            TypeInTargetAssembly=dc:NavigationPane, 
            ResourceId={x:Static dc:NavigationPaneColors.NavPaneTitleForeground}}}">
          </TextBox>
        </StackPanel>                               
    </StackPanel>
  </Border>              
  </Border>
</DockPanel>

The TextBox control named "VerticallyExpandMe" needs to automatically expand vertically when the text bound to it does not fit on one line. With AcceptsReturn set to true, TextBox expands vertically if I press enter within it, but I want it do do this automatically.

名为“VerticallyExpandMe”的TextBox控件需要在绑定到它的文本不适合一行时自动垂直展开。将AcceptsReturn设置为true时,如果我在其中按Enter键,TextBox会垂直展开,但我希望它自动执行此操作。

5 个解决方案

#1


42  

Although Andre Luus's suggestion is basically correct, it won't actually work here, because your layout will defeat text wrapping. I'll explain why.

尽管Andre Luus的建议基本上是正确的,但它实际上并不适用,因为你的布局会打败文本包装。我会解释原因。

Fundamentally, the problem is this: text wrapping only does anything when an element's width is constrained, but your TextBox has unconstrained width because it's a descendant of a horizontal StackPanel. (Well, two horizontal stack panels. Possibly more, depending on the context from which you took your example.) Since the width is unconstrained, the TextBox has no idea when it is supposed to start wrapping, and so it will never wrap, even if you enable wrapping. You need to do two things: constrain its width and enable wrapping.

从根本上说,问题是这样的:文本换行只在元素的宽度受约束时执行任何操作,但是TextBox具有无约束的宽度,因为它是水平StackPanel的后代。 (好吧,两个水平堆栈面板。可能更多,取决于您从中获取示例的上下文。)由于宽度不受约束,TextBox不知道何时应该开始包装,因此它永远不会换行,甚至如果你启用包装。你需要做两件事:约束它的宽度并启用包装。

Here's a more detailed explanation.

这是一个更详细的解释。

Your example contains a lot of detail irrelevant to the problem. Here's a version I've trimmed down somewhat to make it easier to explain what's wrong:

您的示例包含许多与问题无关的详细信息。这是一个我稍微减少的版本,以便更容易解释错误:

<StackPanel Orientation="Horizontal">
    <TextBlock Name="DataGridTitle" />
    <StackPanel
        Margin="5,0"
        Orientation="Horizontal"
        >
        <TextBlock />
        <TextBox
            Name="VerticallyExpandMe"
            Margin="10,2,10,-1"
            AcceptsReturn="True"
            VerticalAlignment="Center"
            Text="{Binding QueryString}"
            >
        </TextBox>
    </StackPanel>
</StackPanel>

So I've removed your containing DockPanel and the two nested Border elements inside of that, because they're neither part of the problem nor relevant to the solution. So I'm starting at the pair of nested StackPanel elements in your example. And I've also removed most of the attributes because most of them are also not relevant to the layout.

所以我删除了你包含的DockPanel和其中的两个嵌套Border元素,因为它们既不是问题的一部分,也不是解决方案的相关内容。所以我从你的例子中的一对嵌套StackPanel元素开始。而且我还删除了大部分属性,因为它们中的大多数也与布局无关。

This looks a bit weird - having two nested horizontal stack panels like this looks redundant, but it does actually make sense in your original if you need to make the nested one visible or invisible at runtime. But it makes it easier to see the problem.

这看起来有点奇怪 - 有两个嵌套的水平堆栈面板看起来多余,但如果您需要在运行时使嵌套的可见或不可见,它确实在您的原始中有意义。但它更容易看到问题。

(The empty TextBlock tag is also weird, but that's exactly as it appears in your original. That doesn't appear to be doing anything useful.)

(空的TextBlock标签也很奇怪,但这与原始文件中显示的完全相同。这似乎没有做任何有用的事情。)

And here's the problem: your TextBox is inside some horizontal StackPanel elements, meaning its width is unconstrained - you have inadvertently told the text box that it is free to grow to any width, regardless of how much space is actually available.

这就是问题所在:你的TextBox位于一些水平的StackPanel元素中,意味着它的宽度不受约束 - 你无意中告诉文本框它可以*地增长到任何宽度,无论实际有多少空间。

A StackPanel will always perform layout that is unconstrained in the direction of stacking. So when it comes to lay out that TextBox, it'll pass in a horizontal size of double.PositiveInfinity to the TextBox. So the TextBox will always think it has more space than it needs. Moreover, when a child of a StackPanel asks for more space than is actually available, the StackPanel lies, and pretends to give it that much space, but then crops it.

StackPanel将始终执行在堆叠方向上不受约束的布局。因此,当布局TextBox时,它会将double.PositiveInfinity的水平大小传递给TextBox。所以TextBox总是认为它有更多的空间而不是它需要的。此外,当StackPanel的子项要求比实际可用空间更多的空间时,StackPanel会说谎,并假装给它那么大的空间,然后裁剪它。

(This is the price you pay for the extreme simplicity of StackPanel - it's simple to the point of being bone-headed, because it will happily construct layouts that don't actually fit. You should only use StackPanel if either you really do have unlimited space because you're inside a ScrollViewer, or you are certain that you have sufficiently few items that you're not going to run out of space, or if you don't care about items running off the end of the panel when they get too large and you don't want the layout system to try to do anything more clever than simply cropping the content.)

(这是你为StackPanel的极端简单所付出的代价 - 它很简单到了骨头,因为它会愉快地构建实际上不适合的布局。如果你真的有无限制,你应该只使用StackPanel空间,因为你在ScrollViewer中,或者你确定你有足够的物品,你不会用尽空间,或者如果你不关心在面板末端运行的物品太大了,你不希望布局系统尝试做任何比简单裁剪内容更聪明的事情。)

So turning on text wrapping won't help here, because the StackPanel will always pretend that there's more than enough space for the text.

所以打开文本包装在这里没有用,因为StackPanel总是会假装文本的空间足够多。

You need a different layout structure. Stack panels are the wrong thing to use because they will not impose the layout constraint you need to get text wrapping to kick in.

您需要不同的布局结构。堆栈面板使用是错误的,因为它们不会强制执行文本换行所需的布局约束。

Here's a simple example that does roughly what you want:

这是一个简单的例子,大致可以满足您的需求:

<Grid VerticalAlignment="Top">
    <DockPanel>
        <TextBlock
            x:Name="DataGridTitle"
            VerticalAlignment="Top"
            DockPanel.Dock="Left"
            />
        <TextBox
            Name="VerticallyExpandMe"
            AcceptsReturn="True"
            TextWrapping="Wrap"
            Text="{Binding QueryString}"
            >
        </TextBox>
    </DockPanel>
</Grid>

If you create a brand new WPF application and paste that in as the content of the main window, you should find it does what you want - the TextBox starts out one line tall, fills the available width, and if you type text in, it'll grow one line at a time as you add more text.

如果你创建一个全新的WPF应用程序并将其作为主窗口的内容粘贴,你会发现它做你想要的 - TextBox开始一行高,填充可用宽度,如果你键入文本,它当你添加更多文字时,我会一次增长一行。

Of course, layout behaviour is always sensitive to context, so it may not be enough to just throw that into the middle of your existing application. That will work if pasted into a fixed-size space (e.g. as the body of a window), but will not work correctly if you paste it into a context where width is unconstrained. (E.g., inside a ScrollViewer, or inside a horizontal StackPanel.)

当然,布局行为始终对上下文敏感,因此将其放入现有应用程序的中间可能还不够。如果粘贴到固定大小的空间(例如,作为窗口的主体),那将会起作用,但如果将其粘贴到宽度不受约束的上下文中,则无法正常工作。 (例如,在ScrollViewer中,或在水平StackPanel内。)

So if this doesn't work for you, it'll be because of other things wrong elsewhere in your layout - possibly yet more StackPanel elements elsewhere. From the look of your example, it's probably worth spending some time thinking about what you really need in your layout and simplifying it - the presence of negative margins, and elements that don't appear to do anything like that empty TextBlock are usually indicative of an over-complicated layout. And unnecessary complexity in a layout makes it much hard to achieve the effects you're looking for.

因此,如果这对您不起作用,那将是因为您的布局中其他地方出现了其他错误 - 可能还有其他更多的StackPanel元素。从您的示例来看,可能值得花一些时间考虑您在布局中真正需要的内容并简化它 - 负边距的存在,以及似乎没有像空白TextBlock那样执行任何操作的元素通常表示一个过于复杂的布局。布局中不必要的复杂性使得很难实现您正在寻找的效果。

#2


6  

Alternatively, you could constrain your TextBlock's Width by binding it to a parent's ActualWidth, for example:

或者,您可以通过将TextBlock的宽度绑定到父级的ActualWidth来约束TextBlock的宽度,例如:

<TextBlock Width="{Binding ElementName=*ParentElement*, Path=ActualWidth}" 
           Height="Auto" />

This will force it to resize its height automatically too.

这将迫使它自动调整其高度。

#3


2  

Use MaxWidth and TextWrapping="WrapWithOverflow".

使用MaxWidth和TextWrapping =“WrapWithOverflow”。

#4


0  

I'm using another simple approach that allows me not to change the document layout.

我正在使用另一种简单的方法,允许我不要更改文档布局。

The main idea is not to set the control Width before it starts changing. For TextBoxes, I handle the SizeChanged event:

主要思想是在开始更改之前不要设置控件宽度。对于TextBoxes,我处理SizeChanged事件:

<TextBox TextWrapping="Wrap" SizeChanged="TextBox_SizeChanged" />

private void TextBox_SizeChanged(object sender, SizeChangedEventArgs e)
{
    FrameworkElement box = (FrameworkElement)sender;
    if (e.PreviousSize.Width == 0 || box.Width < e.PreviousSize.Width)
        return;
    box.Width = e.PreviousSize.Width;
}

#5


0  

You can use this class which extends TextBlock. It does auto-shrinking and takes MaxHeight / MaxWidth into consideration:

您可以使用此类扩展TextBlock。它会自动缩小并考虑MaxHeight / MaxWidth:

public class TextBlockAutoShrink : TextBlock
    {
        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);
            }
        }
    }

#1


42  

Although Andre Luus's suggestion is basically correct, it won't actually work here, because your layout will defeat text wrapping. I'll explain why.

尽管Andre Luus的建议基本上是正确的,但它实际上并不适用,因为你的布局会打败文本包装。我会解释原因。

Fundamentally, the problem is this: text wrapping only does anything when an element's width is constrained, but your TextBox has unconstrained width because it's a descendant of a horizontal StackPanel. (Well, two horizontal stack panels. Possibly more, depending on the context from which you took your example.) Since the width is unconstrained, the TextBox has no idea when it is supposed to start wrapping, and so it will never wrap, even if you enable wrapping. You need to do two things: constrain its width and enable wrapping.

从根本上说,问题是这样的:文本换行只在元素的宽度受约束时执行任何操作,但是TextBox具有无约束的宽度,因为它是水平StackPanel的后代。 (好吧,两个水平堆栈面板。可能更多,取决于您从中获取示例的上下文。)由于宽度不受约束,TextBox不知道何时应该开始包装,因此它永远不会换行,甚至如果你启用包装。你需要做两件事:约束它的宽度并启用包装。

Here's a more detailed explanation.

这是一个更详细的解释。

Your example contains a lot of detail irrelevant to the problem. Here's a version I've trimmed down somewhat to make it easier to explain what's wrong:

您的示例包含许多与问题无关的详细信息。这是一个我稍微减少的版本,以便更容易解释错误:

<StackPanel Orientation="Horizontal">
    <TextBlock Name="DataGridTitle" />
    <StackPanel
        Margin="5,0"
        Orientation="Horizontal"
        >
        <TextBlock />
        <TextBox
            Name="VerticallyExpandMe"
            Margin="10,2,10,-1"
            AcceptsReturn="True"
            VerticalAlignment="Center"
            Text="{Binding QueryString}"
            >
        </TextBox>
    </StackPanel>
</StackPanel>

So I've removed your containing DockPanel and the two nested Border elements inside of that, because they're neither part of the problem nor relevant to the solution. So I'm starting at the pair of nested StackPanel elements in your example. And I've also removed most of the attributes because most of them are also not relevant to the layout.

所以我删除了你包含的DockPanel和其中的两个嵌套Border元素,因为它们既不是问题的一部分,也不是解决方案的相关内容。所以我从你的例子中的一对嵌套StackPanel元素开始。而且我还删除了大部分属性,因为它们中的大多数也与布局无关。

This looks a bit weird - having two nested horizontal stack panels like this looks redundant, but it does actually make sense in your original if you need to make the nested one visible or invisible at runtime. But it makes it easier to see the problem.

这看起来有点奇怪 - 有两个嵌套的水平堆栈面板看起来多余,但如果您需要在运行时使嵌套的可见或不可见,它确实在您的原始中有意义。但它更容易看到问题。

(The empty TextBlock tag is also weird, but that's exactly as it appears in your original. That doesn't appear to be doing anything useful.)

(空的TextBlock标签也很奇怪,但这与原始文件中显示的完全相同。这似乎没有做任何有用的事情。)

And here's the problem: your TextBox is inside some horizontal StackPanel elements, meaning its width is unconstrained - you have inadvertently told the text box that it is free to grow to any width, regardless of how much space is actually available.

这就是问题所在:你的TextBox位于一些水平的StackPanel元素中,意味着它的宽度不受约束 - 你无意中告诉文本框它可以*地增长到任何宽度,无论实际有多少空间。

A StackPanel will always perform layout that is unconstrained in the direction of stacking. So when it comes to lay out that TextBox, it'll pass in a horizontal size of double.PositiveInfinity to the TextBox. So the TextBox will always think it has more space than it needs. Moreover, when a child of a StackPanel asks for more space than is actually available, the StackPanel lies, and pretends to give it that much space, but then crops it.

StackPanel将始终执行在堆叠方向上不受约束的布局。因此,当布局TextBox时,它会将double.PositiveInfinity的水平大小传递给TextBox。所以TextBox总是认为它有更多的空间而不是它需要的。此外,当StackPanel的子项要求比实际可用空间更多的空间时,StackPanel会说谎,并假装给它那么大的空间,然后裁剪它。

(This is the price you pay for the extreme simplicity of StackPanel - it's simple to the point of being bone-headed, because it will happily construct layouts that don't actually fit. You should only use StackPanel if either you really do have unlimited space because you're inside a ScrollViewer, or you are certain that you have sufficiently few items that you're not going to run out of space, or if you don't care about items running off the end of the panel when they get too large and you don't want the layout system to try to do anything more clever than simply cropping the content.)

(这是你为StackPanel的极端简单所付出的代价 - 它很简单到了骨头,因为它会愉快地构建实际上不适合的布局。如果你真的有无限制,你应该只使用StackPanel空间,因为你在ScrollViewer中,或者你确定你有足够的物品,你不会用尽空间,或者如果你不关心在面板末端运行的物品太大了,你不希望布局系统尝试做任何比简单裁剪内容更聪明的事情。)

So turning on text wrapping won't help here, because the StackPanel will always pretend that there's more than enough space for the text.

所以打开文本包装在这里没有用,因为StackPanel总是会假装文本的空间足够多。

You need a different layout structure. Stack panels are the wrong thing to use because they will not impose the layout constraint you need to get text wrapping to kick in.

您需要不同的布局结构。堆栈面板使用是错误的,因为它们不会强制执行文本换行所需的布局约束。

Here's a simple example that does roughly what you want:

这是一个简单的例子,大致可以满足您的需求:

<Grid VerticalAlignment="Top">
    <DockPanel>
        <TextBlock
            x:Name="DataGridTitle"
            VerticalAlignment="Top"
            DockPanel.Dock="Left"
            />
        <TextBox
            Name="VerticallyExpandMe"
            AcceptsReturn="True"
            TextWrapping="Wrap"
            Text="{Binding QueryString}"
            >
        </TextBox>
    </DockPanel>
</Grid>

If you create a brand new WPF application and paste that in as the content of the main window, you should find it does what you want - the TextBox starts out one line tall, fills the available width, and if you type text in, it'll grow one line at a time as you add more text.

如果你创建一个全新的WPF应用程序并将其作为主窗口的内容粘贴,你会发现它做你想要的 - TextBox开始一行高,填充可用宽度,如果你键入文本,它当你添加更多文字时,我会一次增长一行。

Of course, layout behaviour is always sensitive to context, so it may not be enough to just throw that into the middle of your existing application. That will work if pasted into a fixed-size space (e.g. as the body of a window), but will not work correctly if you paste it into a context where width is unconstrained. (E.g., inside a ScrollViewer, or inside a horizontal StackPanel.)

当然,布局行为始终对上下文敏感,因此将其放入现有应用程序的中间可能还不够。如果粘贴到固定大小的空间(例如,作为窗口的主体),那将会起作用,但如果将其粘贴到宽度不受约束的上下文中,则无法正常工作。 (例如,在ScrollViewer中,或在水平StackPanel内。)

So if this doesn't work for you, it'll be because of other things wrong elsewhere in your layout - possibly yet more StackPanel elements elsewhere. From the look of your example, it's probably worth spending some time thinking about what you really need in your layout and simplifying it - the presence of negative margins, and elements that don't appear to do anything like that empty TextBlock are usually indicative of an over-complicated layout. And unnecessary complexity in a layout makes it much hard to achieve the effects you're looking for.

因此,如果这对您不起作用,那将是因为您的布局中其他地方出现了其他错误 - 可能还有其他更多的StackPanel元素。从您的示例来看,可能值得花一些时间考虑您在布局中真正需要的内容并简化它 - 负边距的存在,以及似乎没有像空白TextBlock那样执行任何操作的元素通常表示一个过于复杂的布局。布局中不必要的复杂性使得很难实现您正在寻找的效果。

#2


6  

Alternatively, you could constrain your TextBlock's Width by binding it to a parent's ActualWidth, for example:

或者,您可以通过将TextBlock的宽度绑定到父级的ActualWidth来约束TextBlock的宽度,例如:

<TextBlock Width="{Binding ElementName=*ParentElement*, Path=ActualWidth}" 
           Height="Auto" />

This will force it to resize its height automatically too.

这将迫使它自动调整其高度。

#3


2  

Use MaxWidth and TextWrapping="WrapWithOverflow".

使用MaxWidth和TextWrapping =“WrapWithOverflow”。

#4


0  

I'm using another simple approach that allows me not to change the document layout.

我正在使用另一种简单的方法,允许我不要更改文档布局。

The main idea is not to set the control Width before it starts changing. For TextBoxes, I handle the SizeChanged event:

主要思想是在开始更改之前不要设置控件宽度。对于TextBoxes,我处理SizeChanged事件:

<TextBox TextWrapping="Wrap" SizeChanged="TextBox_SizeChanged" />

private void TextBox_SizeChanged(object sender, SizeChangedEventArgs e)
{
    FrameworkElement box = (FrameworkElement)sender;
    if (e.PreviousSize.Width == 0 || box.Width < e.PreviousSize.Width)
        return;
    box.Width = e.PreviousSize.Width;
}

#5


0  

You can use this class which extends TextBlock. It does auto-shrinking and takes MaxHeight / MaxWidth into consideration:

您可以使用此类扩展TextBlock。它会自动缩小并考虑MaxHeight / MaxWidth:

public class TextBlockAutoShrink : TextBlock
    {
        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);
            }
        }
    }