Я предполагаю, что вы написали этот код в конструкторе.Это было бы причиной, почему ActualWidth не имеет значения. Весь код не был протестирован (нет IDE).Это необходимо сделать после Loaded Event, после того как WPF построит макет.Это перенаправленное событие, кстати.
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>