Contact Windows Support

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Saturday, 29 June 2013

Windows Phone 8 - Map and Clusters

Posted on 06:00 by Unknown
This code example demonstrates how to dynamically group pushpins in the map control.
There is a lot of code for Windows Phone 7, then I merged all what I need to create a project for WP8.


First of all you need some namespace declaration: for map control and for pushpins from WP Toolkit.

xmlns:map="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"
xmlns:maptk="clr-namespace:Microsoft.Phone.Maps.Toolkit;assembly=Microsoft.Phone.Controls.Toolkit"

You need also two templates: one for a standard pushpin and the other for the cluster.
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="PushpinTemplate">
<maptk:Pushpin GeoCoordinate="{Binding GeoCoordinate}" Content="{Binding}" />
</DataTemplate>
<DataTemplate x:Key="ClusterTemplate">
<maptk:Pushpin GeoCoordinate="{Binding GeoCoordinate}" Content="{Binding Count}"/>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>

ClustersGenerator is the core of the project. It's a static class that accepts in input
  • Map control
  • Pushpins collection
  • Cluster DataTemplate.
public ClustersGenerator(Map map, List<Pushpin> pushpins, DataTemplate clusterTemplate)
{
_map = map;
_pushpins = pushpins;
this.ClusterTemplate = clusterTemplate;

// maps event
_map.ViewChanged += (s, e) => GeneratePushpins();
_map.ZoomLevelChanged += (s, e) => GeneratePushpins();
_map.CenterChanged += (s, e) => GeneratePushpins();

// first generate
GeneratePushpins();
}

Every map event launches the pushpins elaboration, but first to explain GeneratePushpins method, let's introduce another class: PushpinGroup.
PushpinGroup represents a standard pushpin or a cluster, and exposes a GetElement method to return them. If the group is a cluster, it needs to get only the first pushpin GeoCoordinate and the content is a group of all pushpins.
public class PushpinsGroup
{
private List<Pushpin> _pushpins = new List<Pushpin>();
public Point MapLocation { get; set; }

public PushpinsGroup(Pushpin pushpin, Point location)
{
_pushpins.Add(pushpin);
MapLocation = location;
}

public FrameworkElement GetElement(DataTemplate clusterTemplate)
{
if (_pushpins.Count == 1)
return _pushpins[0];

// more pushpins
return new Pushpin()
{
// just need the first coordinate
GeoCoordinate = _pushpins.First().GeoCoordinate,
Content = _pushpins.Select(p => p.DataContext).ToList(),
ContentTemplate = clusterTemplate,
};
}

public void IncludeGroup(PushpinsGroup group)
{
foreach (var pin in group._pushpins)
_pushpins.Add(pin);
}
}

The GeneratePushipins function creates clusters based on map ViewPort and a constant named MAXDISTANCE. An extension method convert pushpin GeoCoordinate to a ViewPort Point. That is used to get the distance from other points. If this distance is less then the MAXDISTANCE, the pushpin become a part of cluster.
private void GeneratePushpins()
{
List<PushpinsGroup> pushpinsToAdd = new List<PushpinsGroup>();
foreach (var pushpin in _pushpins)
{
bool addGroup = true;
var newGroup = new PushpinsGroup(pushpin, _map.ConvertGeoCoordinateToViewportPoint(pushpin.GeoCoordinate));

foreach (var pushpinToAdd in pushpinsToAdd)
{
double distance = pushpinToAdd.MapLocation.GetDistanceTo(newGroup.MapLocation);

if (distance < MAXDISTANCE)
{
pushpinToAdd.IncludeGroup(newGroup);
addGroup = false;
break;
}
}

if (addGroup)
pushpinsToAdd.Add(newGroup);
}

_map.Dispatcher.BeginInvoke(() =>
{
_map.Layers.Clear();
MapLayer layer = new MapLayer();
foreach (var visibleGroup in pushpinsToAdd.Where(p => _map.IsVisiblePoint(p.MapLocation)))
{
var cluster = visibleGroup.GetElement(this.ClusterTemplate) as Pushpin;
if (cluster != null)
{
layer.Add(new MapOverlay() { GeoCoordinate = cluster.GeoCoordinate, Content = cluster.Content, ContentTemplate = cluster.ContentTemplate});
}
}
if (layer.Count > 0)
_map.Layers.Add(layer);
});
}

The extension method GetDistanceTo is the algorithm to calculate the distance between two points:
public static double GetDistanceTo(this Point p1, Point p2)
{
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}

Instead IsPointVisible returns true if the point is visible in the map, otherwise false:
public static bool IsVisiblePoint(this Map map, Point point)
{
return point.X > 0 && point.X < map.ActualWidth && point.Y > 0 && point.Y < map.ActualHeight;
}

Now in your MainPage.xaml, you only need to pass all pushpins to the ClusterGenerator and it will do all work for you.

var clusterer = new ClustersGenerator(map, pushpins, this.Resources["ClusterTemplate"] as DataTemplate);

You can download all code here.

With this article I won TechNet Guru Contribution June 2013 - Windows Phone.
Read More
Posted in Clusters, Maps, windows phone | No comments

Friday, 28 June 2013

Windows Phone - Caliburn Micro and App.xaml error

Posted on 11:15 by Unknown
When I add Caliburn Micro to a new project, I have always some error in App.xaml.
With Caliburn 1.5.1 I found a new problem: "Object Reference not set to an instance of an object".

This error don't prevent the project build, but it seems related to the xaml.
That's why the RootFrame into designer is null.

The fix is easy! Just open your Bootstrapper and change
container.RegisterPhoneServices(RootFrame);
with..
if (!Execute.InDesignMode)
container.RegisterPhoneServices(RootFrame);

Read More
Posted in Caliburn, MVVM, windows phone | No comments

Windows Phone - Caliburn Micro and Telerik

Posted on 10:40 by Unknown
When you use Caliburn Micro you always have a file Bootstrapper like this:

public class Bootstrapper : PhoneBootstrapper
{
PhoneContainer container;

protected override void Configure()
{
container = new PhoneContainer();

container.RegisterPhoneServices(RootFrame);

container.PerRequest<MainPageViewModel>();

AddCustomConventions();
}

static void AddCustomConventions()
{
}

protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}

protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}

protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}

I love to use Windows Phone controls from Telerik and I always add RadPhoneApplicationFrame in my applications, but how to add it in the Bootstrapper?

You need only some lines of code.


private PhoneApplicationFrame rootFrame;
private new PhoneApplicationFrame RootFrame
{
get
{
if (this.rootFrame == null)
this.rootFrame = new RadPhoneApplicationFrame();

return this.rootFrame;
}
set
{
this.rootFrame = value;
}
}

protected override PhoneApplicationFrame CreatePhoneApplicationFrame()
{
return this.RootFrame;
}


I created a public property to instantiate the RadPhoneApplicationFrame and overrided the CreatePhoneApplicationFrame to return the custom frame.

Here the new Bootstrapper:

public class Bootstrapper : PhoneBootstrapper
{
PhoneContainer container;

private PhoneApplicationFrame rootFrame;

private new PhoneApplicationFrame RootFrame
{
get
{
if (this.rootFrame == null)
this.rootFrame = new RadPhoneApplicationFrame();

return this.rootFrame;
}
set
{
this.rootFrame = value;
}
}

protected override void Configure()
{
container = new PhoneContainer();

container.RegisterPhoneServices(RootFrame);

container.PerRequest<MainPageViewModel>();

AddCustomConventions();
}

protected override PhoneApplicationFrame CreatePhoneApplicationFrame()
{
return this.RootFrame;
}

static void AddCustomConventions()
{
}

protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}

protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}

protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}
Read More
Posted in Caliburn, MVVM, windows phone | No comments

Sunday, 16 June 2013

Coding4Fun - ThemedImageConverter

Posted on 05:31 by Unknown
When you publish an application, you need to meet the requirement 5.5.2 from Dev Center:
"App content, such as text and visual elements, must be visible and legible regardless of the phone theme without panning horizontally or zooming.."

The example is when you have an image with the same color of background theme.
What you can do?
- select a different color for image.
- manage the image source swap from code behind.
- the best practice is to use the ThemedImageConverter from Coding4Fun Toolkit.

Let's go:
Download the Coding4Fun Toolkit from NuGet or Codeplex.

Add the static resource in your page:
<c4fun:themedimageconverter x:key="ThemedImageConverter"></c4fun:themedimageconverter>

Use this simple converter in your image:
<Image Source="{Binding Converter={StaticResource ThemedImageConverter}, ConverterParameter={StaticResource PhoneBackgroundColor}}" DataContext="/Assets/{0}/img.png" />

You can check also the InverseThemedImageConverter to swap from light and dark themes.


Read More
Posted in Coding4fun, developers, windows phone, Windows Phone 7.8, Windows phone 8 | No comments
Newer Posts Older Posts Home
Subscribe to: Comments (Atom)

Popular Posts

  • Happy New Year!
    Posted by Lawrence Chang, Product Marketing Manager, Google mobile team When I first asked the mobile team to send me pictures of how they r...
  • XMAS TIME - Get a Lumia 925 for free
    Do you want a Lumia 925 for Christmas? Thanks to DVLUP you can get it easy :) Check the new xmas challenge ! You just need to create 3 new ...
  • Our 5 favourite new Windows Phone apps of the week
    Today myMoneyBook is featured in Nokia's blog:  Our 5 favourite new Windows Phone apps of the week . Thank you so much  Nokia !
  • Mobile Web Calendar for iPhone and Android, now with event management
    It's probably no news to all you parents out there, but as a new dad I only recently found out just how busy life gets with kids. So I w...
  • Windows Phone 8 - Map and Clusters
    This code example demonstrates how to dynamically group pushpins in the map control. There is a lot of code for Windows Phone 7, then I merg...
  • Places Directory app for Android
    As an engineer based in Taipei, I frequently travel to Google headquarters in Mountain View. When I'm there, I'm always looking for...
  • The Iterative Web App - Faster Address Auto-complete and Keyboard Shortcuts
    On April 7th, we announced a new version of Gmail for mobile for iPhone and Android-powered devices. Among the improvements was a complete...
  • Our newest Mobile Search feature: Where am I?
    Many of our improvements to search quality come from analyzing actual search queries. We’re constantly trying to surface more relevant sea...
  • [ITA] Dal 920 al Lumia 1020
    Che dire... Il Lumia 1020 subentra di prepotenza con il suo colore giallo. La prima impressione è sicuramente molto positiva, non solo per l...
  • Impressions of CES
    Posted by Lawrence Chang, Product Marketing Manager, Google mobile team As the 2008 Consumer Electronics Show winds to a close, some of you...

Categories

  • 100th post
  • 3D
  • 6210 navigator
  • 6220 classic
  • adsense
  • adsense for mobile
  • alexandra's mobile [ad]itude
  • Amber
  • android
  • android market
  • android widget
  • app
  • appdeals
  • apphub
  • apple
  • apps
  • att
  • autocomplete
  • best buy mobile
  • better know your mobile
  • biking directions
  • BlackBerry
  • BlackBerry Storm
  • blackjack
  • blogger
  • brightpoint
  • bug
  • buxfer
  • Buzz
  • buzz for mobile
  • c#
  • cab4me
  • Calendar
  • Caliburn
  • canada
  • CES
  • check-in
  • chi-2008
  • clearwire
  • cloud print
  • Clusters
  • Coding4fun
  • Contacts
  • convenience key
  • countdown to 2009
  • coupons
  • csharp
  • culture
  • dennis woodside
  • developers
  • Docs
  • Doodle
  • doodles
  • dotorg
  • doubleclick mobile
  • droid
  • DVLUP
  • e-series
  • ebook
  • election
  • enterprise
  • feature phones
  • france
  • free
  • g1
  • geo
  • geolocation api
  • germany
  • Gesture search
  • gmail
  • gmail for android
  • gmail for mobile
  • GOOG-411
  • googe search
  • Google
  • Google Africa
  • google analytics
  • Google Apps
  • Google Apps Blog
  • google apps device policy
  • google apps for mobile
  • google book search
  • google buzz
  • google buzz for mobile
  • Google Custom Search
  • google docs
  • google earth
  • google finance
  • google gears for mobile
  • google goggles
  • Google I/O
  • google instant
  • google latitude
  • google local search
  • Google Location Alerts
  • google location history
  • Google Locaton History
  • google maps
  • google maps for mobile
  • google maps navigation
  • google mobile
  • google mobile ads
  • google mobile help
  • google mobile help forum
  • Google Mobile Search
  • google mobile tips
  • google mobile tricks
  • google moderator
  • Google News
  • google offers
  • google product search
  • Google profile
  • Google public location badge
  • google search
  • google search app
  • google search by voice
  • google search for mobile
  • google shopper
  • google sites
  • google sky map
  • Google SMS
  • google suggest
  • google sync
  • google talk
  • google toolbar
  • google translate
  • google translate for animals
  • google voice
  • google wallet
  • google+
  • googlenew
  • gps
  • hangouts
  • history
  • honeycomb
  • hot
  • hotpot
  • html 5
  • i-mode
  • igoogle
  • image ads
  • image search
  • inside search
  • Interative web app
  • iOS
  • ipad
  • iphone
  • ipod touch
  • italy
  • iterative web app
  • Iterative Webapp
  • J2ME
  • jason spero
  • lambda
  • latitude api
  • layers
  • Listen
  • Local Business Center
  • local inventory
  • local search
  • locale
  • location based search
  • location tag
  • Lumia 1020
  • Lumia 925
  • mac
  • macworld
  • Mail
  • Maps
  • marketplace
  • mary meeker
  • meow me now
  • microsoft
  • mobile
  • mobile [ad]itude
  • mobile advertising
  • mobile calendar
  • mobile tricks
  • mobile world congress
  • mobile.google.com
  • moneybook
  • motorola
  • movies
  • music
  • MVVM
  • my location
  • my tracks
  • myBattery
  • mymoneybook
  • n-series
  • n78
  • n95
  • n96
  • navigation
  • new york city
  • nexus
  • nfc
  • nokia
  • Nokia Pro Camera
  • NowPlaying
  • ntt docomo
  • NuGet; Visual Studio
  • nyc
  • open handset alliance
  • opera
  • opera mini
  • opera mobile
  • orkut
  • outbox
  • palm
  • palm webos
  • Panoramio
  • personalized suggest
  • Picasa web albums
  • Place Pages for mobile
  • Places
  • Places Directory
  • pre
  • product ideas
  • product search
  • produt search for mobile
  • quick search box
  • Reader
  • registration
  • research
  • s60
  • samsung
  • santa
  • search
  • search by voice
  • Search Options
  • sharing
  • shortcut
  • sidekey
  • silverlight
  • sky lab
  • smart navigation
  • social
  • Sony
  • sony ericsson
  • spain
  • Spreadsheeets
  • sprint
  • sql ce
  • sqlite
  • starring
  • stars
  • street view
  • Summer Games
  • symbian
  • Sync
  • Syncfusion
  • t-mobile
  • tablet
  • tasks
  • TechNet
  • TechNet wiki
  • telerik
  • Thomson
  • TileView
  • tips
  • transit
  • uiq
  • uk
  • universal search
  • verizon
  • visual search
  • voice actions
  • voice search
  • vote
  • walking directions
  • walking navigation
  • web app
  • wep app
  • wikininjas
  • windows 8
  • windows mobile
  • windows phone
  • Windows Phone 7.8
  • Windows phone 8
  • windows RT
  • Windows Store
  • wireless week
  • xaml
  • xna
  • youtube
  • youtube channel
  • YouTube for mobile
  • zoho

Blog Archive

  • ▼  2013 (21)
    • ►  November (3)
    • ►  October (1)
    • ►  September (3)
    • ►  August (3)
    • ►  July (2)
    • ▼  June (4)
      • Windows Phone 8 - Map and Clusters
      • Windows Phone - Caliburn Micro and App.xaml error
      • Windows Phone - Caliburn Micro and Telerik
      • Coding4Fun - ThemedImageConverter
    • ►  April (1)
    • ►  March (1)
    • ►  February (2)
    • ►  January (1)
  • ►  2012 (32)
    • ►  December (2)
    • ►  November (3)
    • ►  October (3)
    • ►  September (6)
    • ►  August (1)
    • ►  June (1)
    • ►  May (2)
    • ►  April (3)
    • ►  March (5)
    • ►  February (5)
    • ►  January (1)
  • ►  2011 (98)
    • ►  December (8)
    • ►  November (9)
    • ►  October (6)
    • ►  September (7)
    • ►  August (2)
    • ►  July (12)
    • ►  June (7)
    • ►  May (11)
    • ►  April (8)
    • ►  March (12)
    • ►  February (9)
    • ►  January (7)
  • ►  2010 (122)
    • ►  December (18)
    • ►  November (10)
    • ►  October (8)
    • ►  September (10)
    • ►  August (10)
    • ►  July (4)
    • ►  June (11)
    • ►  May (7)
    • ►  April (14)
    • ►  March (13)
    • ►  February (10)
    • ►  January (7)
  • ►  2009 (109)
    • ►  December (7)
    • ►  November (14)
    • ►  October (14)
    • ►  September (6)
    • ►  August (7)
    • ►  July (9)
    • ►  June (13)
    • ►  May (10)
    • ►  April (7)
    • ►  March (7)
    • ►  February (11)
    • ►  January (4)
  • ►  2008 (92)
    • ►  December (11)
    • ►  November (7)
    • ►  October (9)
    • ►  September (6)
    • ►  August (6)
    • ►  July (11)
    • ►  June (12)
    • ►  May (4)
    • ►  April (8)
    • ►  March (5)
    • ►  February (5)
    • ►  January (8)
  • ►  2007 (9)
    • ►  December (6)
    • ►  November (3)
Powered by Blogger.

About Me

Unknown
View my complete profile