WP7 The Mask Way– Rating Control and More
In the last couple of months since Microsoft has release the WP7 I’ve started to build games and apps in XNA and Silverlight.
Regarding building games, it’s different then building applications, especially in UI… and most of the developers don’t like dealing with UI, but UI doesn’t have to be so scary and I’ll start this post with a nice and simple technic I learned when I worked with Photoshop called “Masking”.
The first example I’ll take from the first game I built called = “Raise My Dog” - Raise My Dog is an interactive game for WP7 that allows you to raise a dog inside you mobile device, something like – Tamagotchi game.
Heart - I need to build Heart Control to show the user his health, but how do I fill the heart without exceeded the borders???
And as I mention in the article title – Using Mask – to help mask out the heart fill without harming the border, This technique will save you a lot of time.
The initial goal is to separate the Heart Border from the Heart Background, In my demo I used Paths and not Images but the concept remain the same.

Step 1: Placing the Heart Fill
(The heart fill need to be above everything)
<Path x:Name="path" Canvas.Left="246.758" Canvas.Top="199.33" Stretch="Fill" Data="F1 M 246.759,219.964C 246.977,241.504 267.975,259.233 284.206,265.059L 284.206,
265.059C 300.302,259.376 320.885,241.829 320.593,220.288L 320.593,220.288C 320.441,208.875 311.149,199.525 299.872,199.475L 299.872, 199.475C 293.324,
199.446 287.546,202.799 283.884,207.667L 283.884,207.667C 283.766,207.823 283.651,207.982 283.536,208.142L 283.536,208.142C 279.778,202.988 273.756,199.359 266.995,
199.33L 266.995,199.33C 263.721,199.316 260.634,200.087 257.902,201.468L 257.902,201.468C 251.226,204.844 246.679, 211.865 246.759,219.964 Z"
Margin="15,20,0,0" RenderTransformOrigin="0.5,0.5" Height="62.369" UseLayoutRounding="False" VerticalAlignment="Top" HorizontalAlignment="Left" Width="65.75">
<Path.RenderTransform>
<CompositeTransform/>
</Path.RenderTransform>
<Path.Fill>
<RadialGradientBrush RadiusX="0.470614" RadiusY="0.535016" Center="0.50193,0.500556" GradientOrigin="0.50193,0.500556">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFED272A" Offset="0"/>
<GradientStop Color="#FF611317" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<SkewTransform CenterX="0.50193" CenterY="0.500556" AngleX="0.881065" AngleY="0"/>
<RotateTransform CenterX="0.50193" CenterY="0.500556" Angle="0.279347"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Path.Fill>
</Path>
Step 2: Placing the Mask Between the Fill and Border
<Rectangle x:Name="Mask" Fill="{StaticResource PhoneBackgroundBrush}" VerticalAlignment="Top" Margin="4,17,154,0"
Height="{Binding HeartValue,Converter={StaticResource HeartValueConverter}}"/>
And I‘ve added a converter to adjust the Health to the Mask Size,
Example: If the user Health is 50% than I need to change the Mask Height to the center of the Heart Border (half…), but the size have to be relative to the Border Or Heart Fill Size so the Mask size will be 34.126
//The max height of the heart border.
//100 represent the max scale
private const double Max = 68.253;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var health = (int)value;
return ((((health) * Max) / 100) - Max) * -1;
}
Health = 0 then Mask Height= 68.253
Health = 50 then Mask Height= 34.12
Health = 90 then Mask Height= 6.8
Step 3: Placing the Border
<Path x:Name="border" Canvas.Left="243.55" Canvas.Top="195.863" Stretch="Fill" Data="F1 M 243.553,218.219C 243.888,241.644 266.682,261.781 284.255, 268.184L 284.255,
268.184C 301.628,262.071 323.779,242.306 323.365,218.88L 323.365,218.88C 323.143,206.466 313.059,196.258 300.868,196.157L 300.868, 196.157C 293.56,196.097 287.157,
199.683 283.246,205.238L 283.246,205.238C 279.159,199.616 272.639,195.925 265.329,195.864L 265.329,195.864C 261.79, 195.835 258.456,196.66 255.51,198.151L 255.51,
198.151C 248.309,201.793 243.427,209.41 243.553,218.219 Z M 284.205,265.049C 268.588,259.359 248.32,240.575 248.022, 219.761L 248.022,219.761C 247.868,
208.729 256.54,199.805 267.373,199.894L 267.373,199.894C 273.871,199.948 279.662,203.228 283.295,208.224L 283.295, 208.224C 286.767,203.286 292.456,
200.102 298.951,200.154L 298.951,200.154C 309.784,200.245 318.746,209.315 318.942,220.346L 318.942, 220.346C 319.271,238.91 303.666,255.593 289.337,
262.84L 289.337,262.84C 287.598,263.72 285.875,264.461 284.205,265.049 Z " Margin="12,17,0,0" RenderTransformOrigin="0.5,0.5" Width="70.75"
Height="68.253" UseLayoutRounding="False" HorizontalAlignment="Left" VerticalAlignment="Top">
<Path.RenderTransform>
<CompositeTransform/>
</Path.RenderTransform>
<Path.Fill>
<LinearGradientBrush StartPoint="0.00275276,0.496476" EndPoint="1.0027,0.496476">
<LinearGradientBrush.RelativeTransform>
<TransformGroup>
<SkewTransform CenterX="0.00275276" CenterY="0.496476" AngleX="1.353" AngleY="0"/>
<RotateTransform CenterX="0.00275276" CenterY="0.496476" Angle="0.520549"/>
</TransformGroup>
</LinearGradientBrush.RelativeTransform>
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFFAF6AF" Offset="0"/>
<GradientStop Color="#FFF1E091" Offset="0.13058"/>
<GradientStop Color="#FFE9CA74" Offset="0.159348"/>
<GradientStop Color="#FF9C6636" Offset="0.510986"/>
<GradientStop Color="#FFC29855" Offset="0.595192"/>
<GradientStop Color="#FFE9CA74" Offset="0.75824"/>
<GradientStop Color="#FFFAF6AF" Offset="0.972534"/>
<GradientStop Color="#FFFAF6AF" Offset="1"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Path.Fill>
</Path>
And you’re done! – Download The Demo Project For WP7

Rating
Rating Control is more common for application and lots of application use it, The same concept as Heart Masking but here in the Rating Control I used the Same Path for Border and Fill and the difference between them is the Fill property set to “Yellow” in all Stars objects and instead of changing the Height of the Mask I’m changing the Width.
Step 1: Define the Star Path as StaticResource
In the App.Xaml I created a Static Resource called StarPath
<Application.Resources>
<sys:String x:Key="StarPath">F1 M 0,217.042L 227.5,217.042L 297.875,0L 367.542,217L 595.542,217L 410.208,353.667L 480.708,
569.667L 297.208,436.667L 116.208,568.167L 185.708,352.667L 0,217.042 Z</sys:String>
</Application.Resources>
Step 2: Create 5 Stars using Path
<Path Name="star" Stretch="Uniform" Data="{StaticResource StarPath}" Fill="Yellow" Width="73" Height="73" HorizontalAlignment="Left" Margin="3,0.667,0,0"
VerticalAlignment="Top" d:LayoutOverrides="Width, Height" /><Path x:Name="star2" Stretch="Uniform" Data="{StaticResource StarPath}" Fill="Yellow" Width="73" Height="73" Margin="81.922,0.333,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="star3" Stretch="Uniform" Data="{StaticResource StarPath}" Fill="Yellow" Width="73" Height="73" Margin="161.569,0.333,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="star4" Stretch="Uniform" Data="{StaticResource StarPath}" Fill="Yellow" Width="73" Height="73" Margin="240.895,0.333,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="star5" Stretch="Uniform" Data="{StaticResource StarPath}" Fill="Yellow" Width="73" Height="73" Margin="320.89,0.333,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
Step 3: Placing the Mask Between the Fill and Border
<Rectangle x:Name="Mask" Fill="{StaticResource PhoneBackgroundBrush}" VerticalAlignment="Top"
Height="74" HorizontalAlignment="Left" Width="{Binding Value,
Converter={StaticResource RaitingValueToWidthConverter}}" RenderTransformOrigin="0.5,0.5">
</Rectangle>
//The max Width of all stars.
//5 represent the max scale
private const double Max = 395;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var rate = (double)value;
return ((((rate) * Max) / 5) - Max) * -1;
}
Step 4: Create 5 Stars using Path but without the Fill Property
<Path Name="border" Stretch="Uniform" Data="{StaticResource StarPath}" StrokeThickness="2" Stroke="White" Width="75" Height="75" HorizontalAlignment="Left"
Margin="2,-0.333,0,0" VerticalAlignment="Top" d:LayoutOverrides="Width, Height"/>
<Path x:Name="border2" Stretch="Uniform" Data="{StaticResource StarPath}" StrokeThickness="2" Stroke="White" Width="75" Height="75" Margin="81,-0.333,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Path x:Name="border3" Stretch="Uniform" Data="{StaticResource StarPath}" StrokeThickness="2" Stroke="White" Width="75" Height="75" Margin="160.659,-0.334,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="border4" Stretch="Uniform" Data="{StaticResource StarPath}" StrokeThickness="2" Stroke="White" Width="75" Height="75" Margin="240.318,-0.334,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="border5" Stretch="Uniform" Data="{StaticResource StarPath}" StrokeThickness="2" Stroke="White" Width="75" Height="75" Margin="319.98,-0.334,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top" />
And you’re done! – Download The Demo Project For WP7

Drunk?!?! Kruskal's or Prim’s
After a lovely dinner with my girlfriend I found myself unable to drive home after drinking more than 1.5 litter of wine.
Before I was able to drive home I started to drink water and I’ve started to think how to get home without the police catching me…?#?#?#?#?#?#
The first thing that popups was – Prim's algorithm is a greedy algorithm that finds a minimum spanning tree for a connected weighted undirected graph. This means it finds a subset of the edges that forms a tree that includes every vertex, where the total weight of all the edges in the tree is minimized – English Please – What is the shortest way to get home?????
So using my WP7 maps I started to calculate each road possible to get home from the restaurant, than I remembered that Kruskal’s is much better when the weighted of each branch is unknown…….
Kruskal's algorithm is an algorithm in graph theory that finds a minimum spanning tree for a connected weighted graph. This means it finds a subset of the edges that forms a tree that includes every vertex, where the total weight of all the edges in the tree is minimized.
But than I received the decisive conclusion – My girlfriend said –> Sit down and be quiet, I’ll drive.
Some times it’s better to listen to someone else especially when you drunk…….
WP7 – How To Extend ListBox When Reaching Last Item
I’m building a WP7 application that contains a ListBox with search results,right now when the user reached the end of the ListBox he need to press the “Next Button” to bring more results from the server, however this is a bad solution and I wanted to extend the list automatically when the user reaches the last item on the list.
There are many way to to implement this, and here is the simplest way how to listen ListBox Vertical Offset Event and update your ListBox automatically when the user reaches the last item on the list.
Download Demo Project
So How?
Step 1: First you need to create a ListBox in your application, than register the Loaded Event of this Listbox.
public MainPage()
{
InitializeComponent();
ListBoxDemo.Loaded += new RoutedEventHandler(ListBoxDemo_Loaded);
}
Step 2: Than create a DependencyProperty called – ListVerticalOffsetProperty, so we can use it later to perform action upon reaching the Last Item in the Listbox.
public readonly DependencyProperty ListVerticalOffsetProperty = DependencyProperty.Register("ListVerticalOffset",
typeof(double), typeof(MainPage), new PropertyMetadata(new PropertyChangedCallback(OnListVerticalOffsetChanged)));
public double ListVerticalOffset
{
get { return (double)this.GetValue(ListVerticalOffsetProperty); }
set { this.SetValue(ListVerticalOffsetProperty, value); }
}
Step 3: Use the following method to find the ScrollViewer object
/// <summary>
/// Finding the ScrollViewer
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="root"></param>
/// <returns></returns>
static T FindChildOfType<T>(DependencyObject root) where T : class
{
var queue = new Queue<DependencyObject>();
queue.Enqueue(root);
while (queue.Count > 0)
{
DependencyObject current = queue.Dequeue();
for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)
{
var child = VisualTreeHelper.GetChild(current, i);
var typedChild = child as T;
if (typedChild != null)
{
return typedChild;
}
queue.Enqueue(child);
}
}
return null;
}
Step 4: Now we connect all the dots together, getting the FrameworkElement (the ListBox), searching for the ScrollViewer object and register to the VerticalOffset changed event.
void ListBoxDemo_Loaded(object sender, RoutedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.Loaded -= ListBoxDemo_Loaded;
scrollViewer = FindChildOfType<ScrollViewer>(element);
if (scrollViewer == null)
{
throw new InvalidOperationException("ScrollViewer not found.");
}
Binding binding = new Binding();
binding.Source = scrollViewer;
binding.Path = new PropertyPath("VerticalOffset");
binding.Mode = BindingMode.OneWay;
this.SetBinding(ListVerticalOffsetProperty, binding);
}
Step 5: Implement the OnListVerticalOffsetChanged to check if the ListBox has reached the last item and if so, create new items.
private static void OnListVerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
MainPage page = obj as MainPage;
ScrollViewer viewer = page.scrollViewer;
//Checks if the Scroll has reached the last item based on the ScrollableHeight
bool atBottom = viewer.VerticalOffset >= viewer.ScrollableHeight;
if (atBottom)
{
//ViewModel will be better........
int Count = page.ListBoxDemo.Items.Count;
int end = Count + 10;
for (int i = Count; i < end; i++)
{
page.ListBoxDemo.Items.Add("Dummy Item " + i);
}
}
}
Download Demo Project
VS ALM Microsoft MVP For Another Year!
This is my third time as VS ALM MVP and still excited like it’s the first time I got this email:
“Congratulations! We are pleased to present you with the 2010 Microsoft® MVP Award!”
I would like start saying Thanks to My Mentor and my good friend Guy Burstein (The King!!!) who guide me and help me getting where I’m today.
Guy is working in the Developer & Platform Adoption Group at Microsoft Israel, helping customers and technical guys like me in Israel in building their next generation applications and push forward for excellence.
I also would like to say many thanks to my company Sela and my boss David Bassa (Also my King) who pushed me forward in the technical community, promote many tools we built for the ALM community and helping me keep the MVP Award for another Year!
