This blog attempts to be a collection of how-to examples in the Microsoft software stack - things that may take forever to find out, especially for the beginner. I see it as my way to return something to the Microsoft community in exchange for what I learned from it.

30 September 2010

I was creating a little application that had some input fields and a submit button. I wanted the submit button only to be enabled when the user input was valid. No a very unusual use case. So I set out to create a viewmodel the usual MVVMLight way, extending ViewModelBase and making properties using the snippets Laurent Bugnion provides with the MVVMLight toolkit. To validate them, I decorated them with attributes from System.ComponentModel.DataAnnotations, and validated them with using the Validator. A typical property looks like this:

and I turned out not be so very smart after all, for it did not work. When the user entered a value that was outside the range of 0-2000 or even plain nonsense – like “thisisnonumber”, the UI gave an error message, I even got the message in my ValidationSummary, but for some reason the viewmodel still found itself valid.

This puzzled me for a while, but it turned out to be perfectly logical. If the user inputs nonsense this throws an exception, and so does a call to Validator.ValidateProperty. So the invalid input never makes to the viewmodel property, and the viewmodel, if it was initially valid, stays valid en thus my button stays enabled. How to get around this?

Actually, it’s pretty simple: notify your viewmodel of input errors, so it can keep track of whatever nonsense the user has tried to cram down its throat. The way I chose to do it was like this:

Add a field int _fieldErrors;

Bind the event BindingValidationErrorto a command in the viewmodel, passing it’s parameters along

Add to or subtract 1 from_fieldErrors for every time the command was called depending on the parameter

And thus the viewmodel maintains its own integrity, is notified by the UI of all problems playing around there, and can decide based upon the sum of this information whether or not the user can actually save.

Thanks to Mike Taulty for helping me out on the Validator in real-time on Twitter.

29 September 2010

As I was (and still am) playing with my MVVM-driven Windows Phone 7 map viewer, I started thinking about tomb stoning and/or serializing stuff into the Windows Phone 7 application state and/or isolated storage. I came up with four extension methods than can be used to store/serialize the complete model in both. Maybe not ideal in all cases, but it was a simple solution for me.

Getting started

I created an assembly LocalJoost.Utilities, in which I first defined a generic interface for the model, which I called – with a flash of inspiration – IModel ;-). It’s implementation is not interesting for the extension methods.

Interesting caveat – the Locator is instantiated, not your model. When the application runs for the very first time, there will be no model to retrieve. Thus, in the constructor of App.Xaml.cs you need to add:

Locator.Instance.Model = new YourModel();

in which you replace "YourModel" for your own model type.

Storing in / retrieving from phone application state

Using the extension methods is pretty simple then: open your App.Xaml.cs, find two methods called “Application_Activated” and “Application_Deactivated” and modify them as follows:

// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
Locator.Instance.Model = this.RetrieveFromPhoneState();
}
// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
this.SaveToPhoneState(Locator.Instance.Model);
}

And that’s it. Your model now persists to the phone state and survives, for instance, a hit on the search button

Storing in Isolated Storage

This proves to be marginally more difficult. I expanded the class ApplicationExtensions with two more methods and a const:

You now have to find Application_Launching and Application_Closing in App.Xaml.cs and modify them in a similar way:

// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
Locator.Instance.Model =
this.RetrieveFromIsolatedStorage<YourModel>();
}
// Code to execute when the application is closing (eg, user hit Back)
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
this.SaveToIsolatedStorage(Locator.Instance.Model);
}

Some notes

In order to make this work, your need to mark your model class with the [DataContract] attribute, and every member you want to be serialized with [DataMember]

If you are using MVVMLight (which of course you are ;-) ) and if you are just making simple apps that don’t use separate models but just view models, be aware that your model cannot inherit from ViewModelBase, for the simple reason that this class is not serializable. Oops ;-)

If your model communicates with the view using attached dependency properties you may run into some timing difficulties. I will soon blog about a work-around for that.

10 September 2010

For my ongoing ‘research project’ on making the user experience for my MVVM-driven map viewer for Windows Phone 7 a bit better I wanted to make some changes to the header. Initially you could swipe the header which showed which map you show, but it gave no indication that you actually could make the swipe, or that other maps were available. I set out to create a behaviour, and ended up building a control. In my map viewer, it currently looks and works like this:

And, of course, it needed to play along nicely with MVVM. And therefore it has three bindable properties:

Items: an IList of basically anything

SelectedItem: the currently selected item in Items

DisplayText: (optional): the name property of the objects in Items which value should be used in de SwipeTitle. If skipped, the ToString() value of the objects is used as a display value.

It does not sport item or data templates (yet) – it’s just meant to be plug and play. For now.

Usage

You only have to do six things to use this thing:

Create an empty Windows Phone 7 application

Add the LocalJoost.Controls project included in the demo solution to your project.

Create some kind of model with a property containing a list of objects and a property containing a selected object and bind it to the layout root

Drag the SwipeTitle control on the design surface at the place of the TextBox called “PageTitle” (and remove PageTitle)

Bind property Items, SelectedItem and DisplayText as needed

Make sure the Width property of the StackPanel “TitlePanel” is some large width, e.g. 2000.

Below is a short walkthrough of the source. Those who just want to use it, can just grab the source. If you want a simple sample application showing the usage of the control, just grab this solution and see how it works. I sincerely apologize for the sheer silliness of the demo solution, it was all I could think of on short notice.

Walkthrough

The XAML is pretty simple: three TextBlocks in a horizontal StackPanel:

You can swipe endlessly left or right, when it comes to the end or the start of the list it just adds the items from the start or the end again. The middle text is the selected object, and is always shown (in white). When you swipe the text to the left, it animates the swipe to completion: the text previously on the right, which you swiped into view, is now displayed in the middle TextBlock. The text that used to be in the middle block, is now in the left, and in the right TextBlock a new text from Items is displayed, as shown in the video.

Now how does this work? If you know how to do it, it is – as everything – pretty simple. First, some boring stuff, the class definition with some members and dependency properties:

The transformation is used in the animation and to make sure the middle TextBlock is displayed when idle. I tend to tuck dependency properties in regions to keep stuff a bit organized, but feel free to do otherwise. Note, however, that the objects in Items are immediately copied in a LinkedList _displayItems – I use this list to make it easier to find previous and next objects.

Then we need a little method to get the display text from the objects according to the value of “DisplayField”:

To show or update the displayed texts, according the object that is selected (in SelectedItem), the UpdateDisplayTexts method is needed. This is fired when Items or SelectedItem is changed. It finds SelectedItem and puts it in the middle TextBlock, and finds the texts that need to be before and after it, using the LinkedList _displayItems.

In the constructor the members are initialized – particularly the transform – which is set to the StackPanel surrounding the three TextBlocks. When the user now swipes, the texts appear to follow him. When, in pnlSwipe_ManipulationCompleted, the user has dragged the text over more than 25% of the screen, it scrolls the text further until the newly selected items is fully into view. If the text value of the last box is changed, we need to reset the middle TextBlock in the center again – but now without animation, and so it will seem if the scrolling text suddenly changes in color and appears to be selected.

Notice a little gem in here – the ScreenWidth property. It turns out you can determine the actual screensize by trying to cast the RootVisual to a Frame, and then check it’s RenderSize.

All that is left now, basically, is the implementation of ScrollToDisplayItem – and a companion method, as shown below:

In ScrollToDisplayItem the text is either moved or animated in the right direction, and when the animation is finished, the TextBlocks are updated with values according to the swipe direction. If no animation is needed – which occurs initially, or after the texts are updated – the transform is simply applied in stead of animated.

Credits

Important parts of the code came into being during a joint hacking evening at Sevensteps in Amersfoort, Netherlands, at August 31 2010. My sincere thanks to Bart Rozendaal, Kees Kleimeer and Pieter-Bas IJdens, all of Sevensteps, who basically coded the method pnlSwipe_ManipulationCompleted and the property ScreenWidth, almost all of the ScrollToDisplayItem method, and in addition supported me with wine, snacks and enjoyable company during that memorable evening.

Feedback, comments and tokens of appreciation

If you spot things that are incorrect, or if you don't understand what I mean, please drop a comment on the offending article and I will help you ASAP. You can e-mail me at joostvanschaik at outlook dot com or contact me via twitter.

If you find the information on this blog useful (and apparently some 600+ people per day do on average) please let me know as well, that encourages me to keep doing this. Or do tell others - that made me an MVP; who knows what more it might bring ;-P

Disclaimer and legal stuff

Although I take great care in providing quality samples, all postings, articles and/or files on this site are provided "AS IS" with no warranties, and confer no rights. The views expressed on this blog are strictly my own and do not necessarily reflect the views of my employer, or anyone else on the planet for that matter.

I usually make original content, sometimes building upon other people's work. Sometimes I explain things that can be found elsewhere because I felt what I read was not clear enough for my limited mind so I explain it the way it finally clicked with me. In all cases I take great pains to be sure to link to people or articles who deserve the credit. If you think I have shortchanged you on the credits please let me know.

Please note, I do not work for Microsoft and while I proudly wear the title of "Microsoft Most Valueable Professional", my opinions, files offered, etc. do not represent, are approved of, endorsed by or paid for by Microsoft. The only power behind it is me and my sometimes runaway passion for parts of Microsoft's technology.