添加到Panel的Textblock会自动调整大小

时间:2010-09-14 17:02:12

标签: c# wpf panel textblock

我有一个用于布置文本的自定义面板。有一个名为“Text”的DependancyProperty,当该值发生变化时,这段代码运行:

if( !string.IsNullOrEmpty(Text))
{
    Children.Clear();

    foreach (char ch in Text)
    {
        TextBlock textBlock = new TextBlock();
        textBlock.Text = ch.ToString();
        textBlcok.Foreground = Foreground;

        //The rest of these are DPs in the panel
        textBlock.FontFamily = FontFamily;
        textBlock.FontStyle = FontStyle;     
        textBlock.FontWeight = FontWeight;
        textBlock.FontStretch = FontStretch;
        textBlock.FontSize = FontSize;

        Children.Add(textBlock);
        }
    }
}

现在,字体大小为15,字体Arial,这些应该给我一个大约8宽和10高的所需大小。但是,当我做一个Measure()并检查所需的大小时,我每次都会得到40,18!

因此,在尝试找出可能改变大小的内容时,我在上面的代码中添加了Children.Add之前和之后的代码:

textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Console.WriteLine(ch.ToString() + ": " + textBlock.DesiredSize);

Children.Add(textBlock);

textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Console.WriteLine(ch.ToString() + ": " + textBlock.DesiredSize);

这给了我的是,在它添加到儿童系列之前是合适的所需尺寸,并且在添加到该系列之后大小为40,18(不论字母)。

是什么导致这种情况发生?

编辑:您可以在此处找到控件的完整来源:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using IQ.Touch.Resources.Classes.Helpers;

/* TextOnAPath.cs
 * 
 * A slightly modified version of the control found at
 * http://www.codeproject.com/KB/WPF/TextOnAPath.aspx
 */

namespace IQ.Touch.Resources.Controls
{
    public class TextOnAPath : Panel
    {
        // Fields
        PathFigureHelper pathFigureHelper = new PathFigureHelper();
        Size totalSize;

        // Dependency properties
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text",
                typeof(string),
                typeof(TextOnAPath),
                new PropertyMetadata(OnFontPropertyChanged));

        public static readonly DependencyProperty FontFamilyProperty =
            DependencyProperty.Register("FontFamily",
                typeof(FontFamily),
                typeof(TextOnAPath),
                new PropertyMetadata(new FontFamily("Portable User Interface"), OnFontPropertyChanged));

        public static readonly DependencyProperty FontStyleProperty =
            DependencyProperty.Register("FontStyle",
                typeof(FontStyle),
                typeof(TextOnAPath),
                new PropertyMetadata(FontStyles.Normal, OnFontPropertyChanged));

        public static readonly DependencyProperty FontSizeProperty =
            DependencyProperty.Register("FontSize",
                typeof(double),
                typeof(TextOnAPath),
                new PropertyMetadata(12.0, OnFontPropertyChanged));

        public static readonly DependencyProperty FontWeightProperty =
            DependencyProperty.Register("FontWeight",
                typeof(FontWeight),
                typeof(TextOnAPath),
                new PropertyMetadata(FontWeights.Normal, OnFontPropertyChanged));

        public static readonly DependencyProperty FontStretchProperty =
            DependencyProperty.Register("FontStretch",
                typeof(FontStretch),
                typeof(TextOnAPath),
                new PropertyMetadata(FontStretches.Normal, OnFontPropertyChanged));

        public static readonly DependencyProperty ForegroundProperty =
            DependencyProperty.Register("Foreground",
                typeof(Brush),
                typeof(TextOnAPath),
                new PropertyMetadata(new SolidColorBrush(Colors.Black), OnFontPropertyChanged));

        public static readonly DependencyProperty PathFigureProperty =
            DependencyProperty.Register("PathFigure",
                typeof(PathFigure),
                typeof(TextOnAPath),
                new PropertyMetadata(OnPathFigureChanged));

        // Properties
        public string Text
        {
            set { SetValue(TextProperty, value); }
            get { return (string)GetValue(TextProperty); }
        }

        public FontFamily FontFamily
        {
            set { SetValue(FontFamilyProperty, value); }
            get { return (FontFamily)GetValue(FontFamilyProperty); }
        }

        public FontStyle FontStyle
        {
            set { SetValue(FontStyleProperty, value); }
            get { return (FontStyle)GetValue(FontStyleProperty); }
        }

        public double FontSize
        {
            set { SetValue(FontSizeProperty, value); }
            get { return (double)GetValue(FontSizeProperty); }
        }

        public FontWeight FontWeight
        {
            set { SetValue(FontWeightProperty, value); }
            get { return (FontWeight)GetValue(FontWeightProperty); }
        }

        public FontStretch FontStretch
        {
            set { SetValue(FontStretchProperty, value); }
            get { return (FontStretch)GetValue(FontStretchProperty); }
        }

        public Brush Foreground
        {
            set { SetValue(ForegroundProperty, value); }
            get { return (Brush)GetValue(ForegroundProperty); }
        }

        public PathFigure PathFigure
        {
            set { SetValue(PathFigureProperty, value); }
            get { return (PathFigure)GetValue(PathFigureProperty); }
        }

        // Property-changed handlers
        static void OnFontPropertyChanged(DependencyObject obj,
                                          DependencyPropertyChangedEventArgs args)
        {
            (obj as TextOnAPath).OnFontPropertyChanged(args);
        }

        void OnFontPropertyChanged(DependencyPropertyChangedEventArgs args)
        {
            Children.Clear();

            if (String.IsNullOrEmpty(Text))
                return;

            foreach (char ch in Text)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.Text = ch.ToString();
                textBlock.FontFamily = FontFamily;
                textBlock.FontStyle = FontStyle;
                textBlock.FontWeight = FontWeight;
                textBlock.FontStretch = FontStretch;
                textBlock.FontSize = FontSize;
                textBlock.Foreground = Foreground;
                textBlock.HorizontalAlignment = HorizontalAlignment.Center;
                textBlock.VerticalAlignment = VerticalAlignment.Bottom;
                textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
                Console.WriteLine(ch.ToString() + ": " + textBlock.DesiredSize);
                Children.Add(textBlock);
                textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
                Console.WriteLine(ch.ToString() + ": " + textBlock.DesiredSize);
            }
            CalculateTransforms();
            InvalidateMeasure();
        }

        static void OnPathFigureChanged(DependencyObject obj,
                                        DependencyPropertyChangedEventArgs args)
        {
            (obj as TextOnAPath).OnPathFigureChanged(args);
        }

        void OnPathFigureChanged(DependencyPropertyChangedEventArgs args)
        {
            pathFigureHelper.SetPathFigure(args.NewValue as PathFigure);
            CalculateTransforms();
            InvalidateMeasure();
        }

        void CalculateTransforms()
        {
            double pathLength = pathFigureHelper.Length;
            double textLength = 0;
            double textDesiredWidth = 9;
            totalSize = new Size();

            foreach (UIElement child in Children)
            {
                child.Measure(new Size(Double.PositiveInfinity,
                                       Double.PositiveInfinity));
                textLength += child.DesiredSize.Width;
            }
            //textLength = Children.Count * textDesiredWidth;

            if (pathLength == 0 || textLength == 0)
                return;

            //double scalingFactor = pathLength / textLength;
            double baseline = FontSize;     // * FontFamily.Baseline;
            double progress = 0;

            if (textLength <= pathLength)
            {
                progress = ((pathLength - textLength) / 2) / pathLength;
            }

            foreach (UIElement child in Children)
            {
                double width = child.DesiredSize.Width;
                //double width = textDesiredWidth;
                progress += width / 2 / pathLength;
                Point point, tangent;

                pathFigureHelper.GetPointAtFractionLength(progress,
                                                out point, out tangent);

                TransformGroup transformGroup = new TransformGroup();

                //ScaleTransform scaleTransform = new ScaleTransform();
                //scaleTransform.ScaleX = scalingFactor;
                //scaleTransform.ScaleY = scalingFactor;
                //transformGroup.Children.Add(scaleTransform);

                RotateTransform rotateTransform = new RotateTransform();
                rotateTransform.Angle = Math.Atan2(tangent.Y, tangent.X) * 180 / Math.PI;
                rotateTransform.CenterX = width / 2;
                rotateTransform.CenterY = baseline;
                transformGroup.Children.Add(rotateTransform);

                TranslateTransform translateTransform = new TranslateTransform();
                translateTransform.X = point.X - width / 2;
                translateTransform.Y = point.Y - baseline;
                transformGroup.Children.Add(translateTransform);

                child.RenderTransform = transformGroup;

                BumpUpTotalSize(transformGroup.Value, new Point(0, 0));
                BumpUpTotalSize(transformGroup.Value, new Point(0, child.DesiredSize.Height));
                BumpUpTotalSize(transformGroup.Value, new Point(child.DesiredSize.Width, 0));
                BumpUpTotalSize(transformGroup.Value, new Point(child.DesiredSize.Width, child.DesiredSize.Height));

                progress += width / 2 / pathLength;
            }

            Point endPoint, endTangent;
            pathFigureHelper.GetPointAtFractionLength(1, out endPoint, out endTangent);
            totalSize.Width = Math.Max(totalSize.Width, endPoint.X);
        }

        void BumpUpTotalSize(Matrix matrix, Point point)
        {
            point = matrix.Transform(point);
            totalSize.Width = Math.Max(totalSize.Width, point.X);
            totalSize.Height = Math.Max(totalSize.Height, point.Y);
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (UIElement child in Children)
                child.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));

            // return the size calculated during CalculateTransforms
            return totalSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            foreach (UIElement child in Children)
                child.Arrange(new Rect(new Point(0, 0), child.DesiredSize));

            return finalSize;
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您应该将TextBox水平对齐到leftrightcenter。它默认为strech,因此将其扩展到可用区域。

修改

只是用一个小班来测试它:

public class TextOnAPath : Panel
{
    public TextOnAPath() {
        var textBlock = new TextBlock();
        textBlock.Text = "Test";
        textBlock.Background = Brushes.Blue;
        textBlock.VerticalAlignment = System.Windows.VerticalAlignment.Top;
        textBlock.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
        this.Children.Add(textBlock);

        this.Background = Brushes.Gray;
    }

    protected override Size MeasureOverride(Size availableSize) {
        return availableSize;
    }

    protected override Size ArrangeOverride(Size finalSize) {
        foreach (UIElement child in this.Children)
            child.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
        return finalSize;
    }
}

删除对齐会占用所有可用空间......可能是您的CalculateTransforms方法会导致效果吗?特别是,然后在MeasureOverride方法中使用结果。

答案 1 :(得分:0)

我弄清楚了问题,事实证明问题根本与控件无关,但在代码的某处,文本块的默认模板发生了变化,MinWidth和MinHeight被设置为40,18理由......现在找到嫌犯并对他们大喊大叫。

谢谢你们