【问题标题】:How to position FormattedText with ItemsControl on Canvas (MVVM)如何在 Canvas (MVVM) 上使用 ItemsControl 定位 FormattedText
【发布时间】:2014-08-21 18:35:01
【问题描述】:

对 XAML 使用带有 ItemsControl 的 MVVM 模式,我试图将 FormattedText 字符串的左上墨点准确定位在指定矩形的左上角。 (矩形由 InkAnalyzer.Location.GetBounds() 给出)。

由于我无法弄清楚(或在 Google 上找到)的原因,FormattedText 字符串始终位于矩形左上角的右下方,距离似乎与用于打印的字体大小成正比.

如何将 FormattedText 定位到矩形的左上角?

非常感谢任何帮助。

XAML

<ItemsControl 
                ItemsSource="{Binding Transcription}"
                >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas 
                            Background="Transparent"
                             Width="{x:Static h:Constants.widthCanvas}" 
                             Height="{x:Static h:Constants.heightCanvas}" 
                             />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>             
 </ItemsControl>

C#

 private ObservableCollection<StringViewModel> transcription = new ObservableCollection<StringViewModel>();
    public ObservableCollection<StringViewModel> Transcription
    {
        get
        {
            return transcription;
        }
    }


public class StringViewModel : FrameworkElement, INotifyPropertyChanged
{
    public StringViewModel(
        Point topleft, 
        string text, 
        double fontsize, 
        SolidColorBrush brush, 
        double linewidth, 
        double columnheight,
        Func<FormattedText,FormattedText> f)    
    {
        this.text = text;
        this.FontSize = fontsize * (72.0/96.0);     
        this.color = brush;
        this.origin = topleft;
        this.origin_X = topleft.X;
        this.origin_Y = topleft.Y;
        this.maxtextwidth = linewidth * (72.0/96.0);
        this.maxtextheight = columnheight ;
        this.f = f;
    }

    protected override void OnRender(DrawingContext dc)
    {

        FormattedText ft = new FormattedText(
            text, 
            CultureInfo.CurrentCulture, 
            FlowDirection.LeftToRight,
            new Typeface(new FontFamily("Segoe Script"), FontStyles.Italic, FontWeights.Normal, FontStretches.Normal), 
            FontSize, 
            color);

        ft.TextAlignment = TextAlignment.Left;

        ft.MaxTextWidth = maxtextwidth;
        ft.MaxTextHeight = maxtextheight;


        dc.DrawText(ft, origin);
    }

【问题讨论】:

  • 我们所说的距离左上角有多远,字体大小是多少?如果它只是 ~12pt 的几个像素,可能是由于字体的行高。另外,有什么特别的原因为什么您使用 FormattedText 而不是让 WPF 只将字符串显示为 TextBlocks?
  • @MikeStrobel 嗨。它可以是许多像素。我正在根据笔划的高度创建一个字体大小。格式化文本的 LineHeight 属性似乎在 OnRender 中保持为 0。我正在使用 FormattedText 以希望获得更好看的转录。我希望我不必放弃它。
  • @MikeStrobel 作为一个粗略的近似,这非常接近: TranslateTransform t = new TranslateTransform(0, -0.19 * FontSize); dc.PushTransform(t); dc.DrawText(英尺,原点); dc.Pop();

标签: wpf xaml itemscontrol formatted-text


【解决方案1】:

我注意到 Segoe 系列字体在指标中往往具有相当大的间距。对 16 像素(72 dpi 时为 12 像素)的 Segoe 脚本进行快速测试显示,在较高字形的顶部和边界框之间有大约 5 像素的填充。

在上面的示例中,每个文本块都位于粉红色边框的左上角。您可以在第一行看到额外的垂直空间,我怀疑它重现了您在自己的代码中看到的内容。

将LineHeight 设置为字体大小会消除多余的空间,但会剪掉一些较高的字形。我的实验表明,1.25 * FontSize 中的LineHeight 往往是这种特定字体的理想选择,如第三行所示。它还保持足够的间距以显示多行文本。

顺便说一句,您可能希望将字体嵌入您的应用程序并通过其资源名称引用它,而不是简单地指定字体名称并希望您的用户安装它(请务必检查许可详细信息,不过)。

【讨论】:

    猜你喜欢
    • 2016-03-25
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多