我有一個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