Bending HotTowel.AngularJS to Your Will–SubNavs

19. November 2013

Today I was very excited about getting something to work with HotTowel.Angular.  I tweeted my glee to the author then folks asked how I did it.  So, I threw a demo app together.  it turned out to have a bunch of code changes so a blog seemed the best way to communicate.  (It wasn’t so simple to put on Plunker)  Hopefully this will help someone.

What is it?

HotTowel.Angular is the very well put together project template by John Papa.  It is a SPA (Single Page Application) web package that brings together AngularJS, Twitter.Bootstrap, FontAwesome, jQuery, Moment, toastr, and Spin.  There is a ReadMe up at the Git project here.  It is also available from NuGet here.  There is a set of video tutorials available from PluralSight as well.  John Papa’s blog post is available for more detail here.

All in all, it is a fantastic starting point for trying out AngularJS and a well architected project.

Where’s the sample app download?

Here is the source code to the sample app => skydrive.  Click that link and then choose to download the zip.  The code is provided “AS IS” so if you find it doesn’t run using Visual Studio 2012, try recreating it yourself by just looking at the code.  There are a few files that were edited from the original NuGet package.  Only enough changes were made to demonstrate the concept.

What does the demo do?

Well, here is a screen shot of the finished running web app.  This is showing tab 1 selected within the admin page.  The url showing in the browser address is actually derived from a route.  The templateUrl is pointing to an html file called tab1.html that is in a subfolder of the admin folder.  The subfolder is called tab1.  The tab1.html could be elsewhere and doesn’t have a naming convention requirement. 

Tab1Page

When the user clicks on “Tab Two”, the route location is changed and the partial, tab2.html, is loaded.  Both the main navigation and the sub-navigation controls are selected based on a combination of the selected route and a property value matched up in code.

How did you do it?

The idea came about while trying to solve this very problem.  Initially, I didn’t think there was a way to get a second navigation level in HotTowel.Angular without adding a different route framework.  But with a little trial and error, some dependency injection, and bug fixes it worked out.  It took me a lot longer the first time through.  Putting this demo together didn’t take more than half an hour.  (Writing a blog post on the other hand…)

Step 1 – Install HotTowel.Angular in a new Web Site Project

Open up Visual Studio 2012 (or 2013).  Go to File/New/Web Site to create a blank web site solution and project.  With NuGet and the Package Manager Console set up, go ahead and install the NuGet Package:

Install-Package HotTowel.Angular

Run the app to make sure everything is good.  You should see the awesome HotTowel SPA.

Here is a summary of my code changes and files that were edited (not necessarily in this order):

1. Coped app/layout/sidebar.js and app/layout/sidebar.html to new files in the same folder.

2. Named the new files as subnavsidebar.js and subnavsidebar.html.

3. Changed the subnavsidebar.html to use the twitter bootstrap tabs for a horizontal nav menu.

4. Changed the subnavsidebar.js so the filter logic tests for a property on the route config object called “type”.  Routes are set up in the file app/config/route.js.  Adding a type property is as easy as typing it and assigning a value.

5. Added a bit of logic to fix the url used for navigating between subnavs.  The routeParam of someobjectid replaced the placeholder set up in the route config.

6. Go into app/common/common.js and inject $location.  Then make it public just like $timeout.  This is used in the view model (or controller) of the admin view to allow navigation between the two tabs.

7. The routes for tab1 and tab2 are added in the file app/config/route.js.  For all the routes I added a type property.  I set value of the type property in the parent navs to ‘parentNav’ and the sub-navs to ‘subNav’.  The url for the two tab routes has that ‘someobjectid’ route parameter in it.  In a real application, this could be the id of a data object.  You could also use more than one and in different orders.  (Something I haven’t tried yet).  The other property added is parentTitle.  That allows code in app/layout/sidebar.js to select the parent nav item while on the detail pages.  It gives a visual cue to the user to know where they are in the application.

8. Next, the admin.html and admin.js have buttons added.  When the user selects the admin nav menu item, the admin page appears.  The two buttons let the user jump to a detail tab.  This is probably not the most ideal UX but it demonstrates the idea.  In a real application the user might want to see the first tab by default.

AdminPage

9. In the admin.js, or the view model, two methods were added to respond to the button clicks.  This is where common.$location gets used to change the path.

10. There is also an input field on the admin page.  This gets concatenated into the route path and becomes the someobjectid route parameter.  For this view, the input is bound to the view model property someObject. Or vm.someObject.  So basically, you can type in the text ‘notimetocodemustplayxbox’ it will show up in the url when you click one of the buttons.

11. The folders and files for the tabs were created next.  The view models don’t do much other than initialize the view.  There is an ng-include on each of the pages for /app/layout/subnavsidebar.html.  This is the navigation controls for the sub-pages.  The current tab is selected based on the logic in /app/layout/subnavsidebar.js.

12. To make all this work, the JavaScript files for the subnavsidebar, tab1, and tab2 had to be linked to in the index.html file.  (I’m getting better at catching myself before I run an angularjs app to check for these.)

Summary

So, this isn’t a very technical step by step but the source code is provided to cover anything missing.  There is at least one bug with this approach that I found.  When you select a tab from the admin screen, click the other tab, then click on the admin parent nav, then change the object id in the input field, then click on one of the tabs….whew!…. when you click on the other tab the route isn’t correct.  The route param uses a cached parameter value.  I’ll be looking into this for a solution.  If you find one drop me a comment.

As I said before, I really enjoy working with this template and AngularJS.  Given my Silverlight, and WPF data-binding experience AngularJS provides a familiar solution to that tangled thing that is HTML  Now that AngularJS is here to help with things on the client side, web development is better for it. (My two cents)

 

Creating a network shared Git source control workflow on Windows 8

6. October 2012

This post is mainly for my reference but in case someone sees it I hope it is helpful.  The source links are referenced for more information and to credit the original authors of this technique.

(Assumes Git is installed correctly for Windows 8)

sources: 

 http://tendrid.blogspot.com/2011/03/svn-users-tale-of-git-learning-curve.html
 http://elegantcode.com/2011/06/18/git-on-windows-creating-a-network-shared-central-repository/

 

 

1. Create a local directory for source code

 - something like "C:\code\"

2. Open a command prompt from the new local folder

 - Right click on the folder while holding down the shift key and "Open Command Prompt Here"

3. At the client folder path, type "pushd //networkdrivefolder/sourceCode/", where the path is one level above where you will create the origin folder.

 - "pushd" will map a network drive to the network share location.

4. At the network drive folder path, type "mkdir repo", where repo is the name of the folder.

5. At the network drive folder path, type "cd repo".

6. At the network drive folder path, now showing the repo folder, type "git init".

 - This will create an empty master branch.

7. Create a new file, type "touch readme".

8. Add the file to the repository, type "git add *".

9. Commit the file to the repository, type "git commit -a -m "first commit".

10. Create a separate branch from master to work in, type "git branch dev", where dev is the name given to the branch

11. Type "popd" in the command prompt to return to the local directory.

 - "popd" will navigate back and will remove the network share the pushd command created above.

12. Type "git.exe clone   --progress -v  '//networkdrivefolder/sourceCode/repo' 'C:\code\repo'" at the command prompt to clone the network share repo to a local folder named repo.

13. At the local directory folder path, type "git branch dev", where dev is the branch name created above.

14. At the local directory folder path, type "git checkout dev" to pull files from the network repo.

 

At this point, you have a full working copy of the git repo on your machine in which you have created and started work in the dev branch.

 

Code

Building Blocks for Designer Friendly Windows Phone Code

15. June 2011

Last night at PDXSLUG I was able to talk about some easy to use building blocks for design-time data friendly Windows Phone projects.  The main benefit of the approach is that you do not have to press F5 all the time.  Instead there is visible sample data in the design surfaces of Visual Studio 2010 and Expression Blend 4.  This isn’t “Lorem Ipsum” generated xml sample data.  The actual code you write for design time data is exercised at design time.  It is a visual test of that code as well. 

The time saving act of making changes without waiting for the emulator or browser to startup translates directly into making a better application.  You can use this technique for one or a collection of model objects, results from a design time web service, and even images.  The example is small but using some simple building blocks like MVVM Light and MicroIoC it can scale nicely.  It works for Silverlight as well as WP7 projects with little change.  By going through the steps of making the designers display sample data, I know that I’m making my applications more maintainable, and I’m not going to waste time waiting to see if layout changes work at run time. 

Here is the point: Count the developers you have on a UI project and multiply that by a minimum of 1 minute every time someone needs to press F5.  That is time that could be used for actually adding new features, making existing features better, or fixing important bugs.

Read more about all of this in my blog series on the same subject.  Here is a quick set of links:

Blog Series Part 1

MVVM Light 

MicroIoC 

Bindable App Bar 

Container singleton pattern 

App Hub 

The completed source code from the talk is available in Part 6 of the blog series.

My Windows Phone 7 Applications in the Marketplace

8. March 2011

Update (4/26/2012): New links direct to the Windows Phone Marketplace

These are the applications that I have in the marketplace. I have updates to these in the works with more applications to deploy to the marketplace too! If enough people purchase Airport Info I’ll add more features. An update is on the way regardless. Video School is very similar to an application called Khan Academy. It too will have improvements but decide for yourself if you like it or the competing application. Video School is a free app.

 

http://windowsphone.com/s?appId=b37a913d-8f05-e011-9264-00237de2db9e

image

 

http://windowsphone.com/s?appId=42f42f30-840c-e011-9264-00237de2db9e

image

WP7

Using Social Networks to Build Reusable Architecture for the Windows Phone 7 – Part VI

8. March 2011

 

Part I
Part II
Part III
Part IV
Part V
Part VI

This is the sixth and final installment of a several part series/journey to use social network resources for Windows Phone 7 development and produce a reusable code base.

What Has Come Before

In Part I the idea of going to social media for Windows Phone 7 research was introduced and we started putting together a solution with Visual Studio Express for Windows Phone 7.  In Part II we took the great leap forward and added the MVVM pattern and IoC pattern to the solution.  In Part III the Silverlight Toolkit controls, Coding4Fun controls, Bindable ApplicationBar control, and other Silverlight behaviors and actions were added.  In Part IV, we found a web service to get random quotes and hooked up the design time data using Assembly.Load to avoid referencing the Design project in our main phone application.  Finally, in Part V, we did some nice refactoring, added a custom page navigation solution to MVVM, added an About page, and implemented a bindable ApplicationBar control.

The application that was built gets random quotes from a public web service as JSON formatted data.  It displays the quote on the Main page.  A refresh button on the ApplicationBar will go get a new random quote.  The user can also navigate to an About page and the use the hardware back button on the phone to get to the Main page.

The final task for this blog post is to talk about how to use simple copy/paste/rename techniques to be able to reuse the solution for other project.  It is possible to export individual projects as project templates.  It is not as easy to do this for a whole solution.  So instead a somewhat more manual and tedious process can be used. 

Note: This entire series of articles was based on using the free development tools.  Renaming and refactoring code is easier using the professional versions of Visual Studio 2010.  There is also a nice refactoring extension for Visual Studio 2010 Professional (or higher) called ReSharper.

Copy / Paste / Rename / Refactor / Reuse

The first thing to do is make a copy of the solution folder from Windows Explorer.  This copied source code will be used for each separate project.  The process when starting a new project with this source is:

1. Copy the solution source code folder using Windows Explorer
2. Name the new solution folder as the name of your project.  For example, if you want to build a Silverlight Windows Phone application called, maybe, “Weather Report” you would name the solution folder “WeatherReportSolution”.  Again, this is from Windows Explorer and not from within Visual Studio.

3. Open the solution and rename/refactor as needed to use the project name desired.  “WeatherReport” as in the example above.

4. Compile and test to locate other items that require renaming.

Before continuing on it is a good idea to copy the solution folder and save it in a backup location.  A good reference article on MSDN for what needs to be done can be found here: How to: Rename Solutions, Projects, and Items.

Without further ado, we simply follow those directions to rename the solution.  This application will be called “RandomQuoter”. We rename the solution WindowsPhoneApplication1 to RandomQuoterSolution, the WindowsPhoneApplication1 project to RandomQuoter, the WindowsPhoneApplication1.Design project to RandomQuoter.Design, the WindowsPhoneApplication1.Shared project to RandomQuoter.Shared, and then update the namespaces within each project property editors.

image

If you follow the step to rename projects through the Solution Explorer the project references will also update properly.  Make sure to manually change the Assembly name and Default namespace in WindowsPhoneApplication1, WindowsPhoneApplication1.Design, and WindowsPhoneApplication1.Shared.  Once the projects and solution are renamed correctly compile the application and fix any errors.  There should not be any if it was done correctly. 

The next step is to do a Replace in Files operation on the entire solution.  This can be a tricky operation without a good way to undo it.  So avoid typos in the Replace in Files fields.  The image below has the settings to use for this Replace operation:

image

Fill in the fields as pictured above and click Replace All.  You are given a choice to open all files affected and therefore have a way to undo the changes.

image

Now build the solution again to find any errors and correct them.  The build should succeed with all the XAML and code using the corrected namespaces.

Now we go back to the main phone application properties dialog and see that the xap file still shows the startup xap is pointing to WindowsPhoneApplication1.xap:

image

This needs to be fixed from outside of Visual Studio.  Note too that the folder structure is not renamed in this process.  Folders in Windows Explorer still have names with WindowsPhoneApplication1 in it.  Also, because of this, the solution file itself will be pointing to these folders.  These must be updated manually.

We save all the changes and close the solution in Visual Studio, or close Visual Studio entirely.  First up, the folder name change.  Change all the project folders within the solution folder to use the new project name.

image

From the above image to the names displayed in the image below.

image

Now use Notepad to update the folder paths within the solution file.  This will be the .sln file located at the root of the solution folder.  Once it is opened in Notepad (or Notepad2 pictured below) the task is a simple string replace.  Replace the string “WindowsPhoneApplication1” with “RandomQuoter”.  Save the file and this round of renaming is complete.

image

Now open the solution up in Visual Studio and locater the properties window for the RandomQuoter project.  You will see that the startup object is blank.  Select the RandomQuoter.xap item from the drop down list and recompile the solution.

image

The refactor and renaming steps are complete.  Test that the application runs correctly using the Emulator. 

With practice, this process can take as little as 5 minutes.

Summary

That is it!  I hope you enjoyed reading through the series or that you found this post and the source code useful.  There are many different approaches for the patterns used in the code, MVVM, IoC, and so on.  Investigate and improve at your leisure.  There are daily updates to the open source projects discussed here so be vigilant and check the authors blogs, twitter, and project sites for updates.  Windows Phone 7 Development, I have found, is based on a strong community so whenever possible share with people on twitter and use the #wp7dev hash tag.  Your applications will get better as a result of participating in this vibrant community.

 

Source Code

Code, Silverlight, WP7

Using Social Networks to Build Reusable Architecture for the Windows Phone 7 – Part V

28. February 2011

 

Part I
Part II
Part III
Part IV
Part V

 

This is the fifth installment of a several part series/journey to use social network resources for Windows Phone 7 development and produce a reusable code base.

In this post, we’re going to discuss how to enhance a sample provided by Laurent Bugnion for Navigation using MVVM Light.  The goal is to create a custom PageNavigation object like the MVVM Light navigation service code.  Then we refactor some things to make it easy to use.  Finally, we add an about page, a way to get to it, and a refresh quotation button.

This requires a refactoring and some architecture changes.

 

Refactoring

As you can read in Laurent’s blog posting, there is an interface and class for a navigation service.  In this implementation of it we change the name slightly from NavigationService to PageNavigation.  We want to be able to pass an object context as well as (or instead of) a Url.  Because each ViewModel will have a need for a PageNavigation object we move the code to a single location that can be inherited from.  To a custom ViewModelBase class. The new class is located in the ViewModels folder and MainViewModel is updated to inherit from it instead of directly to the MVVM Light version.

ViewModelBase.cs
using WindowsPhone.Helpers.Navigation; namespace WindowsPhoneApplication1.ViewModels { public class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase { private object context; public object Context { get { return context; } set { if (context == value) return; context = value; RaisePropertyChanged("Context"); } } /// <summary> /// Gets PageNavigation from Container /// </summary> public IPageNavigation PageNav { get { IPageNavigation pageNav = (IPageNavigation)Container.Instance.Resolve(typeof(PageNavigation), "PageNavigation"); return pageNav; } } } }

 

Moving the IoC for Easy Access

This all means that we have to move the container from a class variable in the ViewModelLocator into a singleton class of its own.  The line of code in ViewModelLocator is removed and the new class is added.  We locate the new container singleton in the ViewModels folder of my main project.  Here is a link to a nice explanation of the singleton: http://www.yoda.arachsys.com/csharp/singleton.html.

So, this line in ViewModelLocator.cs….

private readonly IMicroIocContainer container = new MicroIocContainer();

…turns into this class:

Container.cs
using MicroIoc; namespace WindowsPhoneApplication1.ViewModels { public sealed class Container { Container() { } public static IMicroIocContainer Instance { get { return Nested.instance; } } class Nested { // Explicit static constructor to tell C# compiler // not to mark type as before field init static Nested() { } internal static readonly IMicroIocContainer instance = new MicroIocContainer(); } } }

Now the ViewModelLocator has to be refactored to use Container.Instance.RegisterInstance instead of container.Register.

PageNavigation

The next thing is to add the new IPageNavigation interface.  It has one more property than the one the MVVM Light demo article used.  Because we want a context to pass through during page navigation, we add a property to contain an object and a method to pass it in.  The final interface is below.

IPageNavigation.cs
using System; using System.Windows.Navigation; namespace WindowsPhone.Helpers.Navigation { public interface IPageNavigation { event NavigatingCancelEventHandler Navigating; object CurrentContext { get; } void NavigateTo(Uri pageUri); void NavigateTo(Uri pageUri, object context); void GoBack(); } }

 

The implementation of PageNavigation is almost identical to Laurent’s.  With the exception of the additional method and context property.

PageNavigation.cs
using System; using System.Windows; using System.Windows.Navigation; using Microsoft.Phone.Controls; namespace WindowsPhone.Helpers.Navigation { public class PageNavigation : IPageNavigation { private PhoneApplicationFrame mainFrame; private bool EnsureMainFrame() { if (mainFrame != null) { return true; } mainFrame = Application.Current.RootVisual as PhoneApplicationFrame; if (mainFrame != null) { // Could be null if the app runs inside a design tool mainFrame.Navigating += (s, e) => { if (Navigating != null) { Navigating(s, e); } }; return true; } return false; } public event NavigatingCancelEventHandler Navigating; private object currentContext; public object CurrentContext { get { return this.currentContext; } } public void NavigateTo(Uri pageUri) { if (pageUri == null) throw new ArgumentNullException("uri"); if (EnsureMainFrame()) this.NavigateTo(pageUri, null); } public void NavigateTo(Uri pageUri, object context) { if (pageUri == null) throw new ArgumentNullException("uri"); if (EnsureMainFrame()) { this.currentContext = context; mainFrame.Navigate(pageUri); } } public void GoBack() { if (EnsureMainFrame() && mainFrame.CanGoBack) { mainFrame.GoBack(); } } } }

The ViewModelLocator now needs to register IPageNavigation so that the custom ViewModelBase (which is explained next) can resolve it.  Because page navigation doesn’t occur in design mode it only needs to be registered if not in design mode.  The line of code is this:

//Register PageNavigation - only if not design time Container.Instance.RegisterInstance(typeof(PageNavigation), "PageNavigation");

ViewModelBase

A custom ViewModelBase needs to be created.  MVVM Light already includes a ViewModelBase class.  So we create a new class that inherits it.  It needs one property with get access only for the PageNavigation.  The property returns the resolved IPageNavigation object from the container.  Later you will see how the context is assigned.  We also want a property in every ViewModel to hold the context for the ViewModel.  This is helpful for Tombstoning (which is out of scope for this blog series).  But the mechanism is in place for Tombstoning our context later.  The new ViewModelBase.cs gets created in the ViewModels folder of the main project.  It looks like this.

ViewModelBase.cs
using WindowsPhone.Helpers.Navigation; namespace WindowsPhoneApplication1.ViewModels { public class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase { private object context; public object Context { get { return context; } set { if (context == value) return; context = value; RaisePropertyChanged("Context"); } } /// <summary> /// Gets PageNavigation from Container /// </summary> public IPageNavigation PageNav { get { IPageNavigation pageNav = (IPageNavigation)Container.Instance.Resolve(typeof(PageNavigation), "PageNavigation"); return pageNav; } } } }

This new base class needs to be implemented on the MainViewModel as follows.

public class MainViewModel : WindowsPhoneApplication1.ViewModels.ViewModelBase, IMainViewModel

Passing the Context in VIewModelLocator

Context is all set up to pass through during navigation from one page to the next.  Except for one last step.  The “magic” that this architecture relies on is the timing in construction of any ViewModel.  When a page is navigated to, the View binds to the ViewModel it needs using the ViewModelLocator public properties.  Each time a View is navigated to.  So, if PageNavigation is given a context object to carry just before navigation begins, at the time the ViewModel is constructed it can be handed that context.  Remembering the GetViewModel method in ViewModelLocator, it is easy to conclude that transfer of the context happens in there.  Also remember that the ViewModel base has a context property.  We can simply assign context from PageNavigation to that property if it is null or not.  While it may be tempting to use the CurrentContext of the PageNavigation as the context of any ViewModel, it would be unwise to do so.  That property is guaranteed to change or be null when navigating from one View to the next.  The intent is to rely on the ViewModelBase.Context property instead.  As each ViewModel is created and context is set, the ViewModel can control any logic it needs on the property changed event of its context.  The new code becomes as follows:

private T GetViewModel<T>() where T : ViewModelBase { // Create a new view model T vm = Container.Instance.Resolve<T>(); //Assign the Context from PageNavigation to Context property of the ViewModelBase vm.Context = vm.PageNav.CurrentContext; return vm; }

About Page Setup

There are a few steps now to creating new pages.  The main architecture is updated to make this a fairly consistent but definitely a manual process.  The general steps are 1. create an interface for the new view model, 2. create the view model, 3. implement the interface on the view model, 4. copy the view model to the design project, 5. register the view model in the IoC container (both for production and design modes), 6. expose a property in the locator to resolve the view model, and 7. create a view bound to the locator view model.  That is fairly close to the MVVM Light steps to creating a view.  The IoC register/resolve and design project steps are extra.

The solution should look something like the following when done.  Full source code is available to download so you can take a closer look.

image

Here is what we do for the Design version of the AboutViewModel.  Note that we don’t need to care about context or page navigation yet so these view models don’t yet inherit the custom ViewModelBase.

AboutViewModel.cs
using GalaSoft.MvvmLight; using WindowsPhoneApplication1.Shared.ViewModels; namespace WindowsPhoneApplication1.Design.ViewModels { /// <summary> /// This class contains properties that a View can data bind to. /// <para> /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel. /// </para> /// <para> /// You can also use Blend to data bind with the tool's support. /// </para> /// <para> /// See http://www.galasoft.ch/mvvm/getstarted /// </para> /// </summary> public class AboutViewModel : ViewModelBase, IAboutViewModel { /// <summary> /// Initializes a new instance of the MainViewModel class. /// </summary> public AboutViewModel() { } ////public override void Cleanup() ////{ //// // Clean own resources if needed //// base.Cleanup(); ////} private string aboutText = "This is design time about text"; public string AboutText { get { return aboutText; } set { if (aboutText == value) return; aboutText = value; RaisePropertyChanged("AboutText"); } } } }

 

Using the Custom Application Bar with MVVM Light

In Part III of this series, you read about using MVVM Light with a bindable ApplicationBar control. The reference article is here.  In that post we added the control to the WindowsPhone.Controls project.  The other piece of a puzzle that we’ll put together here has to do with the MVVM Light RelayCommand.  There is a good background article about that here.  The goal is to implement the bindable ApplicationBar control with commands in the MainViewModel to navigate to the AboutView and to refresh the quote by calling the web service.

Let’s set up the commands in the MainViewModel.  We need a public property for both commands.  The type for the command properties is ICommand, which is available from System.Windows.Input.  Here they are:

public ICommand NavigateToAboutCommand { get; private set; }
public ICommand GetRandomQuoteCommand { get; private set; }

These commands are going to be assigned to the click events on the application bar button and menu item.  That is all the View is going to bind to.  Within the ViewModel, we can assign a RelayCommand to these properties that takes a method for an action to perform.  That is done immediately when the ViewModel is constructed.  So the constructor for MainViewModel looks like this:

public MainViewModel() { NavigateToAboutCommand = new RelayCommand(() => NavigateToAbout()); GetRandomQuoteCommand = new RelayCommand(() => this.GetRandomQuote()); }

Note that this is not needed in the Design copy of MainViewModel because we won’t be able to perform a click action at design time.  So we can see that the ICommand bound to the About menu item will invoke a method called NavigateToAbout.  That method uses the PageNav object from the ViewModelBase to go to the relative Url for the AboutView.  It looks like this:

private void NavigateToAbout() { this.PageNav.NavigateTo(new Uri("/Views/AboutView.xaml", UriKind.Relative)); }

We already had some code to get the random quote so it’s easy to assign that to the command.  There is going to be a refresh button and a menu item with “about” as the text.  So, we need an application bar button image for refresh.  You can find some pre-made icons for the application bar in the Windows Phone SDK folder.  It should be in a path similar to the following: C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Icons.  There is a dark, light, and vector folder in there.  We typically want to use the dark icons and specifically the png format.  We create a folder in the main phone project and call it “images” to store a copy of the icon for refresh.  There is one critical setting we set in the properties window for the file.  The Build Action for application bar icons must be set to Content for the icon to appear correctly.  The solution and properties windows will look like this:

image

Implementing the application bar requires another important step.  Because the control is in a separate project, we need an xml namespace reference in the XAML for MainView.xaml.  The references section requires the following reference:

xmlns:wp7ControlsAppBar="clr-namespace:WindowsPhone.Controls.AppBar;assembly=WindowsPhone.Controls"

Then within the main content control of the PhoneApplicationPage, or the view, we need that application bar.

<wp7ControlsAppBar:BindableApplicationBar x:Name="AppBar" BarOpacity="1.0"> <wp7ControlsAppBar:BindableApplicationBarIconButton Command="{Binding GetRandomQuoteCommand}" Text="get quote" IconUri="/images/appbar.sync.rest.png" /> <wp7ControlsAppBar:BindableApplicationBar.MenuItems> <wp7ControlsAppBar:BindableApplicationBarMenuItem Text="about" Command="{Binding NavigateToAboutCommand}" /> </wp7ControlsAppBar:BindableApplicationBar.MenuItems> </wp7ControlsAppBar:BindableApplicationBar>

You can see in the XAML above that there is a button and a menu item.  The button has a Command property bound to GetRandomQuoteCommand from MainViewModel.  The menu item has a Command property bound to NavigateToAboutCommand.  The default event for each, the click, will invoke the action assigned to those commands in the MainViewModel.  There is no code in the MainView.xaml.cs, the code behind for MainView.xaml.  The out of the box ApplicationBar for Windows Phone 7 would require code for click events in the code behind of the view.  This control wrapper saved us from breaking the MVVM pattern.

 

Summary

The application is done from a functional point of view.  There could be some design improvements at this point.  Because this isn’t a series about design for the phone we can simply refer to the Design Resources for Windows Phone.  In the next and final post, we’ll go over how to turn this solution into a manageable “template”.  Then we can start writing high quality Windows Phone 7 applications!

 

Source Code

Code, Silverlight, WP7

Using Social Networks to Build Reusable Architecture for the Windows Phone 7 – Part IV

24. February 2011


Part I
Part II
Part III
Part IV

This is the fourth installment of a several part series/journey to use social network resources for Windows Phone 7 development and produce a reusable code base.

 

Using the Web to Find Data

There are great how-to articles about consuming data in your Windows Phone applications.  You can find some of them using the Reddit.com site.  For example, navigate to Reddit.com and in the search field enter a search like, “wp7dev web services”.  Among the results might be a link to the MSDN article, “Connecting to Web and Data Services for Windows Phone”.

On Create.MSDN.com there is a quick start tutorial that uses the Bing Search API.  It can be found here.  You can search through the site for other examples and tutorials.  Like many web service APIs, the Bing Search API requires a key to use it.  This tutorial will help you understand  how to consume a web service that doesn’t require a key.

After doing a some web research you might find a web service like this one located at http://www.iheartquotes.com/.  The service returns random quotes.  The site explains how to use the web service on its API page.  Developers can request one of several formats such as text, JSON, or HTML.  There are also a bunch of sources to get quotes from like starwars and hitchikersguide.  Here is the link we will use in this application: http://www.iheartquotes.com/api/v1/random?source=oneliners.   If you navigate to the link directly, you will get back text data by default.  Because we want to get JSON formatted data we add the parameter format=json to the end of the Url.  Each time the service returns it returns a new random quote with this same structure.  So, this is perfect.

{"json_class":"Fortune","tags":["oneliners"],"quote":"Never trust a stockbroker who's married to a travel agent.","link":"http://iheartquotes.com/fortune/show/7326","source":"oneliners"}

Consuming the Data

Now to understand how to consume this data in a Windows Phone 7 application we need to search for the text, “How to parse JSON on Windows Phone 7”.  It turns out that is a great question to search for on the web because it leads to an article on MSDN here: DataContractJsonSerializer Class.  We need to deserialize the JSON string to a C# object with the same structure.  So in the WindowsPhoneApplication1.Shared project, we add a new folder called Models and the a new class called Quote.cs.  Then we make a plain old CLR object (POCO) based on the properties of the JSON.  There are two modifications we need to make to the class.  First, implement the INotifyPropertyChanged interface so that updates to values of these properties will update any Data Bindings used in the UI.  Second, we have to prepare the class for deseriliazation by adding the DataContractAttribute to the class and the DataMemberAttribute to each property that will be deserialized.  The moment we attempt to add the [DataContract] attribute to the class we need a reference to System.Runtime.Serialization.  So in the Shared project simply add the reference and finish decorating the properties in the class.  Notice too that the Name parameter of the DataMember attribute needs to be set to the proper casing of the properties returned in the JSON data.  This creates the correct mapping to properties during deserialization.  The final class is shown below.

using System.ComponentModel; using System.Runtime.Serialization; namespace WindowsPhoneApplication1.Shared.Models { [DataContract] public class Quote : INotifyPropertyChanged { private string randomQuote; [DataMember(Name="quote")] public string RandomQuote { get { return randomQuote; } set { if (randomQuote == value) return; randomQuote = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("RandomQuote")); } } private string source; [DataMember(Name="source")] public string Source { get { return source; } set { if (source == value) return; source = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Source")); } } public event PropertyChangedEventHandler PropertyChanged; } }

 

The DataContractJSonSerializer class is going to be used to serialize and deserialize the JSON string to an object defined by this class.  Going back to the MSDN article we see the class is located in another assembly System.ServiceModel.Web.  The location of the code that does this work is going to be in the WindowsPhone.Helpers project.  So we add the reference to that project and create a helper class with static methods to do some JSON serialization.  The helper class source is listed below.

using System.IO; using System.Runtime.Serialization.Json; using System.Text; namespace WindowsPhone.Helpers { public class JsonSerialization { public static string Serialize(object obj) { // Serialize to a memory stream.... MemoryStream ms = new MemoryStream(); // Serialize to memory stream with DataContractJsonSerializer DataContractJsonSerializer s = new DataContractJsonSerializer(obj.GetType()); s.WriteObject(ms, obj); byte[] json = ms.ToArray(); ms.Close(); // return utf8 encoded json string return Encoding.UTF8.GetString(json, 0, json.Length); } public static T Deserialize<T>(string json) { T result = default(T); // load json into memorystream and deserialize MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)); DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(T)); result = (T)s.ReadObject(ms); ms.Close(); return result; } } }

 

Getting Design Time Data from the Web Service

It can be fairly easy to create a web request given the information up to this point, deserialize the result, and show it in the UI of the application.  In a nutshell that is the goal. But we want to be able to have design time data and build a slightly more robust structure.  So we are going to build a custom client and then wrap that client.  The custom client has an asynchronous call to the Url for the Quote API that when complete will deserialize the result and return the Quote object in an event.  The wrapper class for the client will have a public method to start the request and will listen to the completed event to return the Quote object.  This approach allows us to create an interface on the client wrapper for use in IoC and thereby create a design time data implementation of the wrapper.  The interface is located in the Shared project in a folder called WebServices.  We add a copy of the wrapper class to the Design project that inherits the interface.  The difference in the Design copy is that instead of calling into the actual client for the web service, we can simply instantiate a Quote object, populate it, and return it to the design surface.  To take a step back, the client and wrapper classes will be located in the main phone project inside a folder called WebServices.  The Design project copy of the wrapper will be located in a folder also called WebServices.

There is an additional helper for making passing event arguments a little easier.  That article can be found here: Custom Generic EventArgs.  Simply add that to the source code in the WindowsPhone.Helpers project and correct namespaces as needed.

 

References, References, References

To get all this to tie together and compile there are a few required references.  The Shared project has to reference the Helpers project.  The Design project has to reference the Helpers and Shared projects.  The main phone application project has to reference Helpers and Shared projects just like the Design project does.  The good thing is that so far there is no circular reference and we get design time data for a web service!  Here is what it looks like now in the solution tree.

image

 

Hooking Up Design Time Data

Now it is time to add the design time and run time objects for the web service to the ViewModelLocator class.  Again, if the code is in design time the class from the Design project has to be registered to the IoC container.  If not, the production web service wrapper class is registered.  The MainViewModel class will have a property for the web service wrapper so that means a few additional changes are needed.  The interface needs the property.  MainViewModel needs the implementation of that property.  At the time the MainViewModel is resolved in ViewModelLocator, the web service wrapper is resolved too and assigned to the new property.  Finally, the design time wrapper class for the web service returns data.  Not from the web service client, but from the wrapper alone.

ViewModelLocator.cs
/* In App.xaml: <Application.Resources> <vm:ViewModelLocator xmlns:vm="clr-namespace:WindowsPhoneApplication1.ViewModels" x:Key="Locator" /> </Application.Resources> In the View: DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}" */ using System.IO; using System.Reflection; using GalaSoft.MvvmLight; using MicroIoc; using WindowsPhoneApplication1.Shared.ViewModels; using WindowsPhoneApplication1.WebServices; using WindowsPhoneApplication1.Shared.WebServices; namespace WindowsPhoneApplication1.ViewModels { /// <summary> /// This class contains static references to all the view models in the /// application and provides an entry point for the bindings. /// </summary> public class ViewModelLocator { private readonly IMicroIocContainer container = new MicroIocContainer(); private Assembly designTypes = null; /// <summary> /// Initializes a new instance of the ViewModelLocator class. /// </summary> public ViewModelLocator() { if (ViewModelBase.IsInDesignModeStatic) { try { //Load the non-referenced assembly containing design time ViewModels and Services designTypes = Assembly.Load("WindowsPhoneApplication1.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); } catch (FileNotFoundException) { designTypes = Assembly.LoadFrom(@"C:\code\WP7\WindowsPhoneApplication1\WindowsPhoneApplication1.Design\BuildFiles\WindowsPhoneApplication1.Design.dll"); } // Register design time view models and services container.RegisterInstance(designTypes.GetType("WindowsPhoneApplication1.Design.ViewModels.MainViewModel"), "MainViewModel_DesignTime"); container.RegisterInstance(designTypes.GetType("WindowsPhoneApplication1.Design.WebServices.QuoteServiceWrapper"), "QuoteService_DesignTime"); } else { // Register run time view models container.RegisterInstance(typeof(MainViewModel), "MainViewModel"); container.RegisterInstance(typeof(QuoteServiceWrapper), "QuoteService"); } } public IMainViewModel Main { get { if (ViewModelBase.IsInDesignModeStatic) { IMainViewModel mainViewModel = (IMainViewModel)container.Resolve(designTypes.GetType("WindowsPhoneApplication1.Design.ViewModels.MainViewModel"), "MainViewModel_DesignTime"); mainViewModel.QuoteService = (IQuoteService)container.Resolve(designTypes.GetType("WindowsPhoneApplication1.Design.WebServices.QuoteServiceWrapper"), "QuoteService_DesignTime"); return mainViewModel; } else { IMainViewModel mainViewModel = GetViewModel<MainViewModel>(); mainViewModel.QuoteService = (IQuoteService)container.Resolve(typeof(QuoteServiceWrapper), "QuoteService"); return mainViewModel; } } } private T GetViewModel<T>() where T : ViewModelBase { // Create a new view model T vm = container.Resolve<T>(); return vm; } } }
IMainViewModel.cs
using WindowsPhoneApplication1.Shared.Models; using WindowsPhoneApplication1.Shared.WebServices; namespace WindowsPhoneApplication1.Shared.ViewModels { public interface IMainViewModel { string ApplicationTitle { get; set; } IQuoteService QuoteService { get; set; } Quote Quote { get; set; } } }
MainViewModel.cs
using GalaSoft.MvvmLight; using System; using WindowsPhoneApplication1.Shared.ViewModels; using WindowsPhoneApplication1.Shared.WebServices; using WindowsPhoneApplication1.Shared.Models; using System.ComponentModel; namespace WindowsPhoneApplication1.ViewModels { /// <summary> /// This class contains properties that a View can data bind to. /// <para> /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel. /// </para> /// <para> /// You can also use Blend to data bind with the tool's support. /// </para> /// <para> /// See http://www.galasoft.ch/mvvm/getstarted /// </para> /// </summary> public class MainViewModel : ViewModelBase, IMainViewModel { /// <summary> /// Initializes a new instance of the MainViewModel class. /// </summary> public MainViewModel() { } private IQuoteService quoteService; public IQuoteService QuoteService { get { return quoteService; } set { if (quoteService == value) return; quoteService = value; GetRandomQuote(); } } private void GetRandomQuote() { this.QuoteService.GetQuoteCompleted += (s, e) => { this.Quote = e.Value; }; this.QuoteService.GetQuote(); } private Quote quote; public Quote Quote { get { return quote; } set { if (quote == value) return; quote = value; RaisePropertyChanged("Quote"); } } /// <summary> /// The <see cref="ApplicationTitle" /> property's name. /// </summary> public const string ApplicationTitlePropertyName = "ApplicationTitle"; private string applicationTitle = "This is an awesome phone application template!"; /// <summary> /// Gets the ApplicationTitle property. /// TODO Update documentation: /// Changes to that property's value raise the PropertyChanged event. /// This property's value is broadcasted by the Messenger's default instance when it changes. /// </summary> public string ApplicationTitle { get { return applicationTitle; } set { if (applicationTitle == value) { return; } var oldValue = applicationTitle; applicationTitle = value; // Update bindings, no broadcast RaisePropertyChanged(ApplicationTitlePropertyName); } } ////public override void Cleanup() ////{ //// // Clean own resources if needed //// base.Cleanup(); ////} } }

WindowsPhoneApplication1.Design.WebServices.QuoteServiceWrapper.cs
using System; using WindowsPhone.Helpers; using WindowsPhoneApplication1.Shared.Models; using WindowsPhoneApplication1.Shared.WebServices; namespace WindowsPhoneApplication1.Design.WebServices { public class QuoteServiceWrapper : IQuoteService { public void GetQuote() { Quote quote = new Quote() { Source = "Lorem Ipsum (translation)", RandomQuote = "There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain.... " }; if (GetQuoteCompleted != null) GetQuoteCompleted(this, new EventArgs<Quote>(quote)); } public event EventHandler<EventArgs<Quote>> GetQuoteCompleted; } }

Showing the Design Time Data

The MainView.xaml can now display design time data!  Because of all the infrastructure in place, all that needs to be done is to add standard Silverlight data binding to the View.  The View is unaware of everything else going on in the VIewModel, Locator, and other architecture.  All it knows is that there is a value for a Quote, and it is bindable.  It seems like a lot of extra code to make this separation of concerns between the View and ViewModel happen.  The alternative is not to use MVVM and deal with the increase in cost later when you need to change the code.  This is a much more maintainable setup.  The XAML below shows the bindings for a quote and source.

MainView.xaml
<phone:PhoneApplicationPage x:Class="WindowsPhoneApplication1.Views.MainView" 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:DesignWidth="480" d:DesignHeight="768" shell:SystemTray.IsVisible="True" DataContext="{Binding Main, Source={StaticResource Locator}}"> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12"> <TextBlock x:Name="ApplicationTitleTextBlock" Text="{Binding ApplicationTitle}" Style="{StaticResource PhoneTextNormalStyle}" /> <ScrollViewer> <StackPanel> <TextBlock x:Name="QuotationTextBlock" Text="{Binding Quote.RandomQuote}" TextWrapping="Wrap" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}" /> <TextBlock x:Name="SourceTextBlock" Text="{Binding Quote.Source}" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle2Style}" /> </StackPanel> </ScrollViewer> </StackPanel> </Grid> <!-- Sample code showing usage of ApplicationBar <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton x:Name="appbar_button1" IconUri="/Images/appbar_button1.png" Text="Button 1"></shell:ApplicationBarIconButton> <shell:ApplicationBarIconButton x:Name="appbar_button2" IconUri="/Images/appbar_button2.png" Text="Button 2"></shell:ApplicationBarIconButton> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem x:Name="menuItem1" Text="MenuItem 1"></shell:ApplicationBarMenuItem> <shell:ApplicationBarMenuItem x:Name="menuItem2" Text="MenuItem 2"></shell:ApplicationBarMenuItem> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar> --> </phone:PhoneApplicationPage>

Here is the result of the design time data in Visual Studio.  We can see the Application Title, and a quote on screen.  The source of the quote is implemented but not visible in this layout.

image

Summary

This post outlined the steps to add a web service to the solution and show design time data from it.  The application is taking shape.  Next time we will add a custom Application Bar to be able to refresh the quote.  Then we’ll add some nice finishing touches that take advantage of some other features in the solution.  It gets much easier from this point forward!

 

Source Code

Code, Silverlight, WP7

Using Social Networks to Build Reusable Architecture for the Windows Phone 7 – Part III

11. February 2011


Part I
Part II
Part III

This is the third installment of a several part series/journey to use social network resources for Windows Phone 7 development and produce a reusable code base.

In Part II of the series two pattern frameworks were introduced.  MVVM Light for the Model-View-ViewModel pattern, and MicroIoC for the Inversion of Container pattern.  Both are great frameworks for adding maintainability, stability, and blendability to your WIndows Phone 7 applications.

Things progress quickly in the Windows Phone 7 development world.  While writing this post Laurent Bugnion updated his MVVM Light framework.  Thankfully updating the assemblies, snippets, and item templates is all fairly easy using the MVVM pattern.  The source code for each series post has these updates and you can download them.  It may be worth noting that it is a good idea to update 3rd party frameworks before publishing a phone application to market.

 

Silverlight Toolkit for Windows Phone

It is time to add the Silverlight Toolkit for Windows Phone.  The Silverlight Toolkit released a new update on February 17th, 2011.  The source code for this blog series was created a few days before that release.  However, the final source will be updated to use it.

If you download the source code from Silverlight.Codeplex.com and extract it, you will see one subfolder that we are interested in.

image

It is in {unzipped path}\Release\WindowsPhone7.  Here you see the projects for the Toolkit and the projects with names ending in “Design”.  These are projects for the Blend and Visual Studio designers.  There is also a strongly typed key file that is needed.  That is PhoneToolkit.snk.  So, refer to the image above and copy the folder Microsoft.Phone.Controls.Toolkit and the file PhoneToolkit.snk into the root of our phone solution.  Then right click and add the project to the solution.

The Solution Explorer should look something like this once the project reference is completed.

image

The list of controls available to your application now includes all of the Toolkit controls.  Here is that list:

image 

 

Silverlight Toolkit People

It’s worthwhile to go back to the CodePlex project site and review the people working on the source code.  One of the developers is Jeff Wilcox.  He is a reliable and enthusiastic contributor to the platform.  He keeps a blog at http://www.jeff.wilcox.name/blog/.  Jeff had a control released on his blog called the PerformanceProgressBar.  He blogged about that here: http://www.jeff.wilcox.name/2010/08/performanceprogressbar/.  It is now part of the Silverlight Toolkit for Windows Phone.  As you can see in the image above.  To really understand how to use the control it is worth reading that older post.  In it you find that if you need a progress bar control in your application for loading or waiting animations you should use the PerformanceProgressBar.  Also, you should always always always set the boolean flag IsIndeterminate to false once you are done with it.  It is a good idea to keep track of Jeff Wilcox to stay up to speed with control updates for the platform.

 

Coding4Fun Toolkit and a CustomInputPrompt Control

Ok, let’s go back to Reddit to see what’s new in terms of controls and helpers.  If you scroll down a bit in the Reddit search for “wp7dev”, you’ll see a link to a control.

image

It looks like a CustomInputPrompt control is provided by a very cool WP7 community site.  That community site is http://www.windowsphonegeek.com/.  This site has a nice community around the phone platform.  Reading the details of this blog you find that it is based on the work done by the Coding4Fun folks.  They offer for the Windows Phone 7 platform something called the Coding4Fun Tools

Let’s follow along this research tangent and take a closer look at Coding4Fun.  In that library they have a really nice set of controls, actions, converters, and helpers (see image below).image

Download the source code from CodePlex and add in the projects to the solution.  The source code has three projects to copy into the root of the solution folder along with references that need to be updated to the Microsoft.Phone.Controls.Toolkit project.  Once completed the solution tree should look something like this:

image

Now get the CustomInputPrompt control source code.  Since it is a small project it can be added manually into the WindowsPhone.Controls project we have.  The new control relies on a reference to the Coding4Fun.Phone.Controls project.  So add a reference to that project in WindowPhone.Controls.  After we copy the Themes folder and class file from that project into the WindowsPhone.Controls project, we have to update the namespace to WindowsPhone.Controls in two places.

image

image

The WindowsPhone.Controls project should look like the following:

image

 

Bindable ApplicationBar Control

Ok, back to the wp7dev Reddit search results.  Scanning a bit further, you may find the following link.  It is a must read blog about using MVVM Light with a bindable ApplicationBar control.  That article is here.

image

To understand the issue a bit better, we have to go back to a blog from Laurent Bugnion regarding MVVM Light and the Application Bar.  The issue is that ApplicationBarItems, which include the menu items and buttons, are not controls.  Because they are not inherited from FrameworkElement in Silverlight the normal mechanism that allows binding a RelayCommand to them does not work.  RelayCommand is a mechanism that gives MVVM Light the ability to separate event handlers into ViewModels instead of handling them in code behind of Views.  For example, regular button controls have a click event that can be routed to the ViewModel, while default Application Bar buttons cannot.  The ugly workaround for the out of the box Application Bar is that you have to break the idea of separation of concerns that MVVM gives us and put event handling code in the code behind of any View that has an ApplicationBar control.  But using the bindable ApplicationBar control from the link above allows us to have proper MVVM.  This will be illustrated in detail later in this series.

You can download the source code from here and add it to the Windows.Controls project.  There will be namespace corrections as before but they are easy to make.  There are other some changes to make when including the source code.

First we create a folder in WindowsPhone.Controls and call it “AppBar”.  Then we copy the three main class files needed from the source code into that folder.  The namespace for the three class files need to change to “namespace WindowsPhone.Controls.AppBar”.  There is a required VisualTreeHelperExtensions.cs file that would best be located in the WIndowsPhone.Helpers project.  So we copy that in to the other project, fix the namespace for it, and add a reference to the WindowsPhone.Controls project to the WIndowsPhone.Helpers project.  So far so good.  No circular references!

image

 

Behaviors for Marketplace Ratings and User Feedback

image

There are some nicely written Actions you can add to your applications.  There is a recommendation to include a way for your customers to contact you for support.  This was originally a requirement but as of February 24th, 2011 it became a recommendation.  It seems natural to have an About page in every application with the ability to send an email to you for support or comments.  Included in the above blog are two other marketplace related actions.  These are four nice to have items in your application.  They either navigate to or allow actions in the marketplace related to the application details, rating the application, or searching for similar applications.  There is also an action to send emails to a support email address you specify.  They can easily be added to the Windows.Helpers project.  Download the source code from here and adapt it into the solution using the techniques described earlier.  Put the Actions in the WindowsPhone.Helpers project.  Read about the source code here.  It’s important to note that this code requires two additional references.  Also, in the WindowsPhone.Helpers project add references to Microsoft.Phone and System.Windows.Interactivity.  Later in this series we will have an About page and will implement one or more of these features.

 

Summary

There are 4 major control and helper libraries in the phone solution at this point.  If you read through the series from the beginning you should have a good idea about how to include more community source code in your phone projects.  This post explained the basic process of researching for frameworks and controls and how to adapt them into your architecture.  Be aware of licensing restrictions as you do this because some licenses cannot be used for commercial purposes or some authors require certain rules to use the code.  As it stands right now, this phone solution has enough architecture and supporting code to write a nice application.  In the next part of the series we look at adding a real data source from somewhere, mocking up design-time data for the service, and finishing up on implementing some of the controls that are available in the solution.

 

Source Code

Code, Silverlight, WP7

Using Social Networks to Build Reusable Architecture for the Windows Phone 7 – Part II

8. February 2011
.

 

Part I
Part II

This is the second installment of a several part series/journey to use social network resources for Windows Phone 7 development and produce a reusable code base.

In Part I the goal simply was to show a couple of reliable sources for WP7 development, and get started building up the baseline phone application solution.  The next step is to add some patterns, helpers, and controls to the solution.  All of which are reusable for your Silverlight Windows Phone 7 applications.

 

MVVM Pattern

MVVM Light is one of several options for implementing the Model-View-ViewModel pattern.  There are many articles available to explain the benefits of this pattern.  If you aren’t using MVVM for WP7 you really need to start.  There is a little up front cost in implementing any pattern but the return on investment usually makes it worthwhile.  Caliburn.Micro is another great option.  Reactive UI is yet another option for the MVVM pattern.  For this series we are going to use Laurent Bugnion’s MVVM Light library and if you like, you can refactor the source code at the end of the series to use something else.  MVVM Light can be found on Laurent’s blog here.  There is also a CodePlex project here where you can get the source code and/or binaries from.  There are detailed installation instructions for installing the custom MVVM Light project, item templates, binaries, and code snippets. 

Instead of following the installation steps to the letter, since I’ve worked with MVVM Light extensively, we take a modified approach.  You may want to install first based on the instructions and then follow my steps after that.

After downloading the latest source code and compiling the binaries, copy compiled assemblies and code snippets for MVVM Light and drop them in the SolutionFiles project.  Then reference the binaries located in the SolutionFiles project and add the snippets to Visual Studio.  To accomplish this first create two folders within the SolutionFiles project and copy in the binaries and snippets files.  Next use the Tools menu in Visual Studio and open up the Code Snippets Manager to import the snippets. There is an Import button to do this.  The steps to add the binaries are fairly straightforward but the Code Snippets Manager can be more confusing than necessary sometimes.  Here is a screen shot to help.

image

Now go into the WindowsPhoneApplication1 project and add references to the MVVM Light binaries from the newly added SolutionFiles files.

There is a detailed explanation on how to get started with MVVM Light here.  The reason it is mentioned here is that there is a section on Components that is worth a quick review.

It isn’t completely necessary to add folders for different kinds of MVVM code files.  It is a good practice to do so.  Caliburn.Micro for instance follows a “Convention over Configuration” approach forcing you to structure folders a certain way so that the version of an MVVM framework can locate Views and ViewModels via reflection.  Following this folder structure convention doesn’t hurt, it keeps files organized, and might make refactoring a little less tedious later.  So, add three folders to the WindowsPhoneApplication1 project.  One called “Models”, one called “Views”, and one called “ViewModels”.

To use MVVM something has to “locate” the matching ViewModel for a View.  In MVVM Light that is done using a dedicated ViewModelLocator class.  Laurent was smart and already created an item template for that.  As well as item templates for Views and ViewModels.  Go to this link and scroll down to the section on “Installing the templates for Visual Studio 2010”.  You can follow the instructions for installing both the Project Template and all of the Item Templates.  Because this series is about creating our own custom project template, we skip the step for the MVVM Light project template.

Now, right click on the ViewModels folder to Add a New Item.  Choose the ViewModelLocator item template.  You can see the other item templates in the screen shot below.

image

Name this class “ViewModelLocator”.  The class file is generated based on the name and there are a couple of interesting points as you look through it.  There is a constructor and a cleanup method.  The commented out code and summary text has the really interesting stuff.  At the top of the file there is a comment section telling you that you need to add some XAML to the App.xaml.cs file.  This creates a Static Resource to use throughout the application for the locator class.  The second important comment shows how each View references the locator and binds the correct ViewModel to the View.  It is a line of XAML that basically says, set this View’s DataContext to the ViewModel located via a public property in the ViewModelLocator.  The nice thing about this is that it sets up the ability to have “blendability”, or design-time data.  Built into both the WP7 programming API and MVVM Light is the ability to check a value to determine if the application is running in a device or emulator, or not.  When the application is not running the term blendability refers to the design surface in Expression Blend.  It can also be interpreted as the design surface in Visual Studio. 

The Windows Phone 7 Phone Application project template that comes out of the box with the development tools allows for some design-time data if you use Blend to create it.  There is an approach for that detailed at KIRUPA.com here.

In a real world application there are going to be ViewModels, web services, and other sources of data.  You can mock up data for a simple class very easily.  But it is more difficult to mock up data for web services.  It requires some code to provide design time data for complex object graphs.  It is important to separate that code from production code to improve maintainability and readability.  So, how do we get design-time data in the application?

 

IoC Pattern Plus a Little Trick to Enable Design Time Data

To improve productivity in developing the application we add another pattern.  MVVM allows for a clean separation of concerns.  Getting design time data in a Silverlight application also allows for the separation of roles between designers working strictly in Blend and developers working strictly in Visual Studio.  Design-time data will increase productivity more than enough to justify the work of adding and using the Inversion of Container pattern (IoC).

It is arguable that you don’t need another pattern after using MVVM to get design time data.  You could put all the design-time data in the main phone project and switch logic if the DesignerProperties.IsInDesignTool flag is true or false.  However, this will clutter code up to some extent and could increase the final size of the application XAP file.  Maintainability of code suffers as a result and performance also can be affected.  So what you can do is put the data into a separate project that you don’t need to reference directly in the production code.

There are multiple ways of doing what is described here. Essentially, we are going to create a shared project and a design-time data project and set up some references.  Then we are going to implement IoC and describe a way to get design-time data from a project that isn’t referenced.

Just like MVVM Light, there are lightweight frameworks available so you don’t have to write your own if you don’t want to.  The one we’ll use is called MicroIoC and it can be found on CodePlex here.  Download and add just the MicroIoC.Core project into the solution.  Again, copy the source code of the MicroIoC.Core project into the root folder of the solution so all the code is organized.  Reference the MicroIoC.Core project in the main phone application project.

Create a new project and call it something like WindowsPhoneApplication1.Design.  Choose the class library project template for it.  Create another project as a class library and call it WindowsPhoneApplication1.Shared.  The Design project is going to have the design-time data in the form of ViewModels and Services.  The Shared project is going to have interfaces for all of the ViewModel and Service classes.  Once those projects are created, add a reference in the main phone application to the Shared project.  In the Design project also reference the Shared project.  Do not reference the Design project anywhere.  In the Design project, do reference the MVVM Light binaries stored in the SolutionFiles project.  For the sake of organization, create a folder called “ViewModels” in the Design project.

At this point, you should have 7 projects in the solution.  If you press CTRL+W,C the Visual Studio IDE will display the Class View of the solution.  It should look something like this.

image

The default phone application template created a few things that need to change for MVVM.  First, create a new View in the Views folder by using the MVVM Light item template.  Call it “MainView.xaml”.  The code generated will have the DataContext setting described earlier.  We want to make this the first phone application page of the application.  So in the Properties folder you will find a file WMAppManifest.xml.  It has a default startup phone application page.  Locate and change the xml as it appears below:

<DefaultTask  Name ="_default" NavigationPage="Views\MainView.xaml"/>

The NavigationPage attribute needs the correct relative path to the Main View.  Next create a ViewModel in the ViewModels folder and use the MVVM Light item template.  Call it “MainViewModel”.  You don’t save much time by using the ViewModel template because it is really just a class file.  There are some useful instructions.  So for all future ViewModels, just use the create new Class.cs template.  The convention approach has a naming convention putting the text “ViewModel” at the end of the class file name.  Instructions in the new ViewModel tell you how to use the MVVM Light code snippets to create custom dependency properties. 

It is worth taking a moment to look at the code generated by one of the snippets.  Go ahead and create a custom dependency property now using the code snippet mvvminpc.  Make it a string property and call it ApplicationTitle.  The backing variable name isn’t as important.  After creating the property, set the default text value to something like this:

private string applicationTitle = "This is an awesome phone application template!";

Notice too that in the constructor there is some code to add blendability.  It can be ignored or removed.  Ok, now we have a MainViewModel, and a MainView.  Now we need an interface for the MainViewModel in the Shared project and a copy of the MainViewModel.cs file in the Design project.  So right click and select Copy for the MainViewModel.cs file and then paste it into the ViewModels folder of the Design project created earlier.  Change the default value of the application title property so we can see the design-time data later on.

private string applicationTitle = "This is Design time data!!!!";

This express version of Visual Studio does not have a Refactor-Extract Interface feature.  So, we create an interface manually.  It should look something like this and it should be created in the Shared project.

namespace WindowsPhoneApplication1.Shared.ViewModels 
{ 
    public interface IMainViewModel 
    { 
        string ApplicationTitle { get; set; } 
    } 
}

Again, this interface exists in the Shared project.  Which is referenced both by WindowsPhoneApplication1.Design and WindowsPhoneApplication1 projects.  Make sure to implement the interface on both of the concrete classes.

Inside the class ViewModelLocator use the MVVM Light snippet for generating a public property that locates MainViewModel for MainView.  That snippet is mvvmlocatorproperty.  The generated code will be deleted shortly so don’t be too concerned at how much code is there.  Take a quick look over it and you see a static MainViewModel is returned from the Main property.  If you named everything as intended using the snippet.  Ok, now click undo until the snippet code is removed (or just highlight and delete it). 

There is a slightly more terse way to accomplish the same thing.  That is to use IoC to return the correct MainViewModel based on the value of ViewModelBase.IsInDesignModeStatic.  If the application is in Design Mode, we want the locator to return a MainViewModel instance from the Design project.  Not from the main phone project.  That Design project MainViewModel will have all the design-time data in it.  Conversely, if the application is running in an emulator or on a phone, we want the locator to return the MainViewModel instance from the main phone project.  Its data will be production quality in some fashion.  Either hard coded in the view model or created dynamically from a web service result.

In order to get items from an IoC container, you first have to put things into them.  This is done by registering types of objects.  These types will be instantiated later when needed.  There are variations on where to register objects so by no means is this the only way.  For this project, this will be done entirely in the ViewModelLocator class.  Ultimately, the MainViewModel needs to be set as the DataContext in the MainView.  So, in the constructor of the ViewModelLocator we register a design time instance and a production time instance. 

How do you get the Design time instance if it isn’t referenced directly in the project?  The trick to loading the Design project assembly dynamically with Assembly.Load.  Let’s take a look at this in detail.  First in the build output and then how the code ties it together.

If you open the Configuration Manager for the Solution, you will see that the Design project is marked to build in both Debug and Release configurations.

image

However, if you look at the xap file contents (by changing the xap extension to zip) you will see that in fact the Design assembly is not included.

image

 

It seems time to show some code.  Note that the source code for this post is available at the bottom.

ViewModelLocator.cs
/* In App.xaml: <Application.Resources> <vm:ViewModelLocator xmlns:vm="clr-namespace:WindowsPhoneApplication1.ViewModels" x:Key="Locator" /> </Application.Resources> In the View: DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}" */ using System.IO; using System.Reflection; using GalaSoft.MvvmLight; using MicroIoc; using WindowsPhoneApplication1.Shared.ViewModels; namespace WindowsPhoneApplication1.ViewModels { /// <summary> /// This class contains static references to all the view models in the /// application and provides an entry point for the bindings. /// </summary> public class ViewModelLocator { private readonly IMicroIocContainer container = new MicroIocContainer(); private Assembly designTypes = null; /// <summary> /// Initializes a new instance of the ViewModelLocator class. /// </summary> public ViewModelLocator() { if (ViewModelBase.IsInDesignModeStatic) { try { //Load the non-referenced assembly containing design time ViewModels and Services designTypes = Assembly.Load("WindowsPhoneApplication1.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); } catch (FileNotFoundException ex) { designTypes = Assembly.LoadFrom(@"C:\code\WP7\WindowsPhoneApplication1\WindowsPhoneApplication1.Design\BuildFiles\WindowsPhoneApplication1.Design.dll"); } // Register design time view models and services container.RegisterInstance(designTypes.GetType("WindowsPhoneApplication1.Design.ViewModels.MainViewModel"), "MainViewModelDesignTime"); } else { // Register run time view models container.RegisterInstance(typeof(MainViewModel), "MainViewModel"); } } public IMainViewModel Main { get { if (ViewModelBase.IsInDesignModeStatic) { return (IMainViewModel)container.Resolve(designTypes.GetType("WindowsPhoneApplication1.Design.ViewModels.MainViewModel"), "MainViewModelDesignTime"); } else return GetViewModel<MainViewModel>(); } } private T GetViewModel<T>() where T : ViewModelBase { // Create a new view model T vm = container.Resolve<T>(); return vm; } } }

 

Looking at the code above, the essential “magic” happens in the constructor.  If the code is in Design Mode, then Assembly.Load is used to create the Assembly object designTypes.  From which view models (or service instances) can be instantiated with design-time data. 

There is a try-catch wrapping Assembly.Load.  Blend is able to locate the Design assembly but Cider, the Visual Studio designer for XAML, can only load the assembly given an absolute file path.  If the designer is not Blend, the Assembly.Load fails to find the assembly and instead uses the method overload Assembly.LoadFrom.  The ugly part is that you have to hard code the absolute path to the Design dll.  The payoff is that design-time data is available in Visual Studio in addition to Blend.

Unfortunately, when the absolute path is used that points to the output file in the Bin folder, there is another issue.  When you open the MainView in Visual Studio, the ViewModelLocator will run the code to load the assembly.  Once in use by Visual Studio, the Design project won’t be able to compile.  There is a simple workaround to this issue.  By using a post build event in the Design project, the output dll from the build can be copied to a different location.  The ViewModelLocator can point to that location for the Assembly.LoadFrom code.  Then the issue of writing over the dll in the Build folder is fixed.  Here is the post build command for the Design project.

start xcopy /y $(ProjectDir)$(OutDir)$(TargetFileName) $(ProjectDir)BuildFiles\

The instance needs to be registered in the container.  That is done using the container.RegisterInstance method.  Note the use of a string key for the MicroIoC register method.  We use a different string key for design verses production time instances.  If the application is running and not in Design Mode, the instance registration doesn’t include the Assembly.Load of the Design project at all.

There is a method GetViewModel that uses generics to get (or resolve) the instance of a view model from the container.  You can see that for a given type T where T inherits the ViewModelBase type, we can retrieve the instance from the container.

Look at the property described by

public IMainViewModel Main
{
    get
    {
        if (ViewModelBase.IsInDesignModeStatic)
        { ....

The getter includes the test for design mode and returns either the design time instance of an object adhering to the interface IMainViewModel.  Or it returns a production time instance MainViewModel.

This is the pattern for all ViewModel instances and it is centralized in this ViewModelLocator class.  A small amount of work to have a good scalable, maintainable, and blendable architecture.

When you run this application, you see the production time data for the application title.

image

While you are writing and designing the application in Visual Studio or Blend you see the design-time data.

image

 

Summary

So far, the solution is set up to take advantage of MVVM Light and an IoC framework called MicroIoC.  This overall structure could also be applied to Silverlight 4 applications and not just Windows Phone applications.

In the next part we’ll add a few value converters, actions, behaviors, and controls.  There is at least one more project to add to the solution.  The Silverlight for Windows Phone Toolkit.  We’ll also go into a problem and a solution for the WP7 Application Bar control.

 

Source Code

Code, Silverlight, WP7

Using Social Networks to Build Reusable Architecture for the Windows Phone 7 – Part I

7. February 2011

This is the first installment of a several part series/journey to use social network resources for Windows Phone 7 development and produce a reusable code base.

Social networking resources used here include Twitter, Reddit, Microsoft Windows Phone developer community resources, and developer blogs.  A lot of useful information is shared by the people developing for the Windows Phone 7 platform on their personal blogs.

There are a couple of reasons for writing this and doing this work.  First it is to produce a template based on many public sources that can be reused for Silverlight Windows Phone 7 applications.  This isn’t intended to be a “hello world” template but instead it will be a fairly robust model.  It will use some solid patterns and it will contain several maintainable libraries.  In fact there will be a solution with several reusable projects.  The other goal is to talk about another way to answer the question, “Where do I start learning about Windows Phone 7 development?”

The main starting point that you need to go to is the APP HUB for Windows Phone and Xbox 360.  Here you will find formal documentation, tools, samples, forums, community, and much more.  If you are a beginner, read through the content on getting started and follow the guidance on installing latest tools.  There will be updates to the development tools so check back there frequently.  You must also read the series by Andrea Boschin about Getting Started with Windows Phone 7.  His series goes deep into basic features that you should be aware of.  This series focuses more on structure and architecture and does assume an intermediate understanding of the Windows Phone 7 platform.

 

Twitter and Reddit.com

A great way to find up the the minute and current resources is to search for the hash tag #wp7dev on Twitter.  You don’t even need a Twitter account for this!  Here is a screen shot of results as of this writing:

image

Scan through the results and you start to see trends about current releases, tool updates, and interesting blog postings.  When Windows Phone 7 developer tools went public there were a few product announcements from the phone team on the hash tag.  Now everyone seems to be tweeting about their applications, news about the phone platform, re-tweeting, and having other conversations around the topic.  Starting at the top of this search and working backwards is a good way to find very useful and up to date resources.  It’s important to filter out the noise (no offense intended) and find a tweet that either is the source of a topic or is very close to the source. 

This sort of filter and scanning process will uncover tweets from people who are one re-tweet away from a direct source.  Such as @gcaughey.  This is the Twitter account of Ginny Caughey who is a Windows Phone Development MVP.  It turns out that she is one of the most enthusiastic people about Windows Phone 7.  Her tweets and re-tweets are an invaluable resource for finding great information about WP7.

Let’s look at another source.  Reddit.com has an incredibly rich source of information about WP7DEV.  The link is http://www.reddit.com/search?q=wp7dev.  Click over there now to see the latest entries.

image

 

New Phone Project and Solution

Ok, now with the latest free developer tools installed on your PC (from here), it’s time to open up a new project.  Visual Studio 2010 Express Edition for Windows Phone and Microsoft Expression Blend 4 for Windows Phone includes the majority of what you need to write applications for the Windows Phone Marketplace.  While this series won’t go into designing a phone application, it is worth noting that you may want to use some image tools.  Paint.Net in my experience is good enough to create all the image work you need for Silverlight applications (not XNA) and it is free.

Choose the default empty project template, or “Windows Phone Application” as seen below.

image

 

Solution Folder (or Project)

Solution folders are very useful in keeping everything you need for the source code to run, in one place.  There is a way using this free version of Visual Studio to include such a folder.  Solution folder are not supported in Visual Studio Express 2010 or Blend 4 for Windows Phone.  One way to do have something like them, however, is to include an empty project, remove all references, and change its build action such that it doesn’t build in any configuration.  Then you can create all the folders and subfolders that you wish with your dependencies and documentation in them.  This is not being recommended as a best practice.  It does work for the purposes of this solution.  If source control is added to your process having all the files needed for an application somewhere in the folder tree will make the development process better.  Source control solutions are out of scope for this series.  It is worth keeping things organized so it can be added, however.

image

To disable any builds for the empty project, right click on the Solution Explorer tree root and enter the Configuration Manager.

image

If you used the project template pictured above it will not appear in the list of projects that build.  Under any configuration.

image 

 

Helpers and Controls

Already, there is more than one project in the solution.  It’s time to add two more Windows Phone Class Library projects to the solution.  Right click on the solution root in Solution Explorer and choose the Windows Phone Class Library template as seen below.  Name one project “WindowsPhone.Helpers” and the other one “WindowsPhone.Controls”.

image

WindowsPhone.Helpers will contain things like Value Converters, Extension Methods, Actions, Behaviors,and other reusable code.  WindowsPhone.Controls will contain custom controls that are not part of a control toolkit and styles for those controls.  Right away this splits out a bunch of maintenance tasks into reusable parts.  These projects can be copied into a new solution easily.

 

Summary

This first post was a walkthrough to create a base solution with 4 projects in it.  While social network code resources were introduced, not much was done yet with the information.  In the next part we locate useful source code and add more projects, some patterns, and start writing code.

 

Source Code

Code, Silverlight, WP7