WPF - Finding Control Location
Recently for a sample application I was building in WPF, I had to find the location of a button control on the window. Playing around with Button.Margin didn't help much since it gave the position with reference to the immediate parent. So if the button was inside a Grid and the grid itself inside say a StackPanel, the values were incorrect.
Searching on the forums, I got some ideas and following is what worked for me
GeneralTransform transform = button1.TransformToAncestor(this);
Point rootPoint = transform.Transform(new Point(0, 0));
button1 is the control for whom I wanted to find the location. The this represents the top level window. The value obtained in rootPoint is the Left and Top cordinates of the button with respect to the top level window. Adding button's height and width will give the complete location details.



Comments
Can you explain how can I achieve the same functionality in .Net 1.0 Or 1.1 ?
Posted by: Ayan Mitra | November 23, 2007 9:12 AM
Ayan, for .net controls in Winform applications, you can usually do a Control.Location to get the cordinates of the control wrt to its immediate parent. If you want it wrt to its top level parent form, somethign like the following should work
Control.FindForm().PointToClient(Control.Parent.PointToScreen(Control.Location))
The conversion of control's coordinates to screen coordinates should be done wrt to its parent, otherwise there will be a difference equal to the border of the Form.
Posted by: Atul Gupta | November 26, 2007 3:15 AM
I used GeneralTransformation in wpf it works fine with stack panel and grid but as soon as Put my control in tab control (on tab pages it gives error :---
"The specified Visual is not an ancestor of this Visual."
So with tab control how to remove this error or is there any other way in WPF?
Posted by: Prasad | May 6, 2008 6:24 AM
I got the solution for WPF,
Use following to get location of control :--
// Return the offset vector for the TextBlock object.
Vector vector = VisualTreeHelper.GetOffset(myTextBlock);
// Convert the vector to a point value.
Point currentPoint = new Point(vector.X, vector.Y);
Posted by: Prasad | May 6, 2008 6:33 AM
Thanks Prasad for sharing your findings
Posted by: Atul Gupta | May 8, 2008 2:04 AM
Can you please tell me how to dynamically add a control to a canvas at a particular location .
Posted by: sreeraj | October 16, 2008 10:02 AM
Sreeraj, you can use the Canvas.SetLeft, Canvas.SetRight etc attached properties. something like this should work
Button btn = new Button();
btn.Content = "Click Me";
Canvas.SetLeft(btn, 50);
Canvas.SetTop(btn, 40);
LayoutRoot.Children.Add(btn);
(where LayoutRoot is a Canvas)
Posted by: Atul Gupta | October 17, 2008 7:43 AM
Hello Atul,
Tried this code on different window size and on different location on the screen.
Doesn't seem to work.
Posted by: KJ | January 28, 2009 11:20 AM
KJ, can you share more details on what you tried and what didn't work?
Posted by: Atul Gupta | January 30, 2009 12:45 PM
Can someone please tell me how can I set control location in the page? In c#, I used to set it like:
ctrl.Location = new point (int,int)
Posted by: eran | February 11, 2009 4:11 PM
Eran, is your question related to WPF or Winform? In WPF, the control location can be set as I had shown a few comments earlier.
Note however this will also depend on what Panel is the control residing inside of, as not all panels allow contols to positioned at any location. In such containers you need work with Margins and padding and not really location.
Posted by: Atul Gupta | February 17, 2009 2:38 AM
I am using code below to get the position of a ContectMenu as I want to place an image at the point the user right clicks. However, the "currentPoint" is always 0,0. What am I doing wrong here?
private void MenuItemNewShop_Click(object sender, RoutedEventArgs e)
{
TabItem ti = tabControl1.SelectedItem as TabItem;
MenuItem mi = sender as MenuItem;
ContextMenu cm = mi.Parent as ContextMenu;
Vector vector = VisualTreeHelper.GetOffset(mi);
Point currentPoint = new Point(vector.X, vector.Y);
Posted by: Stewart Clark | July 21, 2009 9:11 PM