Wpf 异步计算字体大小

Wpf 异步计算字体大小,wpf,fonts,textblock,Wpf,Fonts,Textblock,我使用WPF。我的应用程序有一些文本块,里面有可更改的文本。每一个的宽度为200,高度为150。问题是我有7个这样的文本块,我希望它们有相同的字体大小。文本必须自动调整。我知道它可以自动装配。但是当一个句子在里面而另一个只有两个单词时,字体大小是如此的不同。。。我需要异步重新计算大小(例如,创建一些事件,如OnTextChange)。块内的文本会动态更改。如何编写函数?我想传递3个参数:文本、字体(字体系列+字体样式)和文本块大小,并返回合适的字体大小。确定合适字体大小的最佳方法是测量任意大小的

我使用WPF。我的应用程序有一些文本块,里面有可更改的文本。每一个的宽度为200,高度为150。问题是我有7个这样的文本块,我希望它们有相同的字体大小。文本必须自动调整。我知道它可以自动装配。但是当一个句子在里面而另一个只有两个单词时,字体大小是如此的不同。。。我需要异步重新计算大小(例如,创建一些事件,如OnTextChange)。块内的文本会动态更改。如何编写函数?我想传递3个参数:文本、字体(字体系列+字体样式)和文本块大小,并返回合适的字体大小。

确定合适字体大小的最佳方法是测量任意大小的文本,然后将其乘以大小与区域大小的比率

例如,如果您测量文本,并且文本大小为其所在容器大小的一半,则可以将其乘以2,它应该填充容器。您希望选择要使用的宽度或高度比的最小值

在WPF中,FormattedText类进行文本测量

public double GetFontSize(string text, Size availableSize, Typeface typeFace)
{
    FormattedText formtxt = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeFace, 10, Brushes.Black);

    double ratio = Math.Min(availableSize.Width / formtxt.Width, availableSize.Height / formtxt.Height);

    return 10 * ratio;
}
无论何时更改文本块的文本,您都可以使用此函数,如下所示:

txtBlock.FontSize = GetFontSize(txt.Text, new Size(txt.ActualWidth, txt.ActualHeight), new Typeface(txt.FontFamily, txt.FontStyle, txt.FontWeight, txt.FontStretch));
编辑:


出于实用性的目的,您可能希望能够使文本垂直居中于此预定义的边框中。这样做的一个好方法是将TextBlock包装在另一个对象(如Border元素)中。这样,您可以告诉您的文本块在边框的中心对齐,并且它可以自动调整大小以适应其内容。

确定。很好。但我还有一个问题。我在MainWindow.cs中编写了两个方法:

    private void fitFontSize()
    {
        propertiesList.Clear();

        TextUtils.FontProperty fontProps = new TextUtils.FontProperty();
        foreach (TextBlock tb in findVisualChildren<TextBlock>(statusOptionsGrid))
        {
            fontProps.Text = tb.Text;
            fontProps.Size = new Size(tb.ActualWidth, tb.ActualHeight);
            fontProps.FontFamily = tb.FontFamily;
            fontProps.FontStyle = tb.FontStyle;
            fontProps.FontWeight = tb.FontWeight;
            fontProps.FontStretch = tb.FontStretch;
            propertiesList.Add(fontProps);
        }

        MessageBox.Show(TextUtils.recalculateFontSize(propertiesList) + "");
    }

    public IEnumerable<T> findVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }

                foreach (T childOfChild in findVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
    }
private void fitFontSize()
{
propertiesList.Clear();
TextUtils.FontProperty fontProps=新的TextUtils.FontProperty();
foreach(findVisualChildren中的文本块tb(状态选项网格))
{
fontProps.Text=tb.Text;
fontProps.Size=新大小(tb.ActualWidth,tb.ActualHeight);
fontProps.FontFamily=tb.FontFamily;
fontProps.FontStyle=tb.FontStyle;
fontProps.FontWeight=tb.FontWeight;
fontProps.FontStretch=tb.FontStretch;
属性列表。添加(fontProps);
}
MessageBox.Show(TextUtils.recreactefontsize(propertiesList)+“”;
}
公共IEnumerable findVisualChildren(DependencyObject depObj),其中T:DependencyObject
{
if(depObj!=null)
{
for(int i=0;i
之后,我为文本处理创建了一个新类。代码如下:

public class TextUtils
{
    public class FontProperty
    {
        public FontFamily FontFamily { get; set; }
        public FontStyle FontStyle { get; set; }
        public FontWeight FontWeight { get; set; }
        public FontStretch FontStretch { get; set; }
        public string Text { get; set; }
        public Size Size { get; set; }

        public Typeface getTypeFace()
        {
            return new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
        }
    }

    public static double recalculateFontSize(List<FontProperty> propertiesList)
    {
        List<double> fontSizes = new List<double>();
        foreach (FontProperty fp in propertiesList)
        {
            fontSizes.Add(getFontSizeForControl(fp));
        }

        return fontSizes.Min<double>();
    }

    private static double getFontSizeForControl(FontProperty fp)
    {
        string text = fp.Text;
        Size availableSize = fp.Size;
        Typeface typeFace = fp.getTypeFace();

        FormattedText formtxt = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeFace, 10, Brushes.Black);
        double ratio = Math.Min(availableSize.Width / formtxt.Width, availableSize.Height / formtxt.Height);

        return 10 * ratio;
    }
}
公共类TextUtils
{
公共类属性
{
公共FontFamily FontFamily{get;set;}
公共字体样式字体样式{get;set;}
公共FontWeight FontWeight{get;set;}
公共FontStretch FontStretch{get;set;}
公共字符串文本{get;set;}
公共大小大小{get;set;}
公共字体getTypeFace()
{
返回新字体(FontFamily、FontStyle、FontWeight、FontStretch);
}
}
公共静态双重新计算字体大小(列表属性列表)
{
List fontSizes=新列表();
foreach(属性列表中的FontProperty fp)
{
添加(getFontSizeForControl(fp));
}
返回fontSizes.Min();
}
私有静态双getFontSizeForControl(FontProperty fp)
{
字符串text=fp.text;
可用大小大小=fp.Size;
Typeface-Typeface=fp.getTypeFace();
FormattedText formtxt=新的FormattedText(文本,CultureInfo.CurrentCulture,FlowDirection.LeftToRight,字体,10,画笔.黑色);
双倍比率=Math.Min(availableSize.Width/formtxt.Width,availableSize.Height/formtxt.Height);
回报率为10倍;
}
}
代码看起来很糟糕,但我稍后会更正它

嗯。现在我想创建一个新的计时器,它每秒检查字体大小。当我尝试在其中使用fitFontSize()方法时,我得到一条消息:“调用线程无法访问此对象,因为另一个线程拥有它。” 如何做到这一点以避免类似的问题? 我尝试(只是一次尝试)创建调用此方法的新线程。但是findVisualChildren()方法也有同样的问题——它在fitFontSize()中调用。我不知道如何解决我的问题