About 1.5 years ago I received my Nokia Lumia 925 phone as a replacement for my Nokia Lumia 620, which I had lost. I couldn’t be more happy at that moment. It has a great screen, it’s quite fast and nice to look at.

The only downside was, it sometimes rebooted while I was doing something. This happened almost all the time when I was taking a picture, but also when listening to podcasts, driving my car, reading e-mail, etc. It’s rather annoying when you are using a phone and it reboots almost all the time, especially if you don’t know why!

After having read a lot of forums, discussed with some colleagues and tried a lot of stuff myself, I discovered the Wi-Fi Sense (Dutch: Wi-Fi-inzicht). Disabling these options solved the issue of the spontaneous reboots. As I didn’t use these options anyway, I’m not missing out on anything either.

wp_ss_20141002_0001

So, if you are experiencing (a lot of) random reboots on your Windows Phone 8 phone, try turning of the Wi-Fi Sense options. It might help.

Tijdens het ontwikkelen van een van m’n WP7 applicaties liep ik er tegenaan dat er naar een andere pagina moest worden genavigeerd. Je kunt, naar mijn mening, namelijk niet alles binnen een Pivot- of Panorama-control plaatsen. Het kan ook zijn dat dit nog een ouderwetse gedachtengang is, maar daar ben ik nog niet achter.

Het probleem was echter dat navigatie niet echt (goed) is geïmplementeerd binnen WP7 of Silverlight. Omdat dit toch moest binnen mijn applicatie heb ik hier een oplossing voor moeten verzinnen. Gelukkig was ik niet de enige met dit probleem en kwam ik op Stack Overflow (link ben ik kwijt) al snel op een antwoord waar ik mee kon werken.

Het idee is dat je je views laat afleiden van een BaseView. In deze BaseView definieer je dan de navigatie methoden, zodat alle views dit kunnen doen. De navigatie wordt gedaan aan de hand van een navigatie object en het registreren op de wijzigingen binnen dit object. Door gebruik te maken van de Message bus die je gratis bij MVVM Light krijgt is dit eenvoudig te realiseren.

Eerst dient er een object te worden gemaakt waar de pagina en querystring in kan worden gestopt. Dit is bij mij een nieuwe klasse welke er als volgt uit ziet:

public class NavigationMessage : NotificationMessage
{
	public string PageName
	{
		get { return base.Notification; }
	}

	public Dictionary QueryStringParams { get; private set; }

	public NavigationMessage(string pageName) : base(pageName) { }

	public NavigationMessage(string pageName, Dictionary queryStringParams)
		: this(pageName)
	{
		QueryStringParams = queryStringParams;
	}
}

Zodra deze is gemaakt kan er een BaseView worden aangemaakt waarin deze zichzelf registreert op wijzigingen van objecten van de vooraf gedefinieerde klasse. Bij een wijziging kan er dan een methode worden aangeroepen welke de navigatie tot stand brengt. Dit zal er ongeveer als volgt uit komen te zien:

public class BaseView : PhoneApplicationPage
{
	public BaseView()
	{
		Messenger.Default.Register(this, NavigateToPage);
	}

	public void NavigateToPage(NavigationMessage message)
	{
		string queryStringParams = message.QueryStringParams == null ? "" : GetQueryString(message);

		string uri = string.Format("/{0}.xaml{1}", message.PageName, queryStringParams);
		NavigationService.Navigate(new Uri(uri, UriKind.Relative));
	}

	private string GetQueryString(NavigationMessage message)
	{
		string queryString = string.Empty;
		bool first = true;
		foreach (var s in message.QueryStringParams)
		{
			if (first)
			{
				queryString += "?";
				first = false;
			}
			queryString += string.Format("{0}={1}", s.Key, s.Value);
		}
		return queryString;
	}
}

Wat wel belangrijk is om te weten is dat de XAML en de code-behind hiervan beide moeten afleiden van de BaseView. Dit was waar ik de fout in ging, aangezien ik niet wist hoe je in XAML zoiets kunt bewerkstelligen. Gelukkig is dit heel eenvoudig. De code-behind gaat zoals je dat normaal doet:

public partial class MainPage : BaseView


In de XAML is dit iets uitgebreider. Daar moet er namelijk een namespace worden toegevoegd en het root element moet worden gewijzigd in de juiste BaseView klasse.

Wanneer je dit niet doet krijg je de melding dat een partial klasse niet van verschillende base klassen kan overerven. Logisch!

Zodra alles is opgezet en geregistreerd kun je, dankzij de Messenger bus, met een regel een andere pagina aanroepen:

Messenger.Default.Send(new NavigationMessage("Results"));

Op zich is het allemaal heel eenvoudig, maar je moet er wel even aan denken. Wat ik wel een eye-opener vond is dat Silverlight dus blijkbaar ook werkt met Uri’s en querystrings, net zoals een web applicatie. Dit is waarschijnlijk triviale kennis voor een Silverlight developer, waardoor wel weer blijkt dat ik nog een beginner ben op dit vlak.

Enkele weken geleden ben ik begonnen met het ontwikkelen voor applicaties op de Windows Phone 7, zowel prive als op het werk. Vandaag was het dan eindelijk zo ver dat m'n eerste applicatie in de Zune Marketplace is komen te staan.

De applicatie draagt de naam LoveTester en is te vinden op de volgende Zune url: http://social.zune.net/External/LaunchZuneProtocol.aspx?pathuri=navigate%3FphoneAppID%3D50ce8d2e-8af5-df11-9264-00237de2db9e

Binnen Zune ziet het er als volgt uit:

Met de applicatie kan worden berekend hoe goed twee personen (namen) bij elkaar passen. Hier wordt een berekening op losgelaten en een antwoord verstrekt op het scherm. Dit antwoord wordt in zowel een percentage als een korte zin beschreven.

Deze actie kan tot in de oneindigheid worden herhaald, echter wanneer de applicatie nog in trial modus is, zal dit maar eenmaal per dag kunnen worden uitgevoerd. Gelukkig is de applicatie maar 99 cent, dus vallen de kosten ook nog wel mee.

Voor het zien van Windows Phone 7 applicaties binnen Zune dient de locatie van de computer wel te worden gewijzigd in United States.

Hopelijk is dit niet meer nodig wanneer de Marketplace in Nederland beschikbaar is.

Nu maar snel aan de slag met m'n tweede applicatie. Moet nog wel even nadenken wat dat gaat worden.

Zoals in m'n vorige post is te lezen ben ik momenteel bezig met het maken van een nieuwe Windows Phone 7 applicatie met het MVVM pattern. Op zich niet zo heel spannend, aangezien er duizenden anderen zijn die dit ook doen.

Enkele jaren geleden heb ik geleerd om m'n applicatie in meerdere logische lagen of tiers op te delen, presentatie-, business- en data-laag. Ik ben nog steeds een groot voorstanden van dit principe en of je hier nu lagen of tiers gebruikt, beide keren moet er data van 1 klasse naar een andere worden gestuurd.

Dit wil ik nu dus ook toepassen binnen m'n Windows Phone 7 applicatie. Eerst heb ik nu een nieuw MVVM Light project gemaakt met daarin de benodigde onderdelen voor m'n applicatie. Daarna heb ik gelijk een business en een data laag er bij gemaakt. Tegenwoordig heb je ook de keuze om een Windows Phone Class Library te maken:

Hier heb ik dan ook voor gekozen, omdat deze er standaard voor zorgt dat ik niet alle assemblies van .NET 3.5 kan kiezen en dus een dll maak die geschikt is voor een WP7 apparaat. Het resultaat is ongeveer als volgt:

Aangezien ik jarenlang aan webdevelopment heb gedaan in ASP.NET en Sharepoint 2007/2010 ben ik niet meer zo in de loop van asynchroon werken en het gebruik van meerdere threads binnen je code. Met Silverlight ontkom je hier niet aan, dus heb ik m'n kennis aardig moeten bijspijkeren. Vandaag heb ik ongeveer de gehele dag besteedt om communicatie tussen m'n lagen aan de praat te krijgen. Na veel voorbeelden te hebben gelezen, geïmplementeerd en verwijderd te hebben, heb ik nu toch iets werkends kunnen maken. Of het helemaal goed is, dat is een tweede. Waarschijnlijk kijk ik over een jaar hier heel anders tegen aan, maar momenteel ben ik er tevreden mee.

Het voordeel van werken met meerdere threads is dat je UI niet vast loopt tijdens het uitvoeren van een actie. Ook kan alleen de UI-thread de UI bijwerken, wat het geheel iets 'veiliger' maakt. Nu was het de bedoeling dat ik aan de hand van de coordinaten van de telefoon (interne GPS) de plaats ging bepalen. Hier kan natuurlijk Bing of Google voor worden gebruikt. Aangezien je bij Bing een key moet aanvragen, heb ik nu eerst voor Google gekozen.

Wat ik wilde doen is de coordinaten van het apparaat doorsturen naar de business laag, hier wordt deze dan worden vertaald naar 2 double's die in de data laag kan worden gebruikt en dan de Google services er mee kan aanroepen. Heel eenvoudig en in een website zou ik dit ook in enkele minuten hebben gemaakt. In Silverlight moest ik me echter gaan houden aan het asynchrone model. Gelukkig kan er tegenwoordig gebruik worden gemaakt van lambda expressies en Action<T> en Func<T>, welke ik nu echt nodig had.

Ten eerste de data laag. Hier plaats ik 2 double's in de code en moet er voor zorgen dat de respons van het http request wordt teruggestuurd. Dit wilde ik doen met het HttpWebRequest. Binnen Silverlight is er nu alleen nog maar de BeginGetResponse methode beschikbaar. Dit was al de eerste aanpassing die ik moest maken in m'n gedachtengang. Na wat zoeken hoe lambda expressies werken (vergeet ik altijd door gebrek aan gebruik) is hier een redelijk goed werkende oplossing voor gemaakt.

Let wel, hier moet nog wel wat validatie en dergelijke op plaatsvinden, maar voor nu werkt het eerst prima.

public void GetNearestTown(Action<GoogleGeoCodeResponse> callback)
{
    var address = string.Format("http://url{0}{1}"this.Latitude, this.Longitude);
    HttpWebRequest webRequest = GetWebRequest(address);
    webRequest.BeginGetResponse(result =>
    {
        var response = webRequest.EndGetResponse(result);
        string resultstring = null;
        Stream responseStream = response.GetResponseStream();
        StreamReader sr = new StreamReader(responseStream);
        resultstring = sr.ReadToEnd();
        GoogleGeoCodeResponse jObject = JSON.Deserialize<GoogleGeoCodeResponse>(resultstring);
        callback(jObject);
    }, null);
}

Het ophalen en lezen van de respons en objecten doe ik nu dus via een lambda expressie binnen de BeginGetResponse. Hier moest ik zelf wel even aan wennen, maar na verloop van tijd wordt het steeds duidelijker. Uiteindelijk plaats ik alle resultaten, via een helper methode, in een zelfgemaakt type. De resultset geef ik hier mee aan een callback, welke als parameter wordt meegegeven. Dit is de eerste keer dat ik nuttig gebruik heb gemaakt van de Action<T>. Ik wist dat het bestond, maar nog nooit het nut er van in gezien, tot nu dus. De callback functie staat namelijk beschreven in de business laag, waar de callback dus ook wordt verwerkt.

Het business object ziet er namelijk ongeveer als volgt uit:

protected string Town { getprivate set; }
private Action<string> responseCallback;

public string GetCurrentCity(GeoPosition<GeoCoordinate> position, Action<string> respCallback)
{
    this.responseCallback = respCallback;
    var gCode = new Geocode(position.Location.Latitude, position.Location.Longitude);
    gCode.GetNearestTown(resultString =>
    {
        GetTownFromResponse(resultString);
    });
    return this.Town;
}
private void GetTownFromResponse(GoogleGeoCodeResponse town)
{
    if (town.status == "OK")
    {
        this.Town = town.results[0].formatted_address;
        responseCallback(this.Town);
    }
}

In de aanroep van de data access (gCode.GetNearestTown) geef ik nu de methode GetTownFromResponse methode mee, welke voldoet aan het Action<string> patroon. Hierdoor zal de callback in deze functie worden uitgevoerd. Zoals is te zien zal deze functie een property in de klasse vullen met de verkregen waarde uit de data laag.
Het vullen van de property is momenteel niet meer direct noodzakelijk, omdat de GetTownFromResponse ook weer een callback functie aanroept welke is meegegeven in de presentatie laag van de code. Immers, in de GetCurrentCity wordt ook weer een Action<string> meegegeven welke een implementatie van een functie bevat welke in de presentatie laag is gedefinieerd.

Het stuk code in de presentatie laag ziet er ongeveer als volgt uit:

private void LocationHasChanged(GeoPosition<GeoCoordinate> position)
{
    Location lb = new Business.Location();
    lb.GetCurrentCity(position, UpdateCurrentCity);
}
private void UpdateCurrentCity(string newCity)
{
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        CurrentCity = newCity;
    });
}

Zoals is te zien wordt de UpdateCurrentCity meegegeven aan de business methode, waardoor deze dus als callback fungeert.

Het stuk Deployment.Current.Dispatcher.BeginInvoke zorgt er voor dat het updaten van de property CurrentCity in de UI-thread gebeurd, zodat dit ook daadwerkelijk wordt uitgevoerd. Wanneer je dit niet goed doet zal er een exception worden ge-raised met als melding "invalid cross-thread access…."

Al met al heb ik weer heel wat geleerd over Silverlight (en .NET) development. De code moet nog wel worden gerefactored, maar het gaat om het idee.

Deze dagen ben ik weer druk doende met een nieuwe Windows Phone 7 applicatie. De vorige applicatie die ik had gemaakt was nogal haastig in elkaar gezet, zonder ook maar een enkel pattern of framework te gebruiken, echt een Hello World dus.

Nu ben ik met een tweede applicatie bezig voor m'n werk en die moet toch van iets hogere kwaliteit zijn. Een collega van me had al een framework gevonden dat ons kon helpen met het MVVM pattern dat veel wordt gebruikt bij Silverlight en WPF applicaties, namelijk MVVM Light. Het duurde even voordat ik alles op het systeem had staan. Het installeren staat goed beschreven op de site van Galasoft: http://www.galasoft.ch/mvvm/installing/manually/
Let er hier ook op dat de hotfix voor Windows Phone 7 ontwikkeling wordt geïnstalleerd:

Important note for Windows Phone developers: If you work with Windows Phone 7, you must install this hotfix on top of V3 SP1.

Wanneer dit niet is gedaan krijg je foutmeldingen tijdens het maken van een nieuw MVVM Light WP7 project.

Zodra de bestanden goed op het systeem staan kan er worden begonnen met ontwikkelen. Er is een nieuw project template beschikbaar, namelijk MvvmLight (WP7).

Dit project bevat gelijk al een tweetal mappen, Model en ViewModel en een XAML bestand.

De ViewModel map bevat ook gelijk al 2 bestanden. Deze zijn belangrijk!

Het bestand MainViewModel.cs is gelinkt aan de MainPage.xaml en de ViewModelLocator.cs bevat volgens mij de logica om ViewModel bestanden te koppelen aan de View's.

Het ViewModel.cs bestand heeft nog niet zoveel nuttige inhoud, zoals is te zien:

public class MainViewModel : ViewModelBase
{
    public string ApplicationTitle
    {
        get
        {
            return "MVVM LIGHT";
        }
    }
    //Nog enkele properties
    public MainViewModel()
    {
    }
}

Omdat ik nog nooit echt met Silverlight, XAML en MVVM heb gewerkt vroeg ik me natuurlijk af hoe het komt dat de properties aan de View zijn gebind. Het grootste nadeel van het gebruik van een framework, is dat je zelf niet alles meer hoeft te maken en dus ook niet precies weet wat er allemaal gebeurd.

Na wat spelen in de XAML ben ik er achter gekomen dat deze regel belangrijk is voor de koppeling met de ViewModel:

DataContext="{Binding Main, Source={StaticResource Locator}}">
												

De StaticResource wordt volgens mij gebind naar de ViewModelLocatorklasse, vanwege de naam.
Het volgende stuk code zorgt er volgens mij voor dat de MainViewModel wordt gebind:

public MainViewModel Main
{
    get
    {
        return MainStatic;
    }
}

Ik heb dit getest door de snippets te gebruiken om nog een Locator aan te maken, genaamd Test.

Daarna heb ik de DataContext gewijzigd in DataContext="{BindingTest,Source={StaticResourceLocator}}">.Nu zag ik de properties van m'n TestViewModel op de pagina weergegeven.

Het lijkt dus dat ontwikkelen met MVVM Light of XAML betekend dat je je aan enkele naam conventies moet houden. Op zich leuk en aardig, maar dat is behoorlijk foutgevoelig natuurlijk. Tijdens compileren kom je hier namelijk niet gelijk achter.

Het toevoegen van acties aan een knop gaat op een vergelijkbare manier:

<Button Content="Zoeken!">
    <Custom:Interaction.Triggers>
        <Custom:EventTrigger EventName="Click">
    <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding ZoekInDeBuurtCommand, Mode=OneWay}"/>
        </Custom:EventTrigger>
    </Custom:Interaction.Triggers>
</Button>

Sidenote: Hier heb ik de volgende toevoeging voor moeten doen in het <phone:-element, anders kun je geen gebruik maken van de elementen.

xmlns:Custom="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7"

In de code van de ViewModel heb ik dan het volgende RelayCommand gedefinieerd als een property:

public RelayCommand ZoekInDeBuurtCommand
{
    get { return new RelayCommand(DoZoekenResultaten); }
}

private void DoZoekenResultaten()
{
    throw new NotImplementedException();
}

Op zich is het geen rocket-science, maar ik had eigenlijk verwacht dat het allemaal iets stricter zou werken. Blijkbaar is dat nog niet het geval. Het was in ieder geval even zoeken naar hoe alles precies werkte en hoe je nieuwe elementen op een pagina kan krijgen. Inmiddels is het me gelukt om een leuke WP7 Pivot applicatie te maken. Nu de inhoud van de pivot's nog.