Home > Windows 8.1 > Create Windows 8.1 Store app from blank template using simple MVVM pattern

Create Windows 8.1 Store app from blank template using simple MVVM pattern

Create new project in VS 2013 using “Blank App” template

image

 

Make the ViewModel bindable

Add a new directory ViewModels and add a new class BaseViewModel.cs insde this directory with this content inside the namespace:

 

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

 

Download source from here

Add another class file called MainViewModel.cs with this content inside the namespace:

public class MainViewModel : BaseViewModel
{
    private string firstname = String.Empty;
    public string Firstname
    {
        get { return firstname; }
        set { SetField( ref firstname, value ); }
    }

    private string lastname = String.Empty;
    public string Lastname
    {
        get { return lastname; }
        set { SetField(ref lastname, value); }
    }
}

 

This way the properties in MainViewModel will automatically be able to databind in both directions.

 

Create a singleton for central access to the ViewModel

Now we must find a way to access the ViewModel from every place inside the app.

This can be done using a singleton pattern like this in app.xaml.cs:

 

private static MainViewModel myMainViewModel = null;
public static MainViewModel MyMainViewModel
{
    get
    {
        if (myMainViewModel == null)
        {
            myMainViewModel = new MainViewModel();
        }
        return myMainViewModel;
    }
}

 

Define the UI

Now add a few controls to Mainpage.xaml.cs (red block)

image

 

Setting the DataContext

in Mainpage.xaml.cs inside the ctor:

image

 

Please note:

Setting the DataContext in the XAML-file using <Page.Resources> does create a new instance of our MainViewModel class each time we open the MainPage, which is not what we want.

Therefore this statement for setting the DataContext is NOT USED here!

See the section “Adding designtime support..” below!

 

<!-- Does create a new instance every thime, because it's not using our singleton -->
<!--<Page.Resources>
    <ViewModels:MainViewModel /> NOT USED HERE !!
</Page.Resources>-->

 

 

Saving data when the OS terminates / suspends the app

Now add saving and loading to LocalSettings or RoamingSettings using code like this in the OnSuspend event:

 

private void OnSuspending(object sender, SuspendingEventArgs e)
{
    var deferral = e.SuspendingOperation.GetDeferral();
    //TODO: Save application state and stop any background activity
    ApplicationData.Current.LocalSettings.Values[Constants.LocalStorage.VIEWMODELDATA] 
        = Utility.SerializeToString(App.ViewModel);
    deferral.Complete();
}

Helper class for serialization / Deserialization

public static string SerializeToString(object obj)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

public static T DeserializeFromString<T>(string xml)
{
    XmlSerializer deserializer = new XmlSerializer(typeof(T));
    using (StringReader reader = new StringReader(xml))
    {
        return (T)deserializer.Deserialize(reader);
    }
}

 

 

 

Reload data after app was suspended

Then make sure, that when the program starts up after it was supended through the OS, that it’s loading the last data using code like this in the OnLaunched event:

if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
    //TODO: Load state from previously suspended application
    if (ApplicationData.Current.LocalSettings.Values[Constants.LocalStorage.VIEWMODELDATA] != null)
    {
        var serializedData 
            = ApplicationData.Current.LocalSettings.Values[Constants.LocalStorage.VIEWMODELDATA] as string;
        App.ViewModel = Utility.DeserializeFromString<MainViewModel>(serializedData);
    }
}

 

 

Adding designtime support / Intellisense for binding statements

using Blend:

Open MainPage.xaml in Blend and click on “Set design-time DataContext” in the right lower corner:

image

 

Select DesignInstance in the following dialog like this:

image

 

 

Create demo data for design time

 

Create dummy data in the ctor of the ViewModel and decide whether its running in design mode using:

if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)

 

 

 

 

.

Categories: Windows 8.1
  1. Carlos
    April 3, 2014 at 2:08 pm

    This was a very interesting presentation and I learn a few things from it. But I am having trouble reproducing.

    First on the step about reloading the data after the application has been susptended you make a reference to Constants.LocalStorage.VIEWMODEL. What is the Namespace under which CONSTANTS is storage? Visual studio says it should be under VB but CONSTANT type define there does not have a member called LocalStorage.

    Second would you continue the example?

  2. April 4, 2014 at 4:03 pm

    Hi Carlos,
    sorry, you are right. the constants class is not described anywhere, but this is just a small class, which i add here:
    public static class Constants
    {
    public static class LocalStorage
    {
    public const string VIEWMODELDATA = “VIEWMODELDATA”;
    ….

    This way, you don’t have string constants cluttering all over your code and can use Intellisense for referencing this constants..

    And yes, i’ll add a few more steps in the description

    Regards
    Hans

  3. October 28, 2014 at 10:37 pm

    Hi Hans,

    I’m trying to implement a very similar approach, I get an error in the SerializeToString method:

    In the line XmlSerializer serializer = new XmlSerializer(obj.GetType());

    {“There was an error reflecting type ‘TestApp.ViewModel.MainViewModel’.”}

    Any idea how to fix it?

    why do we need the design-time DataContext?

    Thanks

    • October 28, 2014 at 11:41 pm

      Hi Juan,
      sorry, but i’ve no idea, why you get this message.
      Try to set a breakpoint on the line and then use QuickView to inspect the obj variable.

      I’ll send a private email to you, wher you could return your source code package, if you want.
      i’ll have a look on it, but i cannot promise anything!
      The design-time DataContext is only needed if you want to have sample data visible in the Visual studio designer!

      Regards
      Hans

  4. October 31, 2014 at 6:24 pm

    Hi Hans! I solved it, the serializer couldnt serilaize a RelayCommand, a [XmlIgnore()] solved it. Thanks for the quick response and also for the mail

  1. No trackbacks yet.

Leave a Reply to hansstan Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: