Sunday, September 1, 2013

MVVM – Windows Phone 8 App using XAML/C#.NET Primer

MVVM – Windows Phone 8 App using XAML/C#.NET Primer
 
Purpose: The purpose of this document is to illustrate how to how to apply MVVM (Model-View-ViewModel) architectural pattern when developing Windows Phone 8 Product catalog App using XAML/C#.NET
 
Challenge: You may need to develop a modern application integrated with Microsoft Dynamics AX 2012 for the purposes of demonstration, POC or to be deployed in production environment. The question is what technology and architectural pattern to use in order to facilitate application development and maintenance efforts        
 
Solution: In this scenario we'll leverage Windows Phone 8 SDK for developing Windows Phone 8 App using XAML/C#.NET
 
Walkthrough
 
First off let's create a new project using Visual C# > Windows Phone > Windows Phone App template
 
New Project
 
 
Target Windows Phone OS Version
 
 
Then we'll apply MVVM (Model-View-ViewModel) architectural pattern for development of Product catalog app
 
Solution Explorer
 
 
For the sake of clarity I created 3 folders for Model, View and ViewModel
 
The model encapsulates business logic and data. Please see below how I define Product class which has 2 attributes: ID and Name as a part of the model
 
Model
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace PhoneApp1.Model
{
    public class Product
    {
        public string ID { get; set; }
        public string Name { get; set; }
    }
}
 
The view model encapsulates presentation logic and state. Please see below how I define ObservableCollection of products with respective method(s) (GetProducts) as a part of the view model
 
ViewModel
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.ComponentModel;
using System.Collections.ObjectModel;
using PhoneApp1.Model;
 
namespace PhoneApp1.ViewModel
{
    public class ProductViewModel
    {
        private ObservableCollection<Product> _Products = new ObservableCollection<Product>();
 
        public ObservableCollection<Product> Products
        {
            get
            {
                return _Products;
            }
            set
            {
                _Products = value;
            }
        }
 
        public void GetProducts()
        {
            Product product;
 
            product = new Product();
            product.ID = "X";
            product.Name = "AlexProductX";
            Products.Add(product);
        }
    }
}
 
 
The view encapsulates the UI and any UI logic. Please see below how I instantiate an object of view model class to retrieve a list of products
 
View (ProductsPage.xaml.cs)
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
 
using PhoneApp1.Model;
using PhoneApp1.ViewModel;
 
namespace PhoneApp1.View
{
    public partial class ProductsPage : PhoneApplicationPage
    {
        public ProductsPage()
        {
            InitializeComponent();
 
            ProductViewModel productViewModel = new ProductViewModel();
            productViewModel.GetProducts();
            this.DataContext = productViewModel;
        }               
    }
}
 
And then I use bindings to link product metadata to respective UI elements for display
 
XAML (ProductPage.xaml)
 
<phone:PhoneApplicationPage
    x:Class="PhoneApp1.View.ProductsPage"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">
    <phone:PhoneApplicationPage.Resources>
        <DataTemplate x:Key="ProductDataTemplate">
            <Grid Width="400" Height="100" Background="White">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Border BorderThickness="2" BorderBrush="White" Height="100" VerticalAlignment="Top" Background="Black">
                    <TextBlock TextWrapping="Wrap" Text="{Binding ID}" Style="{StaticResource PhoneTextNormalStyle}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                </Border>
                <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Top" Style="{StaticResource PhoneTextSubtleStyle}" Margin="10,5,10,0" Grid.Column="1" Foreground="Black"/>
            </Grid>
        </DataTemplate>
    </phone:PhoneApplicationPage.Resources>
 
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="Product Catalog" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="Product Catalog" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
 
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <phone:LongListSelector x:Name="ProductLongListSelector" ItemsSource="{Binding Products}" ItemTemplate="{StaticResource ProductDataTemplate}"/>
        </Grid>
    </Grid>
 
</phone:PhoneApplicationPage>
 
Please note that LongListSelector control was specifically designed for phone scenarios and it is encouraged to use the LongListSelector instead of ListBox for phone apps
 
Please note that I used ItemTemplate to define a style. You can easily generate ItemTemplate as shown below 
 
Document Outline
 
 
And then define a style for any UI element as you wish
 
ProductsPage.xaml (ProductDataTemplate)
 
<phone:PhoneApplicationPage
    x:Class="PhoneApp1.View.ProductsPage"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">
    <phone:PhoneApplicationPage.Resources>
        <DataTemplate x:Key="ProductDataTemplate">
            <Grid Width="400" Height="100" Background="White">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Border BorderThickness="2" BorderBrush="White" Height="100" VerticalAlignment="Top" Background="Black">
                    <TextBlock TextWrapping="Wrap" Text="{Binding ID}" Style="{StaticResource PhoneTextNormalStyle}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                </Border>
                <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Top" Style="{StaticResource PhoneTextSubtleStyle}" Margin="10,5,10,0" Grid.Column="1" Foreground="Black"/>
            </Grid>
        </DataTemplate>
    </phone:PhoneApplicationPage.Resources>
 
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="Product Catalog" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="Product Catalog" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
 
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <phone:LongListSelector x:Name="ProductLongListSelector" ItemsSource="{Binding Products}" ItemTemplate="{StaticResource ProductDataTemplate}"/>
        </Grid>
    </Grid>
 
</phone:PhoneApplicationPage>
 
As the result our Product catalog application will look like below
 
Result
 
 
Please review the following article to learn how to quickly connect your application to Microsoft Dynamics AX 2012 Demo VM to test out the integration: http://ax2012aifintegration.blogspot.com/2013/04/microsoft-dynamics-ax-2012-windows-8.html
 
In case you are developing a mobile application for production please review the best practice guidance on Developing Mobile apps for Microsoft Dynamics AX 2012 here: http://www.microsoft.com/en-us/download/details.aspx?id=38413
 
Summary: This document describes how to apply MVVM (Model-View-ViewModel) architectural pattern when developing Windows Phone 8 Product catalog sample App using XAML/C#.NET.
 
Author: Alex Anikiev, PhD, MCP
 
Tags: MVVM, Model-View-ViewModel, Windows Phone 8 App, C#.NET, XAML, Microsoft Dynamics AX 2012.
 
Note: This document is intended for information purposes only, presented as it is with no warranties from the author. This document may be updated with more content to better outline the concepts and describe the examples.

No comments:

Post a Comment