TextBlock应居中于位置x(或方向为垂直时为y)。 我实施了:
TextBlock text = new TextBlock();
// Some code to define text, font, etc. here
// Turn if Orientation is vertical
if (Orientation == Orientation.Vertical)
{
text.RenderTransform = new RotateTransform() { Angle = 270 };
}
// Update, then ActualWidth is set correctly
text.UpdateLayout();
// Position of label centered to given position
double halfWidth = text.ActualWidth / 2;
double x1 = (Orientation == Orientation.Horizontal) ? x - halfWidth : x;
double y1 = (Orientation == Orientation.Horizontal) ? y : y + halfWidth;
Canvas.SetLeft(text, x1);
Canvas.SetTop(text, y1);
Children.Add(text); // Add to Canvas
这实际上很好,但是可以在没有UpdateLayout
的情况下执行此操作。如果我删除UpdateLayout
,那么我找不到我想要的位置,因为ActualWidth(当然)为零。
答案 0 :(得分:3)
您可以通过将Canvas.Top
/ Canvas.Left
值绑定到TextBlock的ActualWidth
/ ActualHeight
并使用Converter
来实现此目的。
这是一个例子。我正在使用我通常用于数学公式的自定义MathConverter
(代码可以找到here),但您也可以使用普通转换器返回其传递的任何值的一半。
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="Canvas.Left"
Value="{Binding RelativeSource={RelativeSource Self},
Path=ActualWidth,
Converter={StaticResource MathConverter},
ConverterParameter=@VALUE/2}" />
</Trigger>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="Canvas.Top"
Value="{Binding RelativeSource={RelativeSource Self},
Path=ActualHeight,
Converter={StaticResource MathConverter},
ConverterParameter=@VALUE/2}" />
</Trigger>
</Style.Triggers>
</Style>
修改强>
重新阅读问题并意识到您正试图将TextBlock置于Canvas上特定的x,y坐标中心。在这种情况下,您需要实现MultiConverter
而不是常规Converter
,以便您可以传递两个参数:X / Y值和ActualHeight / ActualWidth值
答案 1 :(得分:0)
我假设您在构造函数中编写了此代码。这就是为什么ActualWidth没有值的原因。 所有代码尚未经过测试(没有可用的IDE)。在WPF构建布局之后,您需要在Loaded Event之后执行此操作。这是一个路由事件,顺便说一句。
public class Class1{
public Class1 ()
{
this.Loaded += (sender, args) =>
{
TextBlock text = new TextBlock();
if (Orientation == Orientation.Vertical)
{
text.RenderTransform = new RotateTransform() { Angle = 270 };
}
double halfWidth = text.ActualWidth / 2;
double x1 = (Orientation == Orientation.Horizontal) ? x - halfWidth : x;
double y1 = (Orientation == Orientation.Horizontal) ? y : y + halfWidth;
Canvas.SetLeft(text, x1);
Canvas.SetTop(text, y1);
Children.Add(text);
};
}
此代码可能会有效。当然,在我阅读代码的方式中,这段代码似乎位于您从Canvas派生的类的构造函数中。通常应该没有必要这样做,除非您真的需要扩展canvas控件的核心功能。您可以通过创建UserControl在现有控件之上创建可重用组件。如果您不需要覆盖Canvas的任何方法,则应特别使用此方法。
或者,如果您只想在容器中放置一个居中的项目,那么下面的xaml就可以做到这一点:
<Grid>
<TextBlock Text="Haha!" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>