添加到面板的文本块会自动调整大小
我有一个用于布局文本的自定义面板。有一个名为“Text”的 DependencyProperty,当该值更改时,这段代码将运行:
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;
}
}
}
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;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该将 TextBox 水平对齐到
左
、右
或中心
。它默认对齐为strech
,从而将其扩展到可用区域。编辑
只需用一个小类对其进行测试:
删除对齐会占用所有可用空间...是否是您的
CalculateTransforms
方法导致了这种效果?特别是,因为结果将在 MeasureOverride 方法中使用。You should horizontally align you TextBox to the
left
,right
, orcenter
. It is aligned asstrech
per default, thus expandig it to the available area.Edit
Just testet it with a little class:
Removing the alignments takes up all available space ... could it be that your
CalculateTransforms
method causes the effect? Especially, as the outcome is then used in theMeasureOverride
method.我发现了问题,事实证明问题根本与控件无关,但是代码中的某个地方文本块的默认模板发生了更改,并且 MinWidth 和 MinHeight 由于某种原因设置为 40,18 。现在要找到嫌疑人并对他们大喊大叫。
谢谢大家
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