views:

27

answers:

3

I am new in WPF, I created a new UserControl MyUserControl.

Now I am surprised: the UserContol does not have a location.

How can I read (by code) myUserControl1.Location in the parent container?

I explain:

I have some Dots (UserControls) that the user can drag in a panel. Actually, I am not sure what kind of Panel this will be... Perhaps Grid.

Now, these dots should be linked with a Line.

Actually, I have a Dot.Head and Dot.Queue properties (also Dots). So, when a Head or Queue is added, I need to dinamically create a link (Line) between them [A]-----[B]. This for this Line I search the Start and End points to set.

Control XAML:

<UserControl x:Class="LinePlan.Stop"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d" d:DesignHeight="21" d:DesignWidth="80">
    <Canvas>
        <Path Fill="LightBlue" Width="16" Height="16">
            <Path.Data>
                <EllipseGeometry x:Name="Dot" Center="8,8" 
                    RadiusX="4" RadiusY="4"/>
            </Path.Data>
        </Path>
        <TextBlock x:Name="StopText" Text="Eiffel Tower" Canvas.Left="16"/>
    </Canvas>
</UserControl>

Code:

public partial class Stop : UserControl
{
    private Stop head;
    private Stop tail;
    private LineGeometry headLine;
    private LineGeometry queueLine;

    public Stop()
    {
        InitializeComponent();
    }

    public Stop Head
    {
        get { return head; }
        set
        {
            if (head != value)
            {
                head = value;
                if (head == null) 
                {
                    if (headLine != null)
                        headLine = null;
                }
                else
                {
                    headLine = new LineGeometry();
                    headLine.StartPoint = head.DotPosition;
                    headLine.EndPoint = this.DotPosition;

                    // ?? Add this line to the parent
                }

            }
        }
    }

    public Stop Tail
    {
        get { return tail; }
        set { tail = value; }
    }

    public Point DotPosition
    {
        get
        {
            double x = Canvas.GetLeft(this) + this.Dot.Center.X;
            double y = Canvas.GetTop(this) + this.Dot.Center.Y;
            return new Point(x, y);
        }
        set
        {
            Canvas.SetLeft(this, value.X - this.Dot.Center.X);
            Canvas.SetTop(this, value.Y - this.Dot.Center.Y);
        }
    }
}
+1  A: 

Elements (like user controls) are normally placed in panels in WPF. Depending on which panel you are using the panel may add some attached properties to the user control. If the user control is placed in a Canvas it will get the attached properties Left, Top, Right and Bottom. However, if the user control is placed in a Grid it will get the attached properties Row and Column (and some more). Other panels like StackPanel will not attach any properties. There is no such thing as a universal user control location.

Panels Overview

Attached Properties Overview

Assuming that you are using a Canvas as your panel you can access the attached Left and Top properties like this:

Double x = Canvas.GetLeft(myUserControl1);
Double y = Canvas.GetTop(myUserControl1);
Martin Liversage
+1  A: 

I guess you're using a canvas

control.GetValue(Canvas.LeftProperty)
control.GetValue(Canvas.TopProperty)
vc 74
You need to specify Canvas.Left and Canvas.Top on your Path element
vc 74
+1  A: 

The WPF layout system doesn't use absolute positioning, unless you're placing your controls on a container that supports absolute positioning (typically a Canvas). If you're using a Canvas, you can get or set the position of the control using the Canvas.Left, Canvas.Right, Canvas.Top and Canvas.Bottom attached properties:

double x = Canvas.GetLeft(myControl);
double y = Canvas.GetTop(myControl);

Now, if you want the actual location of the control (relative to its parent), you can use the VisualTreeHelper.GetOffset method:

Vector offset = VisualTreeHelper.GetOffset(myControl);
double x = offset.X;
double y = offset.Y;
Thomas Levesque
thank you. I added a little explanation in the topic.
serhio
According to your explanation, I think the only candidate panel for you is Canvas...
Thomas Levesque
I added the real code... NAN is returned as positions, at least in design mode...
serhio
I tested in runtime too... see the code above: both `this.GetValue(Canvas.LeftProperty)` and `Canvas.GetLeft(this)` returns NAN ...
serhio
The Left and Top attached properties only have a value if you set it explicitly. If you want the actual value, use VisualTreeHelper.GetOffset
Thomas Levesque