Search code examples
windows-runtimesizecenteruielement

Get Size of UIElement in WinRT


I have a canvas. When I click it, I get the coordinates of the mouse and up (adds a child) has custum control (a thumb with a simply circle) there. On the screen, logically, the upper left corner is taken as reference when adding. I will wish to place the center of thumb exactly where I click (see picture. Red star = Where I click).

enter image description here

To do what, I need to get the actual width and height of the thumb, And Then calculate the exact coordonate to place the center of the thumb where the user clicked. Is there a better way ? In WPF, I used this code, but it doen't work in WinRT.

 //Circle in thumb
 Ellipse Bdr = this.GetTemplateChild("Forme") as Ellipse;
 DependencyObject dobj = VisualTreeHelper.GetParent(Bdr);
 Vector ParentPosition = VisualTreeHelper.GetOffset((Visual)VisualTreeHelper.GetParent(dobj));
 Vector BdrPosition = VisualTreeHelper.GetOffset((Visual)dobj);
 return new Point((Position.X+BdrPosition.X) + Bdr.ActualWidth /2,(Position.Y+ ParentPosition.Y) + Bdr.ActualHeight / 2);

Can you help me ? Thanks !


Solution

  • The ActualHeight and ActualWidth properties remain 0 until the FrameworkElement isn't loaded. On other hand, if you've sized Ellipse in ControlTemplate, you can get it's size on OnApplyTemplate(). You can use delegate to pass height and width to container Page. i.e.

    ThumbControl

    public class ThumbControl : Control
    {
        public IThumbSize thumbSize;
        public ThumbControl()
        {
            this.DefaultStyleKey = typeof(ThumbControl);
        }
    
        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            Ellipse child = this.GetTemplateChild("circle") as Ellipse;
            if (thumbSize != null)
                thumbSize.SizeMeasured(child.Width, child.Height);
        }
    }
    

    ThumbControl's Style

     <Style TargetType="local:ThumbControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:ThumbControl">
                        <Ellipse x:Name="circle"
                                 Fill="Blue"
                                 Height="50"
                                 Width="50"></Ellipse>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
      </Style>
    

    IThumb interface

    public interface IThumbSize
    {
        void SizeMeasured(double width, double height);
    }
    

    ContainerPage.xaml

    <Grid Background="Black">
        <Canvas x:Name="rootCanvas"
                Background="Transparent"
                PointerReleased="rootCanvas_PointerReleased"></Canvas>
    </Grid>
    

    ContainerPage.xaml.cs

    public sealed partial class ContainerPage: Page, IThumbSize
    {
        ThumbControl thumbControl = new ThumbControl();
        Point touchPoint = new Point();
        public ContainerPage()
        {
            this.InitializeComponent();
            thumbControl.thumbSize = this;
        }
    
        private void rootCanvas_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            PointerPoint pt = e.GetCurrentPoint(rootCanvas);
            touchPoint.X = pt.Position.X;
            touchPoint.Y = pt.Position.Y;
            if (!rootCanvas.Children.Contains(thumbControl))
                rootCanvas.Children.Add(thumbControl);
            Canvas.SetLeft(thumbControl, touchPoint.X - (thumbControl.ActualWidth / 2));
            Canvas.SetTop(thumbControl, touchPoint.Y - (thumbControl.ActualHeight / 2));
        }
    
        public void SizeMeasured(double width, double height)
        {
            Canvas.SetLeft(thumbControl, touchPoint.X - (width / 2));
            Canvas.SetTop(thumbControl, touchPoint.Y - (height / 2));
        }
    }
    

    Hope it helped.