Wiki

Clone wiki

AtomicMVVM / Windows_Phone_7.1_&_Pure_AtomicMVVM

Before you begin with Windows Phone 7.1, I urge you to read the AtomicPhoneMVVM section to decide if this is the correct MVVM framework for you. Step 1. We will start off with an empty Windows Phone project; just to show you how easy it is to get started! Step 2. Grab AtomicMVVM from Nuget - this will create the two folders needed, namely: Views & ViewModels. Step 3. Open your MainPage.xaml (this will be our shell) and remove the Grid.

<phone:PhoneApplicationPage 
    x:Class="WP71Demo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
</phone:PhoneApplicationPage>

Step 4. In the code behind for MainPage.xaml, have the class inherit from IShell and implement the interface. It has one method which is used to set the content of our ContentControl when the view changes.

public partial class MainPage : PhoneApplicationPage, IShell
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public void ChangeContent(UserControl viewContent)
    {
        this.Content = viewContent;
    }
} 

Step 5. Now we will create the view model. Right click on the ViewModels folder and add a new public class that inherits from CoreData called Simple (i.e. Simple.cs). This view model has a Name property, a method that says hello and a method that states if Name is not null or white space.

public class Simple : CoreData
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            RaisePropertyChanged("Name");
        }
    }

    public void SayHi()
    {
        MessageBox.Show("Hello "+this.Name);
    }

    [ReevaluateProperty("Name")]
    public bool CanSayHi()
    {
        return !string.IsNullOrWhiteSpace("Name");
    }
} 

Notes:

  1. The Name property calls RaisePropertyChanged, which is a helper method to INotifyPropertyChanged.
  2. The name of the SayHi method and its signature (returns void, takes no parameters). This is important for the convention based binding for commands.
  3. The name of CanSayHi method, it’s convention of the Can prefix, and its signature (returns Boolean, takes no parameters). This is important for the convention based binding for commands.
  4. The ReevaluateProperty attribute which tells the bootstrapper that when the Name property changes the result of this method changes too.
    • Step 6. Now for the view, right click on the Views folder and add a UserControl named Simple (i.e. Simple.xaml) and in there we add the XAML to enter a name and click a button.
<UserControl x:Class="WP71Demo.Views.Simple"             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <TextBlock Text="Name"/>
        <TextBox Text="{Binding Name}"/>
        <Button x:Name="SayHi" Content="Say Hello"/>
    </StackPanel>
</UserControl>

Notes:

  1. We use normal binding for the Text property of the TextBox to the Name property of the view model.
  2. The Button name is the same as our method name in the view model.
    • Step 7. Open the App.xaml.cs file and add a property or field of type Bootstrapper.
public partial class App : Application
{
    public static Bootstrapper Bootstrapper {get;set;}

Step 8. Next modify the InitializePhoneApplication method content so that it creates the Bootstrapper and calls the Start<TShell,TContent> method to tie everything together. The first generic type is the class to use as the shell (i.e. our MainWindow) and the second is the default view model to load into the shell. You also need to remove all the RootFrame code. You can also clean out RootFrame from the rest of the app class too.

private void InitializePhoneApplication()
{
    if (phoneApplicationInitialized)
        return;

    Bootstrapper = new Bootstrapper();
    Bootstrapper.Start<MainWindow, ViewModels.Simple>();

    phoneApplicationInitialized = true;
} 

Step 9. Press F5 and enjoy

Updated