How to focus a TextBlock at a given position

The TextBlock should be centered at x (or y when the orientation is vertical). I implemented:

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 

This works very well, but is it possible to do this without UpdateLayout . If I delete UpdateLayout , then I will not get the position I'm looking for, because ActualWidth is (of course) zero.

+7
source share
2 answers

Perhaps you can do this by Canvas.Top / Canvas.Left values ​​to the TextBlock ActualWidth / ActualHeight and using Converter .

Here is an example. I use a custom MathConverter , which I usually use for mathematical formulas (the code can be found here ), but you can also use a simple converter that returns half of any transmitted value.

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

Edit

Just re-read the question and realized that you are trying to center the TextBlock at a specific x, y coordinate on the canvas. In this case, you need to implement MultiConverter instead of the usual Converter , so that you can pass two parameters to it: the X / Y value and the ActualHeight / ActualWidth value

+3
source

I assume that you wrote this code in the constructor. That would be the reason why ActualWidth doesn't matter. All code has not been tested (there is no IDE). You need to do this after the loaded event, after WPF has built the layout. This is a routable event, by the way.

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

This code is likely to work. Of course, as I read your code, this code seems to be in the constructor from the class that you got from Canvas. Generally, there is no need to do this, unless you really need to extend the basic functions of the canvas control. You can make reusable components on top of existing controls by creating a UserControl. This approach is especially recommended if you do not need to override any Canvas method.

Alternatively, if you just want to have a centered element inside the container, the following xaml will do it just fine:

  <Grid> <TextBlock Text="Haha!" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> 
0
source

All Articles