Windows Phone 7 : UI Control Boundaries

I was working on an application at work when I needed to figure out a really trivial case, well, trivial in theory at least. All I wanted to know was if a button was completely inside a rectangle. Could anything else be simpler you think. Just check the button bounds against the rectangle bounds,

pseudocode
if (Button.Top > Rectangle.Top &&
      Button.Left > Rectangle.Left &&
      Button.Right < Rectangle.Right &&
      Button.Bottom < Rectangle.Bottom)
{
    //Button is inside rectangle
}

the Right and Bottom of the Button and Rectangle can be calculated using the Width and the Height properties of each. You’d expect this to work correctly, but as far as Windows Phone 7 is concerned there is only one caveat.

I wrote up a simple application to illustrate this. Create a Windows Phone 7 Silverlight application and add the following to the ContentPanel grid in Mainpage.xaml,

  1. <Grid x:Name="ContentPanel" Grid.Row="1">
  2.     <Canvas x:Name="MainCanvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
  3.         <TextBlock x:Name="RectangleTop" Canvas.Top="0" />
  4.         <TextBlock x:Name="ButtonTop" Canvas.Top="30" />
  5.         <Rectangle x:Name="ColoredRectangle" Width="480" Height="150" Fill="Coral" Opacity="0.4" Canvas.Top="150" Canvas.Left="0"/>
  6.         <Button x:Name="MyButton" Content="Move Me" Canvas.Top="400" Canvas.Left="160" Background="Purple"/>
  7.     </Canvas>           
  8. </Grid>

the constructor of Mainpage looks like this,

  1. public MainPage()
  2. {
  3.     InitializeComponent();
  4.  
  5.     MyButton.ManipulationDelta += new EventHandler<ManipulationDeltaEventArgs>(OnMyButtonManipulationDelta);
  6.  
  7.     RectangleTop.Text = String.Format("Rectangle Top: {0}", Canvas.GetTop(ColoredRectangle));
  8.     ButtonTop.Text = String.Format("Button Top: {0}", Canvas.GetTop(MyButton));
  9. }

We register for the ManipulationDelta event on the button and update the Text on the two Textblocks to show the Top properties of the rectangle and the button, if you run the program this is how the application will look,

FirstScreen

The OnMyButtonManipulationDelta() function will be called whenever a ManipulationDelta event occurs on the MyButton control, which happens when the user clicks and drags the button around. Here we want to move the button along with the users drag,

  1. void OnMyButtonManipulationDelta(object sender, ManipulationDeltaEventArgs e)
  2. {
  3.     double deltaX = e.DeltaManipulation.Translation.X;
  4.     double deltaY = e.DeltaManipulation.Translation.Y;
  5.  
  6.     double btnX = Canvas.GetLeft(MyButton);
  7.     double btnY = Canvas.GetTop(MyButton);
  8.  
  9.     btnX += deltaX;
  10.     btnY += deltaY;
  11.  
  12.     Canvas.SetLeft(MyButton, btnX);
  13.     Canvas.SetTop(MyButton, btnY);
  14.  
  15.     ButtonTop.Text = String.Format("Button Top: {0}", Canvas.GetTop(MyButton));
  16. }

In this function we get the delta manipulation values along the X and Y axis and add it to the Buttons Left and Top property, this makes sure that the button control moves along with the users finger when he/she clicks and drags the button.

Now when we move the button and place it inside the rectangle the values on the textblocks update,

ButtonInsideRect

Things are fine till here, but they start getting interesting when you move the button to the top of the rectangle,

ButtonTopLessThanRectTop

the Button control appears to be well inside the Rectangle but the Top property of the button is 144 where as that of the Rectangle is 150. The values suggest that the button is outside the rectangle!

This happens because there is more to a button control than what meets the eyes. The button is not confined within the white rectangular boundary but is much bigger than that. When you drag and drop a button control using the visual editor in Visual Studio, the area of the button that is selected is bigger than the button itself, (see image below)

ButtonControlSelected

This is intentional and done to make sure that the target area for the user is a bit larger than the control itself so that the control can be selected easily without requiring too much precision. This, of course, is a nice feature (ask anyone who has tried using a Windows Mobile touch screen device with a finger ;)

Placing the Button control precisely on top of the rectangle like below,

ButtonOnTopOfRect

reveals that there are 12 extra pixels on all sides of the button control. (rectangle top = 150,  button top = 138)

So that is all in this post. In the next post we’ll see how easy it is to pick a button control and flick it, the button will bounce around the screen and come to a halt gradually. Refreshing old memories of marbles ;)

 

Post attachments
Source Code: ButtonBoundaries.zip

Update:
I forgot to add that the same case is also true for textbox and password box control

Update 2
I just recorded a short video of the application in action,