MVVM in real life Windows Phone applications Part2
published on: 7/27/2011 | Views: N/A | Tags: MVVM Mango
by WindowsPhoneGeek
This article is Part2 from the "MVVM in real life Windows Phone applications " series where I talk about using MVVM in real life Windows Phone applications:
- MVVM in real life Windows Phone applications Part1
- MVVM in real life Windows Phone applications Part2
NOTE: You can take a look at our previous post: Windows Phone Mango: Getting Started with MVVM in 10 Minutes for reference.
NOTE: For more information about the DelegateCcommand take a look at our previous post Building a Reusable ICommand implementation for Windows Phone Mango MVVM apps
In Part1 of this article we started implementing a real life MVVM application by implementing the following components:
- a ViewModelBase class that contains an INotifyPropertyChanged implementation and other common functionality
- SimplePersonRepository which implements the IPersonRepositoryInterface
- PersonViewModel in which we dropped a hint at how the INavigationService interface will be used
In this post we will finish the initial implementation of our real-life MVVM Windows Phone application.
Previously in Step4 we mentioned the INavigationService interface:
public interface INavigationService
{
void Navigate(string uri);
void Navigate(string uri, IDictionary<string, string> parameters);
}
So the next step is to implement this interface.
Step5: SimpleNavigationService implementation
SimpleNavigationService is, as the class name suggests, a simple implementation of the INavigationService interface. Here, a PhoneApplicationFrame instance is obtained from the Application.Current.RootVisual. Next, an uri is built from the page uri and query parameters passed to the Navigate method. Finally the Navigate method of the PhoneNavigationFrame is used to actually navigate to the desired page.
public class SimpleNavigationService : INavigationService
{
public void Navigate(string uri)
{
this.Navigate(uri, null);
}
public void Navigate(string uri, IDictionary<string, string> parameters)
{
PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
if (frame == null)
{
return;
}
StringBuilder uriBuilder = new StringBuilder();
uriBuilder.Append(uri);
if (parameters != null && parameters.Count > 0)
{
uriBuilder.Append("?");
bool prependAmp = false;
foreach (KeyValuePair<string, string> parameterPair in parameters)
{
if (prependAmp)
{
uriBuilder.Append("&");
}
uriBuilder.AppendFormat("{0}={1}", parameterPair.Key, parameterPair.Value);
prependAmp = true;
}
}
uri = uriBuilder.ToString();
frame.Navigate(new Uri(uri, UriKind.RelativeOrAbsolute));
}
}
Step6: Implementing EditPersonPage
This is the second view in our application, which will be used to edit a person object.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Orientation="Vertical">
<TextBlock Text="Name:"/>
<TextBox Text="{Binding SelectedName}" />
<TextBlock Text="Age:"/>
<TextBox Text="{Binding SelectedAge, Mode=TwoWay}" />
<Button Content="Save Changes" Command="{Binding SaveChangesCommand}" />
</StackPanel>
</Grid>
Step7: PageBase class
We will add a new PageBase class which will be the base class for all pages in our application. Basically it overrides the OnNavigatedTo() method and calls the Initialize method of the view model which is set as the DataContext of the current page. The query string parameters from the uri which was used to navigate to the page, are passed as a parameter of the Initialize method.
public abstract class PageBase : PhoneApplicationPage
{
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ViewModelBase viewModel = this.DataContext as ViewModelBase;
viewModel.Initialize(this.NavigationContext.QueryString);
}
}
Step8: EditPersonViewModel implementation
Just to remind you, in the PersonViewModel class, when we navigate to the EditPage, the ID of the person that we want to edit is passed as a parameter of the navigation:
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add(Person.IdParameterKey, person.ID.ToString());
navigationService.Navigate("/Views/EditPersonPage.xaml", parameters);
As a result of the navigationService.Navigate(.) call, a navigation to the EditPerson page is performed. Then the OnNavigatedTo method is called(which is overridden in the PageBase class). From there, the Initialize method of the EditPersonViewModel is called. Note that in the "parameters" collection we expect to receive the person ID that we have previously coded in the navigation uri.
This ID is used in order to find the Person object which is to be edited. We use it with the GetPersonByID method of IPersonRepository in order to receive the Person object which is to be edited.
public class EditPersonViewModel : ViewModelBase
{
private string name;
private int age;
private Person selectedPerson;
private ICommand saveChangesCommand;
public EditPersonViewModel()
{
this.saveChangesCommand = new DelegateCommand(this.SaveChangesAction);
}
public override void Initialize(IDictionary<string, string> parameters)
{
base.Initialize(parameters);
if (parameters == null)
{
return;
}
string idString = null;
if (!parameters.TryGetValue(Person.IdParameterKey, out idString))
{
return;
}
int personId = -1;
int.TryParse(idString, out personId);
if (personId != -1)
{
IPersonRepository personRepository = this.GetService<IPersonRepository>();
if (personRepository != null)
{
this.SelectedPerson = personRepository.GetPersonByID(personId);
}
}
}
private void SaveChangesAction(object p)
{
if (this.SelectedPerson != null)
{
this.SelectedPerson.Name = this.name;
this.SelectedPerson.Age = this.age;
}
INavigationService navigationService = this.GetService<INavigationService>();
if (navigationService != null)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add(Person.IdParameterKey, this.SelectedPerson.ID.ToString());
navigationService.Navigate("/Views/MainPage.xaml", parameters);
}
}
public ICommand SaveChangesCommand
{
get
{
return this.saveChangesCommand;
}
}
public string SelectedName
{
get
{
if (this.SelectedPerson != null)
{
return this.SelectedPerson.Name;
}
return string.Empty;
}
set
{
this.name = value;
}
}
public int SelectedAge
{
get
{
if (this.SelectedPerson != null)
{
return this.SelectedPerson.Age;
}
return 0;
}
set
{
this.age = value;
}
}
public Person SelectedPerson
{
get
{
return this.selectedPerson;
}
set
{
if (this.selectedPerson != value)
{
this.selectedPerson = value;
if (this.selectedPerson != null)
{
this.name = this.selectedPerson.Name;
this.age = this.selectedPerson.Age;
}
this.RaisePropertyChanged("SelectedName");
this.RaisePropertyChanged("SelectedAge");
}
}
}
}
Finally, when the Save button is pressed we navigate back to the MainPage and again we pass as a parameter the ID of the edited Person object. This is done so that we know that we are navigating back from the edit page and load the data into the list, so that it seems to the user that he has returned to the same page.
Here is how the final structure of our MVVM application should look like:
That was all about "MVVM in real life Windows Phone applications ". Here is the full source code of the project:
I hope that the article was helpful.
You can also follow us on Twitter @winphonegeek
Comments
Our Top Articles & Free books
- Our FREE e-book: "Windows Phone Toolkit In Depth" 2nd edition
- 400+ Windows Phone Development articles in our Article Index
- 21 WP7 Toolkit in Depth articles covering all controls
- 12 WP7 Coding4Fun Toolkit in Depth articles covering all controls
- Performance Tips when creating WP7 apps
- Creating a WP7 Custom Control in 7 Steps
- WP7 working with VisualStates: How to make a ToggleSwitch from CheckBox
- What makes a WP7 App successful
- Creating theme friendly UI in WP7 using OpacityMask
- Implementing Windows Phone 7 DataTemplateSelector and CustomDataTemplateSelector
- All about Splash Screens in WP7 – Creating animated Splash Screen
- Getting Started with Unit Testing in Silverlight for WP7
- WP7 WatermarkedTextBox custom control
Our Top Tips & Samples
- All about WP7 Isolated Storage series
- WP7 Dynamically Generating DataTemplate in code
- 5 tips for a successful WP7 Marketplace submission
- WP7: Navigating to a page in different assembly
- WP7 ContextMenu: answers to popular questions
- WP7 ListBox: answers to popular questions
- WP7 working with Images: Content vs Resource build action
- WP7 Element Binding samples
- WP7 working with XML: reading, filtering and databinding
- Drawing in WP7: #2 Drawing shapes with finger
- WP7 TextBox Light theme problems - the solution
- Changing the WP7 Panorama Background Image dynamically with Animation
