Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 1098649
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 17, 20262026-05-17T00:36:32+00:00 2026-05-17T00:36:32+00:00

I have a custom Panel for laying out text. There is a DependancyProperty called

  • 0

I have a custom Panel for laying out text. There is a DependancyProperty called “Text” and when that value changes, this piece of code runs:

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);
        }
    }
}

Now, with font size of 15 and font Arial, these should be giving me a desired size of around 8 width and 10 height. However, when I do a Measure() and check the desired size, I get 40,18 every time!

So in trying to figure out what could’ve possibly changed the size, I put this code before and after the Children.Add in the code above:

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);

What this gave me, was the proper desired size before it’s added to the children collection, and a size of 40,18 (regardless of letter) after it’s added to the collection.

What is causing this to happen?

Edit: You can find the full source for the control here:

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;
        }
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-17T00:36:33+00:00Added an answer on May 17, 2026 at 12:36 am

    I figured out the problem, it turns out that the problem was not related to the control at all, but somewhere in the code the default template for a textblock got changed, and MinWidth and MinHeight got set to 40,18 for some reason… Now to find the suspect and to yell at them.

    Thanks guys

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have created a custom panel (MyCustomControl) that can contain other controls and be
I have a simple usercontrol that uses a simple custom panel where I just
I have created the custom control which is just a panel that I will
I have a few models that need to have custom find conditions placed on
hi i would like to create a custom calendar, this calendar will have custom
I have a custom control that implements IPostBackEventHandler. Some client-side events invoke __doPostBack(controlID, eventArgs).
I have a custom installer action that updates the PATH environment, and creates an
We have a custom-built Flash-based video player that I maintain, and it needs to
I have a custom Panel which upon resizing has its LayoutUpdated event and ArrangeOverride
I have a custom panel for a listbox <ItemsPanelTemplate x:Key=FloatPanelTemplate> <Controls:FloatPanel x:Name=CardPanel /> </ItemsPanelTemplate>

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.