我有一个TextBlock具有包装文本的固定大小。有时短暂有时很长。用于TextBlock的动态字体大小与包装
如果文本越来越长它不是完全显示这样
我怎样才能让字体大小的灵活性,以使文本适合静态大小的文本框?
我有一个TextBlock具有包装文本的固定大小。有时短暂有时很长。用于TextBlock的动态字体大小与包装
如果文本越来越长它不是完全显示这样
我怎样才能让字体大小的灵活性,以使文本适合静态大小的文本框?
我的解决方案如下:
设置字体大小的值,比你不想任何大。 当您更改字体大小或更改内容时,TextBlock的ActualHeight会发生变化。我基于此建立了解决方案。 您应该为SizeChanged事件创建一个事件处理程序并将下面的代码写入它。
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.
}
为什么我用了Math.Sqrt()的原因是,如果你设置字体大小的一半大如前,那么该字体将使用面积,将是四分之一大小,然后之前(因为它变得比以前宽一半)。你显然希望保持TextBox的宽度,只改变它的高度。
如果你很幸运,在这个方法被执行一次后,字体大小将是适当的。但是,根据字体大小更改后重新打包的文本,您可能会非常“不吉利”,文本将比您希望的长一行。 幸运的是,事件处理程序将被再次调用(因为您更改了字体大小),如果大小仍然过大,则会再次调整大小。
我试过了,速度很快,结果看起来不错。 但是,我可以想象,在一个非常不吉利的文本和高度选择中,经过几次迭代后才会达到正确的字体大小。这就是为什么我使用Math.Floor()。总而言之,如果字体大小最终是12.34或12,那么这并不重要,这样我就不会担心“不幸”的文本,这会花费太长的时间来渲染。 但是我认为如果你不想有一个非常高的文本框(如2000像素)和很多文本,可以省略Math.Floor()。
非常感谢,这帮助我! – Ostkontentitan
谢谢,这对我有帮助。注意;我意识到这不适用于OP的情况,但在Windows 10应用程序中,您可以在桌面上的窗口中调整大小,这将导致文本缩小但不会再变大。 – tagy22
这太棒了! – xleon
这里的包括选项来设置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);
}
}
}
'_typeface'不在您的示例中使用。 – canton7
@ canton7该死的你是对的..我会检查出来 –
你可以尝试使用[视框(http://msdn.microsoft.com/ en-us/library/system.windows.controls.viewbox.aspx),但您可能会遇到ViewBox中包装的问题。 –
是啊,你的猜测似乎是正确的,它杀死了包装。感谢无论如何,我没有偶然发现那个元素! – Ostkontentitan
您是否打开JavaScript解决方案? – ic3b3rg