Search code examples
c#wpfuser-interfaceuser-controls

UserControl positioning understanding


I'm getting close to the understanding of the positioning of the System.Windows.Controls.UserControl objects:
By default, they don't have X or Y coordinates, relative to their container, but there is the possibility to add some, using so-called "Attached Properties".
A typical example of such attached properties are Canvas.Left and Canvas.Top, which mean that, in case the container of the UserControl is a Canvas, then the following happens with (supposingly) its upper left point (pseudo-code):

UserControl_UpperLeft_Point.X = Canvas.Left
UserControl_UpperLeft_Point.Y = Canvas.Top

Now what I'd like to know:

  • Is my idea correct? Is it indeed the upper left corner which is used?

  • What if I want to modify this behaviour, let's say into:

    int left_Margin = 100;
    int top_Margin  = 200;
    UserControl_UpperLeft_Point.X = Canvas.Left / 2 + left_Margin; 
    UserControl_UpperLeft_Point.Y = Canvas.Top  * 2 + top_Margin;
    
  • What if I want to position my UserControl, based on the upper right corner or even the center?


Solution

  • Is my idea correct? Is it indeed the upper left corner which is used?

    It is effectively the upper left corner in this case, but actually each of the sides are aligned. Furthermore, the control is aligned by the Canvas, it does not have internal X or Y coordinates that are set. They are given by the attached properties which are sepcific to the Canvas, no other panel. The Canvas internally calculates a rectangle where it draws the UserControl.

    • Canvas.Left

      Gets or sets a value that represents the distance between the left side of an element and the left side of its parent Canvas.

    • Canvas.Top

      Gets or sets a value that represents the distance between the top of an element and the top of its parent Canvas.

    It is also important to note, that there is a priority for the attached properties.

    If you specify them, the attached properties Canvas.Top or Canvas.Left take priority over Canvas.Bottom or Canvas.Right.


    What if I want to modify this behaviour, let's say into: [...]

    You would still have to assign the attached properties, but calculate the expression before.

    • Use a Binding or MultiBinding with a custom value converter that evaluates an expression that is bound or passed as converter parameter or with a specialized value converter to calculate a specific term.
    • Create your own specialized attached properties that internally assign the calculated value to the Canvas attached properties.

    What if I want to position my UserControl, based on the upper right corner

    Set the Canvas.Top and Canvas.Right attached properties instead.

    <Canvas>
       <local:MyUserControl Canvas.Top="0" Canvas.Right="0" Width="50" Height="80"/>
    </Canvas>
    

    [...] or even the center?

    A Canvas is used for absolute positioning. If you want to center controls, a Grid might be the better choice. If you still want to use a Canvas and it is fixed size, just calculate the center coordinates yourself and set the attached properties accordingly. If it is resizeable and the position of the UserControl position needs to be responsive to that, you could do one of these.

    • Put a Grid around the Canvas and put the UserControl after it. It will appear on top of the Canvas and will be centered automatically, even on resizing.

      Grid>
         <Canvas>
            <Rectangle Canvas.Top="80" Canvas.Left="20" Fill="Black" Width="50" Height="50"/>
            <Rectangle Canvas.Top="300" Canvas.Left="230" Fill="Black" Width="100" Height="80"/>
         </Canvas>
         <local:MyUserControl Width="50" Height="80"/>
      </Grid>
      
    • Implement a custom behavior or complicated bindings with converter using the bound ActualSize of the Canvas to set the attached properties, which I do not recommend.

    I think for your last question it is more useful to ask why you need this behavior, what you want to achieve. Often there is a much simpler and more suitable solution.