Sunday, October 30, 2011

MVVM with Silverlight (Start to End)

Why we use MVVM?

 1. MVVM provide application to code reuse.
2. Simplifies the application.
3. Easy to maintenance and provide maximum support for the testing.

What is MVVM?
Model-View-ViewModel (MVVM) is a design pattern which can be use in WPF and Silverlight.

Model : Entities (Most of the time directly connect with the application backend.)
View : Your silverlight screens.
ViewModel : The glue between the Model and View.

In Silverlight View and ViewModel will located in the client side and Model will located in server side.So We have to use Communication method to communicate between the Client and server side. Most of the time we user WCF Service for this.

Now we will implement a simple silverlight application using MVVM pattern.This example I will explain the Command and Property Binding using MVVM.

Business Requirement : We want to find the person information using person ID and we want to display person information in web form..Here Person information is stored in the server side.



Solution :
1. Create a new Silverlight application and name it as MVVMSample.Now Visual Studio will create Silverlight project and Web Application project for you.


2. Now right click on the MVVMSample.Web project and add New Class named by PersonData and implement the class as bellow.


namespace Index.Web
{
    public class PersonData
    {
        public int PersonID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }
}


3.Again Right Click on the MVVMSample.Web project and add New Class named by PersonRepository and implement the class as bellow.


using System.Collections.Generic;

namespace Index.Web
{
    public class PersonRepository
    {
        public IList<PersonData> Person{get;set;}

        public PersonRepository()
        {
            GeneratePersonList();
        }

        private void GeneratePersonList()
        {
            Person = new List<PersonData>() 
            {
                new PersonData() { PersonID = 1, FirstName = "Erandika",    LastName = "Sandaruwan", Age=25,     Address = "Delgoda"    },
                new PersonData() { PersonID = 2, FirstName = "Niluka",      LastName = "Dilani",     Age = 30,   Address = "Kandy"      },
                new PersonData() { PersonID = 3, FirstName = "Chathura",    LastName = "Achini",     Age = 27,   Address = "Colombo"    },
                new PersonData() { PersonID = 4, FirstName = "Florina",     LastName = "Breban",     Age = 25,   Address = "Romania"    },
            };
        }
    }
}


4.Finally we want to add our silverlight enable WCF service to MVVMSample.Web project.To do that right click on the MVVMSample.Web project Select the Add New Item and then in Installed Template under Visual C# select the Silverlight.Now select the  Silverlight-enable WCF Service and name it as PersonDataService.svc and click on the Add button.



Now implement the service class as bellow.


using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Index.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class PersonDataService
    {
        [OperationContract]
        public PersonData FindPerson(int personID)
        {
            return new PersonRepository().Person.Where(x => x.PersonID == personID).SingleOrDefault();
        }
    }
}

So here now we have completed our model part.So next we have to implement our View and ViewModel part.

5.First We will add our PersonDataService to our silverlight project.To do that In MVVMSample project right click on References and click on Add Service Reference and then Add References Window will open for you and click on Discover button and VS will display all the services that have been added to current solution. But here we have only one service.Give the Namesapce as PersonDataService and click OK button.(Remember before this you have to build your web application project first) and then service reference will added to the your silverlight project.

6. Now add new folder to Silverlight project and named it as ViewModel and add two classes named by MainPageViewModel. and ViewModelBase. Again add new folder called ServiceAgent and add a Interface called IPersonService.and implement the interface as bellow.


using System;
using MVVMSample.PersonDataService;

namespace MVVMSample.ServiceAgent
{
    public interface IPersonService
    {
        void FindPerson(int personID,EventHandler<FindPersonCompletedEventArgs> callBack);
    }
}

Now we want to implement PersonService class using IPersonService interface.So to do that add a new class to ServiceAgent folder and named it as PersonService and then implement the class as bellow.


using System;
using MVVMSample.PersonDataService;

namespace MVVMSample.ServiceAgent
{
    public class PersonService:IPersonService
    {
        private PersonDataServiceClient client = new PersonDataServiceClient();

        public void FindPerson(int personID, EventHandler<FindPersonCompletedEventArgs> callBack)
        {
            client.FindPersonCompleted += callBack;
            client.FindPersonAsync(personID);
        }
    }
}


7. Now we have to implement our ViewModel.Note that here we want to use ICommand interface for the implement the command which it bind to Search button. Here we will use Prism Framework.So we do not want to implement the Command and we can directly use DelegateCommand.You can download the Prism framework from following URL http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=4922
And you have to add as Microsoft.Practice.Prism.dll which is belongs to silverlight as reference to your silverlight project.Now we will start implement our MainPageViewModel and ViewModelBase classes.So First we will implement our ViewModelBase class as bellow.


using System.ComponentModel;

namespace MVVMSample.ViewModel
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public bool IsDesignTime
        {
            get
            {
                return DesignerProperties.IsInDesignTool;
            }
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            var propertyChanged = PropertyChanged;

            if (propertyChanged != null)
            {
                propertyChanged(this,new PropertyChangedEventArgs(propertyName));
            }
        }


        
    }
}

Here you can see that our ViewModelBase class in implemented from INotifyPropertyChanged interface.This is very important in silverlight data binding  to notify  controls and other objects when a bound property value changes.So by using our ViewModelBase class we can reuse it across the multiple ViewModel. So Now we will implement our MainPageViewModel as bellow.




using System.Windows.Input;
using MVVMSample.PersonDataService;
using MVVMSample.ServiceAgent;
using Microsoft.Practices.Prism.Commands;

namespace MVVMSample.ViewModel
{
    public class MainPageViewModel : ViewModelBase
    {

        private PersonService _personService;
        public MainPageViewModel()
        {
            if (IsDesignTime != true)
            {
                this._personService = new PersonService() ;
                this.FindPersonCommand = new DelegateCommand<object>(this.FindPersonByID);
            }
        }

        private PersonData _personData;
        public PersonData PersonData
        { 
            get
            {
                return _personData;
            }
            set
            {
                if (_personData != value)
                {
                    _personData = value;
                    OnPropertyChanged("PersonData");
                }
            }
        }

        private int _personID;
        public int PersonID
        {
            get 
            {
                return _personID;
            } 
            set
            {
                if (_personID != value)
                {
                    _personID = value;
                    OnPropertyChanged("PersonID");
                }
            } 
        }

        public ICommand FindPersonCommand{get;set;}


        private void FindPersonByID(object obj)
        {
            if (PersonID != 0)
            {
                _personService.FindPerson(PersonID, (s, e) => PersonData = e.Result);
            }
        }

    }
}

You can see that we we inherit our MainPageViewModel class from ViewModelBase class  and we reuse IsDesignTime property and OnPropertyChanged method in here. Also note that we are using DelegateCommand here.Which is come from Microsoft.Practice.Prism.dll and so we do not want to worry to implement this event.So now our MainPageViewModel is ready now and we have to bind data to our silverlight View.In this example we are going to bind PersonData and PersonID property and FindPersonCommand command to silverlight View.

8. Now we will create our silverlight View and Bind the Data from our ViewModel.You implement our view as bellow.




<UserControl x:Class="MVVMSample.MainPage"
    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"
    xmlns:viewModel="clr-namespace:MVVMSample.ViewModel"
    d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
    
    <UserControl.DataContext>
        <viewModel:MainPageViewModel/>
    </UserControl.DataContext>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="25"/>
            <RowDefinition Height="25"/>
            <RowDefinition Height="5"/>
            <RowDefinition Height="25"/>
            <RowDefinition Height="5"/>
            <RowDefinition Height="25"/>
            <RowDefinition Height="5"/>
            <RowDefinition Height="25"/>
            <RowDefinition Height="5"/>
            <RowDefinition Height="25"/>
        </Grid.RowDefinitions>
        
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        
        <sdk:Label Height="25" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" Name="label1" VerticalAlignment="Center" Width="120" Content="Person ID :" />
        <TextBox Height="25" Grid.Row="1" Grid.Column="1"  HorizontalAlignment="Left" Name="txtPersonID" VerticalAlignment="Top" Width="150" Text="{Binding PersonID, Mode=TwoWay}" />
        <Button Grid.Row="1" Grid.Column="2" Content="Search" Height="25" HorizontalAlignment="Left" Name="btnSearch" VerticalAlignment="Top" Width="75" Command="{Binding FindPersonCommand}" />
        
        <sdk:Label Height="25" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Right" Name="label2" VerticalAlignment="Center" Width="120" Content="First Name :" />
        <TextBox  Height="25" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left" Name="txtFirstName" VerticalAlignment="Top" Width="200" Text="{Binding Path=PersonData.FirstName, Mode=TwoWay}" />
        
        <sdk:Label Height="25" Grid.Row="5" Grid.Column="0" HorizontalAlignment="Right" Name="label3" VerticalAlignment="Center" Width="120" Content="Last Name :" />
        <TextBox  Height="25" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Left" Name="txtLastName" VerticalAlignment="Top" Width="200" Text="{Binding Path=PersonData.LastName, Mode=TwoWay}" />
        
        <sdk:Label Height="25" Grid.Row="7" Grid.Column="0" HorizontalAlignment="Right" Name="label4" VerticalAlignment="Center" Width="120" Content="Age :" />
        <TextBox  Height="25" Grid.Row="7" Grid.Column="1" HorizontalAlignment="Left" Name="txtAge" VerticalAlignment="Top" Width="200" Text="{Binding Path=PersonData.Age, Mode=TwoWay}" />
        
        <sdk:Label Height="25" Grid.Row="9" Grid.Column="0" HorizontalAlignment="Right" Name="label5" VerticalAlignment="Center" Width="120" Content="Address :" />
        <TextBox Height="25" Grid.Row="9" Grid.Column="1" HorizontalAlignment="Left" Name="txtAddress" VerticalAlignment="Top" Width="200" Text="{Binding Path=PersonData.Address, Mode=TwoWay}" />
        
    </Grid>
</UserControl>

Now if all the things are working correctly you can run the application. And you will see the nice interface without having exceptions.

You can download the source code from here for this example : Download Here

Tuesday, October 11, 2011

C# Programming for beginners: Silverlight Child Windows (Modal Windows)

C# Programming for beginners: Silverlight Child Windows (Modal Windows): Silverlight Child Window provide functionality to pop up a window and it will disable the rest of the application until the window is closed...

Silverlight Child Windows (Modal Windows)

Silverlight Child Window provide functionality to pop up a window and it will disable the rest of the application until the window is closed.(Introduced with Silverlight 3).  

Create Sample Application

1. First create a new silverlight application and named it as SilverlightChildWindow.
2. Right Click on silverlight project and add a new ChildWindow from Add New Item dialog.

3. Now we will design our MainPage.xaml layout as below.
<UserControl x:Class="SilverlightChildWindow.MainPage"
    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"
    d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="40"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <TextBlock x:Name="lblInfo" Margin="10" FontSize="13" TextWrapping="Wrap">
            Please Enter your user information.
        </TextBlock>
        <Button Content="Enter Your Information" Height="23" Grid.Row="1" HorizontalAlignment="Left" Margin="10,10,0,0" Name="button1" VerticalAlignment="Top" Width="150" Click="button1_Click"  />
    </Grid>
</UserControl>

4. After that we will design our ChildWinodw.xaml page as below.
<controls:ChildWindow x:Class="SilverlightChildWindow.ChildWindow1"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"           
           Title="ChildWindow1">
    <Grid x:Name="LayoutRoot" Margin="2">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        
        <TextBlock Grid.Row="0" Grid.Column="0" Margin="3">First Name:</TextBlock>
        <TextBox  x:Name="txtFirstName" Grid.Row="0" Grid.Column="1" Margin="3" Width="150"></TextBox>
        <TextBlock Grid.Row="1" Grid.Column="0" Margin="3">Last Name:</TextBlock>
        <TextBox  x:Name="txtLastName" Grid.Row="1" Grid.Column="1" Margin="3" Width="150"></TextBox>


        <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Left" Margin="3" Grid.Row="2" Grid.Column="1" />
        <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="3" Grid.Row="2" />
    </Grid>
</controls:ChildWindow>

5 . To show a Child Window, we need to create an object of the child window and call its Show() method. Here the Show()  method act as as asynchronous call and it returns immediately, since that we will not get the result from the dialog using this method. So we need to implement the Closed event from the Child Window and check the DialogResult there. So we will implement this in MainPage.xaml.cs page.
using System;
using System.Windows;
using System.Windows.Controls;

namespace SilverlightChildWindow
{
    public partial class MainPage : UserControl
    {
        private ChildWindow1 childWindow = new ChildWindow1();

        public MainPage()
        {
            InitializeComponent();
            childWindow.Closed += new EventHandler(childWindow_Closed);
        }

        void childWindow_Closed(object sender, EventArgs e)
        {
            if (childWindow.DialogResult == true)
            {
                lblInfo.Text ="Hi " +childWindow.UserName+",";
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            childWindow.Show();
        }
    }
}

6. Also we need to add property to ChildWindow.xaml.cs.
using System.Windows;
using System.Windows.Controls;

namespace SilverlightChildWindow
{
    public partial class ChildWindow1 : ChildWindow
    {
        public ChildWindow1()
        {
            InitializeComponent();
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        public string UserName
        {
            get { return txtFirstName.Text + " " + txtLastName.Text; }
        }
    }
}

7 . Now you can Run the application and if everything work fine you will get following type pop up after you click on button.

Download source Code Here.