This article is going to describe how to use MVVM pattern in Windows Phone 7 using a WCF service.
Getting Started
Creating a Windows Phone Application:
- Open Visual Studio 2010.
- Go to File => New => Project
- Select Silverlight for Windows Phone from the Installed templates and choose Windows Phone Application
- Enter the Name and choose the location.
Click OK.
Image 1.
Now add a new WCF Service application using Add New Project.
Image 2.
Image 3.
Now add a class using LINQ to SQL Classes in WCF service using the Add New Item tab. And drag and drop data tables from database.
Image 4.
My data model looks like this.
Image 5.
Now start coding the WCF service. Put this code in.
EventService.svc.cs
public class EventsService : IEventsService
{
MCDataClassesDataContext context = new MCDataClassesDataContext();
public List<Post_CastingCall> GetLatestEvents()
{
var dateTime = DateTime.Now.ToString();
var events = (from r in context.Post_CastingCalls
//where (Convert.ToDateTime(r.Date_Expires) > DateTime.Now)
orderby r.Date_Sent descending
select r);
return events.ToList();
}
public List<Post_CastingCall> GetEventByEventId(int eventId)
{
MCDataClassesDataContext context = new MCDataClassesDataContext();
var eventsbyid = from p in context.Post_CastingCalls
where p.ID == eventId
select p;
return eventsbyid.ToList();
}
}
IEventsService.cs
[ServiceContract]
public interface IEventsService
{
[OperationContract]
List<Post_CastingCall> GetLatestEvents();
[OperationContract]
List<Post_CastingCall> GetEventByEventId(int eventId);
}
Now build the service and you can check that the WCF service is working or not using right click and View in Browser.
Image 6.
When you click on given URL, it shows result in XML format like this.
Image 7.
We are done here with creating the service; now to work on the application. Right click on application and click Add Service Reference.
Image 8.
Now discover the service reference and click OK.
Image 9.
Now add a folder to the application; the name should be Model and add a new class in this folder and give it the name Events.cs.
Model/Events.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using MCMobile.BindingUtilities;
namespace MCMobile.Model
{
public class Events : ViewModelBase
{
public int UserId { get; set; }
public string _category;
public string _title;
public string _city;
public string _state;
public string _country;
public string _zip;
public string _description;
public Uri _logo;
//This property idicates event category field
public string Category
{
get
{
return _category;
}
set
{
_category = value;
NotifyPropertyChanged("Category");
}
}
//This property idicates event title field
public string Title
{
get
{
return _title;
}
set
{
_title = value;
NotifyPropertyChanged("Title");
}
}
//This property idicates event city field
public string City
{
get
{
return _city;
}
set
{
_city = value;
NotifyPropertyChanged("City");
}
}
//This property idicates event state field
public string State
{
get
{
return _state;
}
set
{
_state = value;
NotifyPropertyChanged("State");
}
}
//This property idicates event country field
public string Country
{
get
{
return _country;
}
set
{
_country = value;
NotifyPropertyChanged("Country");
}
}
//This property idicates event zip field
public string Zip
{
get
{
return _zip;
}
set
{
_zip = value;
NotifyPropertyChanged("Zip");
}
}
//This property idicates event description field
public string Description
{
get
{
return _description;
}
set
{
_description = value;
NotifyPropertyChanged("Description");
}
}
//This property idicates event logo field
public Uri Logo
{
get
{
return _logo;
}
set
{
_logo = value;
NotifyPropertyChanged("Logo");
}
}
}
}
Make another folder with the name BindingUtilities and add a class inside of that folder.
ViewModelBase.cs
using System;
using System.Windows;
using System.ComponentModel;
namespace MCMobile.BindingUtilities
{
public abstract class ViewModelBase
: DependencyObject, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public bool IsDesignTime
{
get { return DesignerProperties.IsInDesignTool; }
}
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
You can write this method in the Events class which I have written in comments code.
Now add a folder named ViewModel and add a class inside of that folder.
ViewModel/EventsViewModel.cs
using MCMobile.EventServiceReference;
using System.Linq;
using System.Collections.Generic;
using MCMobile.BindingUtilities;
using MCMobile.Model;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Media.Imaging;
public class EventsViewModel : ViewModelBase
{
//public List<Events> EventCollections{ get; set; }
public void LoadEvents()
{
EventsServiceClient eventsvc = new EventsServiceClient();
eventsvc.GetLatestEventsCompleted += new EventHandler<GetLatestEventsCompletedEventArgs>(eventsvc_GetLatestEventsCompleted);
eventsvc.GetLatestEventsAsync();
}
void eventsvc_GetLatestEventsCompleted(object sender, GetLatestEventsCompletedEventArgs e)
{
var element = e.Result;
var events =
from var in element
select new Events
{
UserId = Convert.ToInt32(var.UserId),
Title = var.Job_Title,
Category = var.Category.ToString(),
Logo = new Uri("/MCMobile;component/Logo/" + var.UserId + "/" + "Real/" + var.Logo.ToString(), UriKind.Relative),
City = var.Job_City,
State = var.Job_State,
Country = var.Job_Country,
Zip = var.ZipCode
};
EventCollections = events.ToList();
}
public List<Events> _collections;
public List<Events> EventCollections
{
get
{
return _collections;
}
set
{
_collections = value;
NotifyPropertyChanged("EventCollections");
}
}
}
Now add one more folder name View and inside of this folder add a Windows Phone user control using the Add New Item tab.
View/EventsView.xaml
<UserControl x:Class="MCMobile.View.EventsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<UserControl.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Green"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="black"/>
</Style>
<Style TargetType="TextBlock" x:Key="HeaderBoldText">
<Setter Property="Foreground" Value="Green"></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="FontFamily" Value="Verdana"></Setter>
<Setter Property="FontSize" Value="24"></Setter>
</Style>
<Style TargetType="TextBlock" x:Key="TitleText">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#4E87D4"/>
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="Margin" Value="0,40,10,10"/>
<Setter Property="Width" Value="300"></Setter>
</Style>
<Style TargetType="TextBlock" x:Key="Label">
<Setter Property="FontSize" Value="8"/>
<Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,3,10,0"/>
<Setter Property="Width" Value="100"></Setter>
<Setter Property="Height" Value="20"></Setter>
</Style>
</UserControl.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 x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="Latest Events" Style="{StaticResource HeaderBoldText}"/>
<!--<TextBlock x:Name="PageTitle" Text="Events" 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">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox Height="664" HorizontalAlignment="Left"
Margin="14,14,0,0"
Name="eventsListBox"
VerticalAlignment="Top"
ItemsSource="{Binding Path=EventCollections}"
Width="432">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,8,0">
<Image Source="{Binding Logo}" Width="150" HorizontalAlignment="Center" ></Image>
<StackPanel Width="370" Margin="5,0,0,0">
<TextBlock Text="{Binding Title}" Style="{StaticResource HeaderBoldText}" />
<TextBlock Text="{Binding City}" />
<TextBlock Text="{Binding State}" />
<TextBlock Text="{Binding Country}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</UserControl>
Image 10.
Now add a new Windows Phone Portrait Page in the root application. And add namespace of view folder.
EventsPage.xaml
<phone:PhoneApplicationPage
x:Class="MCMobile.EventsPage"
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" d:DesignHeight="768" d:DesignWidth="480"
xmlns:views="clr-namespace:MCMobile.View"
shell:SystemTray.IsVisible="True">
<!--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 x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<views:HeaderView x:Name="headerView"></views:HeaderView>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<views:EventsView x:Name="eventsView"></views:EventsView>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
EventsPage.xaml.cs
using MCMobile.EventViewModelNamespace;
public partial class EventsPage : PhoneApplicationPage
{
public EventsPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(EventsPage_Loaded);
}
void EventsPage_Loaded(object sender, RoutedEventArgs e)
{
EventsViewModel EmployeeViewModel = new EventsViewModel();
EmployeeViewModel.LoadEvents();
eventsView.DataContext = EmployeeViewModel;
//GetEvents();
}
private ImageSource GetImage(string fileName)
{
return new BitmapImage(new Uri(fileName, UriKind.Relative));
}
}
Now it is time to build and run the application to see the output.
Image 11.
Conclusion
So we are done here with MVVM pattern in Windows Phone using WCF service. If you have questions or comments then drop me a line in the comments section.