Updating Display Elements in Windows Phone
/This is another in my series of “put this in the blog so that you don’t forget it” posts.
Everyone (or nearly everyone) knows that you can update elements on a Windows Phone display by setting properties on them:
statusTextBlock.Text = "Hello Rob";
This would display “Hello Rob” on the phone screen. The snag is that only code that is running in the context of the page can do this. In other words, I can change the display when page events occur, for example buttons being pressed, but I can’t change the content of the TextBlock in response to a network message arriving because the network message code is not running in the same context of the display page. If I try to do this the program fails at runtime with an exception.
The way to fix this is to use a “dispatcher”. The dispatcher is part of the display management system and it will run things in the context of the display system for you. So, you have to give the dispatcher the thing you want to have done, and it will do it on your behalf. This is a bit like you sending one of your kids to go and buy you some Disney Infinity figures because you are to embarrassed to go yourself. Rather than do the task, you hand it off to another process to have it performed for you.
The best way to do this is to use a “lambda expression”. I hate this name. It makes the expression sound all clever and mathematical, when actually it is really just a useful trick that lets you treat executable code as a lump of data that you can give to something else. What you do is use a the “lamda expression” to wrap you your update behaviour and then pass the result of this expression into the method. In fact it all works with delegates, but to make simple use of the feature you don’t need to know this.
statusTextBlock.Dispatcher.BeginInvoke(() =>
{
statusTextBlock.Text = "Hello Rob";
});
The Dispatcher object is the member of the XAML component that will run the method for us. All XAML display elements have a Dispatcher and it exposes a method called BeginInvoke that will run our code. The parameter to BeginInvoke is the code we want to have run, and this is where the Lamda magic starts.
statusTextBlock.Dispatcher.BeginInvoke(() =>
{
statusTextBlock.Text = "Hello Rob";
});
I've highlighted the actual lamdba expression in the code sample above. It is everything between the ( and ) that goes into the BeginInvoke method. If we pull it out of there we can get a closer look.
() =>
{
statusTextBlock.Text = "Hello Rob";
}
The item at the top, the () part, means that the code in this lambda expression does not act on any data. If you want to pass parameters into the code inside the lambda expression you can do this, but we don’t need to.
The => sequence is the lambda itself, and it is followed by the block of statements that are obeyed. If we were buying Disney Infinity figures this would be where I put the behaviour to ask for a “Mrs Incredible”. What actually happens is that the lump of code is stashed somewhere and a delegate (which in C# is how we manage pointers to code) is created to pass into the method.
So, when my program runs the BeginInvoke method in the Dispatcher is given a lump of code to run. It adds this lump of code to a list of “things to do” next time it has to update the display. This means that the display doesn’t actually update precisely when you ask it to, but the process happens so quickly that this is not a problem.