我做了一个自定义控件继承TextBlock的LetterSpacing,这里是我的代码:
public class NewTextBlock : TextBlock
{
public NewTextBlock() : base() {
var dp = DependencyPropertyDescriptor.FromProperty(
TextBlock.TextProperty,
typeof(TextBlock));
dp.AddValueChanged(this, (sender, args) =>
{
LetterSpacingChanged(this);
});
}
static void LetterSpacingChanged(DependencyObject d)
{
NewTextBlock TB = d as NewTextBlock;
TB.TextEffects.Clear();
for (int i = 1; i <= TB.Text.Length; i++)
{
TranslateTransform transform = new TranslateTransform(TB.LetterSpacing, 0);
TextEffect effect = new TextEffect();
effect.Transform = transform;
effect.PositionStart = i;
effect.PositionCount = TB.Text.Length;
TB.TextEffects.Add(effect);
if (effect.CanFreeze)
{
effect.Freeze();
}
}
}
public double LetterSpacing
{
get { return (double)GetValue(LetterSpacingProperty); }
set { SetValue(LetterSpacingProperty, value); }
}
// Using a DependencyProperty as the backing store for LetterSpacing. This enables animation, styling, binding, etc...
public static readonly DependencyProperty LetterSpacingProperty =
DependencyProperty.Register("LetterSpacing", typeof(double), typeof(NewTextBlock), new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(LetterSpacingChanged)));
private static void LetterSpacingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LetterSpacingChanged(d);
}
}
当我这样使用它时:
<Test:NewTextBlock Background="Red" HorizontalAlignment="Center" VerticalAlignment="Center" LetterSpacing="5" Text="123123123123">
<Test:NewTextBlock.LayoutTransform>
<RotateTransform Angle="45"></RotateTransform>
</Test:NewTextBlock.LayoutTransform>
</Test:NewTextBlock>
原来是这样的:enter image description here
如红色背景所示,NewTextBlock的实际宽度似乎不包括TextEffect的宽度。
我想找到一种方法来获得文本效果的实际宽度,并为NewTextBlock设置一个正确的实际宽度。
我该怎么做呢?
3条答案
按热度按时间0wi1tuuw1#
不要使用
DependencyPropertyDescriptor
来注册一个属性改变的回调。如果你不小心(你的代码就是这种情况),它将创建一个(潜在的严重)每个示例内存泄漏。最好在
static
构造函数中重写dependency属性的元数据,以注册新的回调(参见下面的示例)。TextBlock
不支持自定义字符间距。TextBlock
完全依赖提供的字体(或字样)来计算实际文本宽度。由于MeasureOverride
是密封的,因此在更改Text
值或任何与文本相关的属性(例如FontSize
等)后,通常必须强制使用新的Width
。这意味着,要正确实现大小调整行为,您必须重写所有相关属性的属性元数据,以触发实际
NewTextBlock
宽度的重新计算。您可以遵循以下示例中TextBlock.TextProperty
属性的元数据重写。要计算格式化字符串的宽度,通常使用
FormattedText
类(见下文),在这种情况下,必须将当前字符间距包括在计算中。bkhjykvo2#
也许我错过了这个STextBlock的要点,但在我看来,您可以(也许应该)只使用Glyphs框架元素来代替。
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/introduction-to-the-glyphrun-object-and-glyphs-element?view=netframeworkdesktop-4.8
https://learn.microsoft.com/en-us/dotnet/api/system.windows.documents.glyphs?view=windowsdesktop-7.0
乙二醇
jmo0nnb33#
我从@BionicCode的代码中找到了另一个解决方案