Wednesday, June 18, 2014

Pinch To Zoom functionality in Windows Phone

If you're building a WP8 exclusive app you can use the new ManipulationDeltaEventArgs.PinchManipulation for pinch & zoom effects. Here's a basic example of how to use ManipulationDeltaEventArgs.PinchManipulation data to scale, move and rotate an image.
 
First, we'll create a basic image hovering in the middle of a grid:
 
<Grid x:Name="ContentPanel">
<Image Source="Assets\Headset.png" Width="200" Height="150" ManipulationDelta="Image_ManipulationDelta" x:Name="img" >
<Image.RenderTransform>
<CompositeTransform CenterX="100" CenterY="75" />
</Image.RenderTransform>
</Image>
</Grid>
 
Next, we'll handle the ManipulationDelta event, check if it's a Pinch Manipulation and apply the correct Silverlight transformations on our UIElement.
 
private void Image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
if (e.PinchManipulation != null)
{
        
var transform = (CompositeTransform)img.RenderTransform;
 
// Scale Manipulation
transform.ScaleX = e.PinchManipulation.CumulativeScale;
transform.ScaleY = e.PinchManipulation.CumulativeScale;
 
// Translate manipulation
var originalCenter = e.PinchManipulation.Original.Center;
var newCenter = e.PinchManipulation.Current.Center;
transform.TranslateX = newCenter.X - originalCenter.X;
transform.TranslateY = newCenter.Y - originalCenter.Y;
 
// Rotation manipulation
transform.Rotation = angleBetween2Lines(
e.PinchManipulation.Current,
e.PinchManipulation.Original);
 
// end
 
e.Handled = true;
 
}
}
 

public static double angleBetween2Lines(PinchContactPoints line1, PinchContactPoints line2)
{
if (line1 != null && line2 != null)
{
double angle1 = Math.Atan2(line1.PrimaryContact.Y - line1.SecondaryContact.Y, line1.PrimaryContact.X - line1.SecondaryContact.X);
double angle2 = Math.Atan2(line2.PrimaryContact.Y - line2.SecondaryContact.Y, line2.PrimaryContact.X - line2.SecondaryContact.X);
return (angle1 - angle2) * 180 / Math.PI;
}
else
{
return 0.0;
}
}



Scaling: PinchManipulation actually tracks scaling for us, so all we had to do is apply PinchManipulation.CumulativeScale to the scaling factor.

Transform: PinchManipulation tracks the original center and the new center (calculated between the two touch points). By subtracting the new center from the old center we can tell how much the UIElement needs to move and apply that to a translate transform. Note that a better solution here would also account for multiple Manipulation sessions by tracking cumulative original centers which this code doesn't.

Rotation: We figured out the angle between the two touch points and applied it as the rotation transform.
 
 

Monday, June 9, 2014

Find listbox item after tap and hold

First, make sure to put your gesture listener not under the ListBox itself, but in the top level container of the ListBox's data template (the StackPanel in this example):


<ListBox>  
    <ListBox.ItemTemplate>  
        <DataTemplate>   
            <StackPanel>   
                <toolkit:GestureService.GestureListener>   
                    <toolkit:GestureListener Hold="ListItem_Hold"/>   
                </toolkit:GestureService.GestureListener>   
                <TextBlock Text="{Binding LineOne}"/>   
                <TextBlock Text="{Binding LineTwo}"/>   
            </StackPanel>   
        </DataTemplate>  
    </ListBox.ItemTemplate>  
</ListBox> 

In the Hold event handler, the sender will be the StackPanel of the current ListBoxItem. The DataContext of the StackPanel is the view model item (it is like listbox.SelectedItem when an item is selected, however note that a hold gesture won't actually cause an item to be selected).

private void ListItem_Hold(object sender, GestureEventArgs e) 
        { 
            // sender is the StackPanel in this example 
            var holdItem = (sender as StackPanel).DataContext; 
 
            // holdItem has the type of the view model 
        } 

Sunday, June 8, 2014

Clearing backstack in NavigationService

You can use NavigationService.RemoveBackEntry:
For instance, to remove all entries from the stack:
while (this.NavigationService.BackStack.Any())
{
   this.NavigationService.RemoveBackEntry();
}

Also, if you want to remove only the previous page after checking its URI:
var previousPage = this.NavigationService.BackStack.FirstOrDefault();

if (previousPage != null && previousPage.Source.ToString().StartsWith("/MainPage.xaml"))
{
    this.NavigationService.RemoveBackEntry();
}

Friday, June 6, 2014

Watermark effect on a TextBox in Windows Phone

You need to use PhoneTextBox from windows phone toolkit for this.
  1. You can download it from here.
  2. You can also directly add it to your project by typing the following into your package manager console :
    PM> Install-Package WPtoolkit
Now, add a reference of toolkit inside "phone:PhoneApplicationPage" tag in the xaml page as follows: xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
Finally, use PhoneTextBox control....
<toolkit:PhoneTextBox Hint="Username"/>

Hope it helps :)