我想修改WPF TextBox中字符之间的间距
类似于CSS中可用的letter-spacing: 5px
事物
我认为在XAML中是可能的;什么是最简单的方法?
我找到了“Introduction to the GlyphRun Object and Glyphs Element”文件,发现它非常无益。
这是该页面的代码示例:
<!-- "Hello World!" with explicit character widths for proportional font -->
<Glyphs
FontUri = "C:\WINDOWS\Fonts\ARIAL.TTF"
FontRenderingEmSize = "36"
UnicodeString = "Hello World!"
Indices = ",80;,80;,80;,80;,80;,80;,80;,80;,80;,80;,80"
Fill = "Maroon"
OriginX = "50"
OriginY = "225"
/>
相同的文档页面为Indices
属性的作用提供了“解释”:
我不知道这意味着什么。我也不确定指数是否正确 - 代码中的注释说的是“字符宽度”,我并不关心。我想在字符之间调整的宽度。
此外,没有关于如何将Glyphs
元素应用于TextBox的示例。当我尝试它时,我的WPF测试应用程序崩溃了。
我想要做的是略微增加WPF TextBox中绘制字符之间出现的空白区域。案文的长度和内容各不相同。每次有新角色时我是否必须修改Indicies
属性?有没有办法说“为每个角色增加20%的空间”。
任何人都可以帮助我吗?
答案 0 :(得分:17)
我尝试了Glyphs和FontStretch,并且无法轻易获得我想要的结果。我能够提出一种适用于我的目的的方法。也许它也适用于其他人。
<ItemsControl ItemsSource="{Binding SomeString}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
Margin="0,0,5,0"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我可以绑定到任何字符串,不需要进行任何字符宽度检测来正确设置间距。右边距是字母之间的空格。
示例:
答案 1 :(得分:1)
FontStretch是你的选择吗?
否则你可能想查看this有一个图像,显示提前宽度的含义。虽然我之前没有这样做过,也不知道这是否有效,左右侧轴承可能是你想要的!
答案 2 :(得分:1)
我找到了一种使用 TextBlock 类设置字母间距的方法,因为它支持 TranslateTransforms。通过用自定义的 PropertyChangedCallback
替换默认的 TextBlock.TextProperty
,我们可以将 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>
最后,在 InitializeComponent()
代码隐藏文件中的 .cs
方法之前,像这样添加 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)
)
);
...并在每次 TranslateTransform
更改时将 TextProperty
应用于每个字母:
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# 的完全新手,所以我的答案可能不是可用的最干净的解决方案。如果您对如何改进此答案有任何意见,我们将不胜感激!
其次,我还没有用大量 TextBlock
元素测试过这个解决方案,并且(可能)会造成巨大的性能损失,因为 TranslateTransform
应用于 {{ 1}}。
最后,TextBlock.Text
的文本超出了 TextBlock
的任何正 X
值的范围。我认为您可以重新计算 TranslateTransform
的宽度,然后才以编程方式放置它 (?)
答案 3 :(得分:-1)
它的价值。 。
如果您可以选择将实现切换到RichTextBox,这可能比您在2013年9月找到的解决方案更容易。我只是根据自己的需要尝试它,它可以满足我的需要。我没有看到使用RichTextBox来控制像排版者这样的单个空格的字距调整。但TextBox正在占用额外的空间(将多个相邻空间合并到一个空间),就像HTML一样。我需要空格显示与文本字符串相同的间距,RichTextBox就是这样做的。
<RichTextBox x:Name="MyRichTextBox"></RichTextBox>
我不是专家,但似乎您无法在XAML中指定文字内容。我必须在代码隐藏事件中指定它:
this.MyRichTextBox.AppendText("V A R I E D S P A C E S");