by
kirupa | 30 December 2009
Imagine a world where you didn't have to deal
with crazy positioning schemes. In this world,
everything makes sense. Up is truly up, right is
truly right, and the top-left corner always has a 0
for its x/y coordinates. Of course, while you may
think such a world does not exist, you get very
close in Silverlight and WPF if all you want to do
is read an element's position.
In this short article, I will explain just that -
how to read the position of an element with the
added advantage that your reading is independent of
whatever layout container the element is
in. This is possible thanks to the
TransformToVisual
method, and the following two
lines of code give an example of its use:
- GeneralTransform
generalTransform
=
myElement.TransformToVisual(null);
- Point
point
=
generalTransform.Transform(new
Point());
Before looking at the code, let's set up an
example first. My application consists of a UI that
looks as follows:
[ a simple UI with a handful of elements ]
Right now, I am interested in the position of the
green Log-In button. The way I would get the position is by
taking the above two lines of code and replacing the
highlighted word with the actual name of the green
button itself:
- GeneralTransform
generalTransform
=
logInButton.TransformToVisual(null);
- Point
point
=
generalTransform.Transform(new
Point());
In our code, the position is calculated by simply
taking the the distance from the top-left corner of
your application. That is what the
TransformToVisual
method returns when a null argument is passed in.
The position is originally stored as a
GeneralTransform object with a lot of additional
things that we don't care about, so in the second
line, we distill the information that we want and
store it in our Point object called
point.
To get the actual X and Y positions from the
point object, simply call the X and Y properties on
it:
- MessageBox.Show(point.X
+
" "
+
point.Y);
This wraps up what you most likely came here to
learn about - how to get the absolute position of an
element with your application's top-left corner as
the origin.
The last thing I will briefly discuss is one
quirk in Silverlight that you may not have in WPF.
It is very common for you to have any code related
to layout and position be called from a
Loaded event's event
handler.
Unfortunately, Loaded does not mean the same as
"everything has been laid out as planned." That
means, if you place your TransformToVisual code
inside the Loaded event handler, the values returned
may not exactly be accurate. Instead, if you want to
get the absolute position the moment your
application "loads", use the
LayoutUpdated event
instead. That event only fires after everything has
been laid out, so the position returned will be
accurate.
Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!
|