Volkhard Vogeler
Volkhard Vogeler

Reputation: 27

WPF-Rendering with TranslateTransform and Label

i do have the following Code:

        private static void AddElements(Canvas canvas)
    {
        double canvasHeight = canvas.Height;
        double canvasWidth = canvas.Width;
        double y0 = canvasHeight / 2;
        double x0 = canvasWidth / 2;

        // Defining the new Coordinate-Point (0,0) to mid auf Canvas
        TranslateTransform tt = new TranslateTransform(x0, y0);

        Line line1 = new Line();
        line1.X1 = -350;
        line1.Y1 = 0;
        line1.X2 = 350;
        line1.Y2 = 0;
        line1.Stroke = Brushes.Black;
        line1.StrokeThickness = 2.0;
        line1.RenderTransform = tt;
        canvas.Children.Add(line1);

        Line line2 = new Line();
        line2.X1 = 0;
        line2.Y1 = -350;
        line2.X2 = 0;
        line2.Y2 = 350;
        line2.Stroke = Brushes.Black;
        line2.StrokeThickness = 2.0;
        line2.RenderTransform = tt;
        canvas.Children.Add(line2);


        Label lblN = new Label();
        lblN.Width = 50;

        lblN.Background = Brushes.Red;
        lblN.Margin = new System.Windows.Thickness(0, -350, 0, 0);
        lblN.Content = $"N";
        lblN.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center;
        lblN.VerticalContentAlignment = System.Windows.VerticalAlignment.Center;
        lblN.RenderTransform = tt;
        lblN.Padding = new System.Windows.Thickness(0);
        lblN.BorderBrush = Brushes.Black;
        lblN.BorderThickness = new System.Windows.Thickness(2.0);
        lblN.RenderTransform = tt;
        canvas.Children.Add(lblN);

        Label lblS = new Label();
        lblS.Width = 50;
        lblS.Background = Brushes.Red;
        lblS.Margin = new System.Windows.Thickness(0, 350, 0, 0);
        lblS.Content = $"S";
        lblS.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center;
        lblS.VerticalContentAlignment = System.Windows.VerticalAlignment.Center;
        lblS.RenderTransform = tt;
        lblS.Padding = new System.Windows.Thickness(0);
        lblS.BorderBrush = Brushes.Black;
        lblS.BorderThickness = new System.Windows.Thickness(2.0);
        lblS.RenderTransform = tt;
        canvas.Children.Add(lblS);
    }

this method is called on an Menu-Eventhandler and it shows an coordinate system with (0,0) in the mid of the canvas. It should show a label with "N" at the top and a label with "S" at the bottom.

But i shows the attached image enter image description here

Does anyone know, why lblN looks different than lblS ?

best regards

Volkhard

=============

if i set the height of both Label-Objects to 15

lblN.Height=15
:
lblS.Height=15

i get the following: With Setting Height to 15 i expected the lblN to be more upper on the y-coordinate.

Upvotes: -1

Views: 204

Answers (1)

Keith Stein
Keith Stein

Reputation: 6766

What's causing it

Through a bit of testing, I can definitely say that it's the lblN.Margin = new System.Windows.Thickness(0, -350, 0, 0); that's causing the problem. Apparently, when you give a Label a negative margin like that, it will move upwards only as far is it's Height, and then it will start expanding instead of just continuing to move. So you end up with a Label that's 350 tall. We could try to figure out why that is, but really, that would be missing the point.

Admittedly, I don't have any direct documentation to back up the following statement this, but from years of experience in WPF I feel I can say:

Margin is intended to be used to give space between elements in a dynamic layout, not to give an element an absolute position.

This behavior of the Label seems to strengthen the idea that using Margin in this way was not something that was planed for by the designers.

What you should do instead

Canvas has tools for giving an element a set position, yet nowhere do you use Canvas's SetLeft, SetTop, SetRight, or SetBottom. Take a look at the example on MSDN. You shouldn't need to use a TranslateTransform or set Margin at all. Instead, you should calculate where you want the element to be and use one of the above four listed methods to assign that position.

Extra Tip

Don't use canvas.Height and canvas.Width, use canvas.ActualHeight and canvas.ActualWidth instead. The first pair only work if you are explicitly setting the size of the Canvas (which it seems you are). But in a senario where the Canvas is dynamically sized, the first pair will be NaN. The second pair always return the actual size that the Canvas is.

This doesn't make a difference in your current use case, but it might later on. If you're doing calculations based on the actual size of an element (as opposed to the size you might want it to be), always use ActualHeight and ActualWidth.

Upvotes: 0

Related Questions