我找到了一种使用TextBlock 类来设置字母间距的方法,因为它支持TranslateTransforms。通过将TextBlock.TextProperty 上的默认PropertyChangedCallback 替换为自定义@,我们可以将TranslateTransform 应用于TextBlock 中的每个字母。
这是我完成的完整的分步编码:
首先,我们创建一个自定义类并继承自TextBlock,如下所示:
using System.Windows.Controls;
namespace MyApp
{
class SpacedLetterTextBlock : TextBlock
{
public SpacedLetterTextBlock() : base()
{
}
}
}
然后,在 XAML 中,我们将 TextBlock 更改为我们的自定义类(更多信息可以找到 here):
<Window x:Class="MyApp.MainWindow"
...
xmlns:app="clr-namespace:MyApp">
<Grid>
<app:SpacedLetterTextBlock>
Some Text
</app:SpacedLetterTextBlock>
</Grid>
</Window>
最后,在.cs 代码隐藏文件中的InitializeComponent() 方法之前,添加OverrideMetadata 方法,如下所示:
// This line of code adds our own callback method to handle any changes in the Text
// property of the TextBlock
SpacedLetterTextBlock.TextProperty.OverrideMetadata(
typeof(SpacedLetterTextBlock),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnTextChanged)
)
);
...并在每次TextProperty 更改时将TranslateTransform 应用于每个字母:
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SpaceLettersOut(d);
}
// This method takes our custom text block and 'moves' each letter left or right by
// applying a TranslateTransform
private static void SpaceLettersOut(DependencyObject d)
{
SpacedLetterTextBlock thisBlock = (SpacedLetterTextBlock)d;
for (int i = 1; i <= thisBlock.Text.Length; i++)
{
// TranslateTransform supports doubles and negative numbers, so you can have
// whatever spacing you need - do see 'Notes' section in the answer for
// some limitations.
TranslateTransform transform = new TranslateTransform(2, 0);
TextEffect effect = new TextEffect();
effect.Transform = transform;
effect.PositionStart = i;
effect.PositionCount = thisBlock.Text.Length;
thisBlock.TextEffects.Add(effect);
if (effect.CanFreeze)
{
effect.Freeze();
}
}
}
注意事项:
首先,我是 WPF 和 C# 的完全新手,所以我的答案可能不是最干净的解决方案。如果您有任何关于如何改进此答案的 cmets,将不胜感激!
其次,我还没有使用大量 TextBlock 元素测试此解决方案,并且(可能)存在巨大的性能损失,因为 TranslateTransform 应用于 TextBlock.Text 中的每个单独的字母。
最后,TextBlock 的文本超出了TranslateTransform 的任何正的X 值的范围。我认为您可以重新计算TextBlock 的宽度,然后以编程方式放置它(?)