About the Author

Danny is a Senior Software Engineer at InterKnowlogy in Carlsbad, CA. Danny began acquiring his expertise in software engineering at Neumont University in Salt Lake City, Utah where he graduated with a BSCS. Danny’s passion for technology has led him throughout the Microsoft Stack including .NET, C#, XAML, and F#. Danny has an expertise in NUI (The Natural User Interface) having built numerous multi-touch and gesture based interfaces for software applications across a broad spectrum of devices. Currently his passion includes building Windows Universal Apps and WPF Applications driven by gesture interaction using the Microsoft Kinect. Danny is an Alumnus Microsoft MVP for Windows Platform Development and speaks all over the country including That Conference, Spark Conference, and SoCal Code Camp. When not building beautiful software, Danny is an outdoors man and devoted husband and father. He loves to camp, hike and mountain bike. Follow him on twitter @dannydwarren

WP7 Simplified: CoreApplicationService (Navigation)

My last post in this series covered the CoreApplicationService (CAS) and how it handles app lifecycle which is part of a broad series discussing how to simplify Windows Phone development. In the lifecycle post navigation was discussed only lightly. This post aims to cover the CAS and how it handles navigation. It will also, cover a few open questions about lifecycle from my previous post. The CAS was originally created and used for navigation exclusively. Desires for centralized lifecycle, tombstoning, and navigation management drove us to buff out the former NavigationService and rename it as CoreApplicationService. Since the NavigationService, we have optimized, simplified, and fundamentally improved navigation on Windows Phone applications.

Lesson #1: Centralize Data

The most important of lessons that we learned was to make sure data is centralized in the app. Any object reference that needs to be passed to the next page can only do so if the reference to that object is available from a centralized data provider. We won’t cover data providers here, but I wanted to bring this lesson to the forefront in order to help bring clarity to the thought process behind the navigation paradigm used in the CAS. We had unknowingly painted ourselves into a corner during our development one of the phone apps we developed. We desired to modify the same object reference in two related pages. We made the mistake of storing the object in the PhoneApplicationService.Current.State dictionary. What we didn’t realized until the final weeks of development and testing was that State dictionary serializes the objects stored in it. That means when obtaining an object stored in the State dictionary it was being deserialized as a new object. We would then modify that object and return back to the first page. The first page would then assume the object was updated when in reality a different object reference had been used and updated. This was a huge bummer to realize so late and taught us to never pass objects via the State dictionary if we need the original object reference.

With that said lets get into some navigation topics.

Navigation Infrastructure

Those familiar with Windows Phone development know that in order to perform any kind of navigation you must use the PhoneApplicationFrame. When initializing the CAS in App.xaml we pass in the PhoneApplicationFrame. This gives us the ability to navigate without requiring a PhoneApplicationPage which is the built in intermediary to the PhoneApplicationFrame. The navigation framework in the CAS is essentially a more developer friendly API wrapper for the PhoneApplicationFrame navigation framework. Our goal was to expose all of the PhoneApplicationFrame navigation framework while buffing out the points where it was lacking.

public class CoreApplicationService
{
	private PhoneApplicationFrame _frame;

	public event EventHandler<NavigatingCancelEventArgs> Navigating;
	private void OnNavigating(NavigatingCancelEventArgs e)
	{
		var handler = Navigating;
		if (handler != null) handler(this, e);
	}

	public event EventHandler<NavigationEventArgs> Navigated;
	private void OnNavigated(NavigationEventArgs e)
	{
		var handler = Navigated;
		if (handler != null) handler(this, e);
	}

	public Dictionary<object, string> Mappings { get; private set; }

	public void Initialize(PhoneApplicationFrame frame, bool isLaunching)
	{
		LittleWatson.CheckForPreviousException();
		_frame = frame;
		_frame.Navigated += FrameNavigatedHandler;
		_frame.Navigating += FrameNavigatingHandler;
		PersistTombstoningValue(IS_LAUNCHING_KEY, isLaunching);
	}
	
	private void FrameNavigatedHandler(object sender, NavigationEventArgs e)
	{
		OnNavigated(e);
	}

	private void FrameNavigatingHandler(object sender, NavigatingCancelEventArgs e)
	{
		OnNavigating(e);
	}
}

Navigation Mappings

This is one are of functionality where we’re trying to optimize still. Currently we have a dictionary of object to string mappings. The string represents the Uri to a page while the object is some arbitrary key that maps to that page. Managing the keys is the difficult part that we haven’t quite figured out yet. Here is how we register the mappings in LionHeart.

public partial class App : Application
{
	private void InitializeNavigationMappings()
	{
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.HOME_VIEW_KEY, "/Views/HomeView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.MY_VIEW_KEY, "/Views/MyView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.ALL_CLIENTS_VIEW_KEY, "/Views/AllClientsView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.CLIENT_VIEW_KEY, "/Views/ClientView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.MY_REPORTS_VIEW_KEY, "/Views/MyReportsView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.REPORT_VIEW_KEY, "/Views/ReportView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.ALL_SESSIONS_VIEW_KEY, "/Views/AllSessionsView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.MY_SESSIONS_VIEW_KEY, "/Views/MySessionsView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.SESSION_VIEW_KEY, "/Views/SessionView.xaml");
		CoreApplicationService.Instance.Mappings.Add(ViewKeys.SETTINGS_VIEW_KEY, "/Views/SettingsView.xaml");
	}
}

By using this dictionary of mappings we gain a huge amount of flexibility. This allows the developer to expose and manage navigation keys in lower tiers of the app if desired. In the sample code we use a struct named ViewKeys to manage or contain all view keys. We’ve tried using object types as the key, but we always seemed to come to a point where we were mixing types into ViewModels that shouldn’t know about certain types and tightly coupling types to views. That doesn’t sound all bad, but from experience a struct of string keys has been one of the cleanest and readable approaches.

Note on Managing Views and ViewModels in the CAS: The PhoneApplicationFrame has a BackStack property that manages all pages that are alive in the app. We didn’t want to manage Views or ViewModels in the CAS because that work was already being done by the PhoneApplicationFrame. We also didn’t want to tightly couple the CAS the UI tier, in fact that’s exactly why we need the CAS is that the PhoneApplicationFrame is only available in the UI tier unless passed into a different tier. The CAS is immediately available to ViewModels and any other tier above the very base tier.

Here’s a look at ViewKeys:

public struct ViewKeys
{
	public static readonly string HOME_VIEW_KEY = "HOME_VIEW_KEY";
	public static readonly string MY_VIEW_KEY = "MY_VIEW_KEY";
	public static readonly string ALL_CLIENTS_VIEW_KEY = "ALL_CLIENTS_VIEW_KEY";
	public static readonly string CLIENT_VIEW_KEY = "CLIENT_VIEW_KEY";
	public static readonly string MY_REPORTS_VIEW_KEY = "MY_REPORTS_VIEW_KEY";
	public static readonly string REPORT_VIEW_KEY = "REPORT_VIEW_KEY";
	public static readonly string ALL_SESSIONS_VIEW_KEY = "ALL_SESSIONS_VIEW_KEY";
	public static readonly string MY_SESSIONS_VIEW_KEY = "MY_SESSIONS_VIEW_KEY";
	public static readonly string SESSION_VIEW_KEY = "SESSION_VIEW_KEY";
	public static readonly string SETTINGS_VIEW_KEY = "SETTINGS_VIEW_KEY";
}

Not very exciting… And moving on.

Performing Navigation

Now we get into the exciting stuff. How we perform a navigation. Here is some code from LionHeart in HomeVM and helper class NavigationDefinition to help illustrate how to do this.

<ListBox x:Name="Menu"
	ItemsSource="{Binding NavigationOptions}"
	SelectedItem="{Binding NavigationTarget, Mode=TwoWay}"
	DisplayMemberPath="Name"
	toolkit:TiltEffect.IsTiltEnabled="True"/>

public class HomeVM : PageViewModel
{
	private List<NavigationDefinition> _navigationOptions;
	public List<NavigationDefinition> NavigationOptions
	{
		[DebuggerStepThrough]
		get { return _navigationOptions; }
		set
		{
			if (value != _navigationOptions)
			{
				_navigationOptions = value;
				OnPropertyChanged("NavigationOptions");
			}
		}
	}
	
	private NavigationDefinition _navigationTarget;
	public NavigationDefinition NavigationTarget
	{
		[DebuggerStepThrough]
		get { return _navigationTarget; }
		set
		{
			if (value != _navigationTarget)
			{
				_navigationTarget = value;
				OnPropertyChanged("NavigationTarget");
				Navigate(_navigationTarget);
			}
		}
	}
	
	private void InitializeMenu()
	{
		if (NavigationOptions == null)
		{
			NavigationOptions = new List<NavigationDefinition>(new[]
				{
					new NavigationDefinition(MY_SESSIONS_MENU_ITEM_NAME,
						ViewKeys.MY_VIEW_KEY,
						new Dictionary<string,string>{{NavigationKeys.PIVOT_ITEM_KEY, MyPivotItem.Sessions.ToString()}}),
					new NavigationDefinition(MY_CLIENTS_MENU_ITEM_NAME,
						ViewKeys.MY_VIEW_KEY,
						new Dictionary<string,string>{{NavigationKeys.PIVOT_ITEM_KEY, MyPivotItem.Clients.ToString()}}),
					new NavigationDefinition(MY_REPORTS_MENU_ITEM_NAME,
						ViewKeys.MY_VIEW_KEY,
						new Dictionary<string,string>{{NavigationKeys.PIVOT_ITEM_KEY, MyPivotItem.Reports.ToString()}}),
					new NavigationDefinition(CREATE_REPORT_MENU_ITEM_NAME,
						ViewKeys.REPORT_VIEW_KEY),
					new NavigationDefinition(SETTINGS_MENU_ITEM_NAME,
						ViewKeys.SETTINGS_VIEW_KEY),
				});
		}
	}
	
	private void Navigate(NavigationDefinition definition)
	{
		if (definition != null)
		{
			NavigationTarget = null; // reset selection
			CoreApplicationService.Navigate(definition.Key, definition.Parameters);
		}
	}
}

public class NavigationDefinition
{
	public NavigationDefinition(string name, object key, Dictionary<string, string> parameters = null)
	{
		Name = name;
		Key = key;
		Parameters = parameters;
	}
	
	public string Name { get; private set; }
	public object Key { get; private set; }
	public Dictionary<string, string> Parameters { get; private set; }

}

NavigationDefinition

This simple helper class is just a wrapper for the desired ViewKey, a dictionary of parameter keys and values, and a display friendly name. This class helps to with creating a menu of navigation options in the UI such as the one created in HomeVM.InitializeMenu() in the sample code above.

When we navigate we can append parameters to the page Uri when we pass it to the PhoneApplicationFrame. In HomeVM.InitializeMenu() we create parameters for each NavigationDefinition with a key of ViewKeys.MY_VIEW_KEY. In this case the parameters will be used to determine which pivot item is in view when the user navigates to MyView. How this is done will be covered in a future post.

In HomeView there is a ListBox which displays each NavigationDefinition. The selection of the ListBox is bound to HomeVM.NavigationTarget. When the user selects a definition and NavigationTarget is set we call Navigate() from it’s setter. Navigate() in turn calls CoreApplicationService.Navigate() passing it the view key and the dictionary of parameters.

Processing a Navigation Request

public class CoreApplicationService
{
	/// <summary>
	/// Navigates the specified viewKey.
	/// </summary>
	/// <param name="viewKey">The viewKey.</param>
	/// <param name="parameters">The parameters.</param>
	/// <param name="countToRemoveFromBackStackAfterNavigation">The count to remove from back stack. (ignored if clearBackStack == <c>true</c>)</param>
	/// <param name="clearBackStack">if set to <c>true</c> [clear back stack].</param>
	public void Navigate(object viewKey, Dictionary<string, string> parameters = null, 
		int countToRemoveFromBackStackAfterNavigation = 0, bool clearBackStack = false)
	{
		string target;
		if (viewKey != null && Mappings.TryGetValue(viewKey, out target))
		{
			parameters = parameters ?? new Dictionary<string, string>();
			parameters.Add(IS_RUNNING_KEY, true.ToString());
	
			ICollection<string> parameterKeyValueStrings =
				parameters.Keys.Select(key => string.Format("{0}={1}", key, parameters[key])).ToArray();
	
			target += string.Format("?{0}", string.Join("&", parameterKeyValueStrings));
	
			if (clearBackStack)
			{
				_frame.Navigated += NavigationReadyToClearBackStackHandler;
			}
			else if (countToRemoveFromBackStackAfterNavigation > 0)
			{
				_countToRemoveFromBackStackAfterNavigation = countToRemoveFromBackStackAfterNavigation;
				_frame.Navigated += NavigationReadyToRemoveCountFromBackStack;
			}
	
			_frame.Navigate(new Uri(target, UriKind.RelativeOrAbsolute));
		}
		else
		{
			throw new ArgumentException(string.Format("Cannot navigate to target view. Driver={0}", viewKey));
		}
	}
}

Here we find the meat of navigation processing. The first thing done here is a check to validate the viewKey is a valid key to a page Uri then acquires the target page Uri. If no parameters were passed an empty parameters dictionary is created and immediately we add a parameter for IS_RUNNING_KEY which is always set to true if this method is called. The IS_RUNNING_KEY key is used by ViewModels in order to know how to initialize. Again, another topic that will be covered in a future blog post. After the parameters collection is finalized the CAS then appends each parameter to the target Uri forming the finalized target Uri.

The next step is to hook up handlers for the PhoneApplicationFrame.Navigated event when necessary. Sometimes it is desirable to perform a navigation that clears the entire PhoneApplicationFrame.BackStack. Other times, it is desirable to remove a specified number of pages from the PhoneApplicationFrame.BackStack. If clearBackStack is true then after navigation is complete the CAS clears the PhoneApplicationFrame.BackStack. If clearBackStack is false and countToRemoveFromBackStackAfterNavigation is greater than 0 then after navigation completes the CAS removes the specified number of page entries from the PhoneApplicationFrame.BackStack. This functionality is helpful for navigating to menu pages and in app navigation resets.

Finally, the CAS calls PhoneApplicationFrame.Navigate() allowing Windows Phone to take over.

ViewBase and Handling Navigation in Pages

First, there is currently a disconnect in terminology. Windows Phone calls each View a Page, and here at Interknowlogy we’re in the habit of calling each Page a View. So each term means exactly the same thing and we’re working on simplifying our terminology. With that aside lets look at ViewBase.

ViewBase becomes the new base class of each View in the app. This cuts down on duplicating this code for each view. Because of that maintainability goes up, which is always a good thing.

public partial class HomeView : ViewBase
{
	public HomeView()
	{
		InitializeComponent();
	}
}

public class ViewBase : PhoneApplicationPage
{
	public PageViewModel PageViewModel { get { return DataContext as PageViewModel; } }

	protected override void OnNavigatedTo(NavigationEventArgs e)
	{
		if (PageViewModel != null)
		{
			PageViewModel.Initialize(NavigationContext.QueryString);
		}
		base.OnNavigatedTo(e);
	}

	protected override void OnNavigatedFrom(NavigationEventArgs e)
	{
		if (PageViewModel != null)
		{
			PageViewModel.Uninitialize(e.NavigationMode == NavigationMode.Back);
		}
		base.OnNavigatedFrom(e);
	}

	protected override void OnRemovedFromJournal(JournalEntryRemovedEventArgs e)
	{
		if (PageViewModel != null)
		{
			PageViewModel.Uninitialize(true);
		}
		base.OnRemovedFromJournal(e);
	}
}

ViewBase is by no means required, but it is a nice piece of reusable code. Each page desiring to leverage the navigation framework must have a ViewModel derived from PageViewModel as its DataContext. ViewBase is responsible for knowing what to do with its ViewModel and when to do it. It knows that in OnNavigatedTo the ViewModel needs to be Initialized with the specified parameters, and that in OnNavigatedFrom and OnRemovedFromJournal the ViewModel needs to be Uninitialized and how. OnRemovedFromJournal is called on a Page when it is removed from the PhoneApplicationFrame.BackStack.

Conclusion

The CAS makes navigation more powerful and flexible. It’s simple to request navigation via the CAS and it’s reliable. The CAS does not replace existing navigation options, instead it builds upon the existing framework and extends possibilities. The CAS also makes navigation more reusable and readable inside ViewModels. I hope this post helps inspire innovation with Windows Phone.

WP7 Simplified: CoreApplicationService (Lifecycle)

In my post Simplyfying the Windows Phone Development Experience! Codename: LionHeart I explain that LionHeart is a demo app that I’m using to prove out a few lessons we’ve learned here at IK from our last Windows Phone project. In this post I will start to get into the meat of the app starting in a class named CoreApplicationService (CAS).

What is CoreApplicationService’s Purpose?

Event Forwarding

One of the purposes of the CoreApplicationService (CAS) is to expose events from across the app to ViewModels (VMs) or any other class that is not instantiated by App.xaml. This class acts, in a very simplified way, as an event aggregator. It is not, however, an event aggregator as found in Prism. Instead it’s more of a one to one event forwarding class. For example, in App.xaml there are two events named Deactivated and Closing. Therefore, in the CAS there are two identical events named Deactivated and Closing. When the event is handled in App.xaml.cs we simply forward the handling onto the CAS as show in this example:

public partial class App : Application
{
   private void ApplicationDeactivated(object sender, DeactivatedEventArgs e)
   {
       CoreApplicationService.Instance.OnDeactivated(e);
   }
}

Currently the events handled in the CAS are:

From App.xaml

  • Deactivated
  • Closing
  • Obscured
  • Unobscured
  • NavigationFailed
  • UnhandledException

From PhoneApplicationFrame

  • Navigating
  • Navigated

In all cases, the CAS acts as a forwarding system for any object the desires to subscribe to these events. In LionHeart those objects are usually VMs. This pattern allows the VM to be responsible for knowing when and what to do during these events. This pattern has made more and more sense as we’ve discussed possible solutions to our problem of telling VMs when to Deactivate (prepare for tombstoning) etc.

Error Reporting

Another responsibility of CAS is to prompt the consumer of the app to send error data to the developer. We found Little Watson created by Andy Pennell at Microsoft which simply collects unhandled exception information and stores it in a file in IsolatedStorage before the app closes. The next time the consumer launches the app they are prompted to send the error file to the developer, which they can choose to not send it if they desire. The error file is then deleted and the application will not prompt again until an error file exists again. This is so helpful I cannot even begin to express how many bugs we have been able to track down because of this tool. I want to start buffing this helper class out with logging since the error information we receive on the phone is not as helpful as it could be. Adding a logging feature that began each time the application was launched would be of even greater benefit.

Navigation

This purpose is what originally drove us to create the CAS. In fact we had originally named the CAS as NavigationService, but as it’s functionality increased and purpose morphed we decided that name was to specific and did not convey what we wanted. Navigation will be covered in greater detail in another post. In simple terms we use a dictionary of object to string mappings. Each string represents the Uri to a page. These mappings are set immediately after initializing the CAS as shown in the section below “How to use CoreApplicationService.”

public partial class App : Application
{
   private void InitializeNavigationMappings()
   {
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.HOME_VIEW_KEY, "/Views/HomeView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.MY_VIEW_KEY, "/Views/MyView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.ALL_CLIENTS_VIEW_KEY, "/Views/AllClientsView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.CLIENT_VIEW_KEY, "/Views/ClientView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.MY_REPORTS_VIEW_KEY, "/Views/MyReportsView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.REPORT_VIEW_KEY, "/Views/ReportView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.ALL_SESSIONS_VIEW_KEY, "/Views/AllSessionsView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.MY_SESSIONS_VIEW_KEY, "/Views/MySessionsView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.SESSION_VIEW_KEY, "/Views/SessionView.xaml");
       CoreApplicationService.Instance.Mappings.Add(ViewKeys.SETTINGS_VIEW_KEY, "/Views/SettingsView.xaml");
   }
}

In the example code above you will notice the use of ViewKeys which is a struct that contains string values that we use as keys. The key does not need to be a string instead it can be any object. Sometimes we will use typeof(object) for views that represent specific types. We found that strings were required for some views and decided to go with all strings for consistency. Remembering that VMs will be requesting navigation most of the time we did not use typeof(Page) as the key, because VMs should not have access to those types.

How to use CoreApplicationService

The CAS is provided via a static property of itself named Instance as a singleton. There are two times the CAS will need to be instantiated. The first is when the application is Launching. The second case is when the application is being Activated, but only if there is no application state. In both cases no VMs exist yet, therefore the CAS will not forward the Launching and Activating events because no object would or could receive them. Instead we use the events to initialize the CAS.

public class CoreApplicationService
{
   private static CoreApplicationService _instance;
   public static CoreApplicationService Instance
   {
       get { return _instance ?? (_instance = new CoreApplicationService()); }
   }
}

public partial class App : Application
{
   private void Initialize(bool isLaunching)
   {
       CoreApplicationService.Instance.Initialize(RootFrame, isLaunching);
       InitializeNavigationMappings(); //As shown in above section “What is CoreApplicationService’s Purpose?” and subsection “Navigation”.
   }

   private void ApplicationLaunching(object sender, LaunchingEventArgs e)
   {
       Initialize(true);
   }

   private void ApplicationActivated(object sender, ActivatedEventArgs e)
   {
       if (!e.IsApplicationInstancePreserved)
       {
           Initialize(false);
       }
   }
}

Initialize accepts two parameters: the PhoneApplicationFrame which is used for navigation, and a boolean indicating if the application is launching.

public class CoreApplicationService
{
   public void Initialize(PhoneApplicationFrame frame, bool isLaunching)
   {
       LittleWatson.CheckForPreviousException();

       _frame = frame;
       _frame.Navigated += FrameNavigatedHandler;
       _frame.Navigating += FrameNavigatingHandler;

       PersistTombstoningValue(IS_LAUNCHING_KEY, isLaunching);
   }
}

The reason for the boolean is for VM initialization. This will be explained in much greater detail later on, but for those curious minds out there during Activating (without state) when VMs initialize there are no navigation parameters. This is used as an indication that the application was tombstoned. Because this same state exists during Launching we must differentiate the two somehow. We got around this by adding a boolean to the tombstoning values that is checked for when no navigation parameters exist and indicates the application is Launching not Activating. As I stated before I will cover this in later posts in greater detail.

Conclusion

This concludes the introduction into the CoreApplicationService and how it plays into the lifecycle of the phone app. This service is the backbone to LionHeart and all phone apps that use it. As we cover navigation and how VMs integrate with this service you’ll understand why it is so important and why it is so helpful. As always if you have any suggestions for improvement, comments, or questions please post them. This is not meant to be a one man show, but rather a starting point for phone app architecture.

WP7 Simplified: Wireframes and Information Map

UPDATE 7/12: This post is part of a broad series helping to simplify the development experience of Windows Phone apps. The beginning of the series can be found here.

In architecture a blueprint must exist before a house or office complex can be built. Without the blueprint there would be mass confusion and little if anything would ever happen. The final product would be disaster. The same concept applies to software especially on the phone. If you just start coding the resulting app would struggle to be coherent or usable to the consumer. In order to prevent this we need some kind of software blueprint to help the developer stay focused and deliver what is desired and intended. Over the last 3 years here at InterKnowlogy I’ve come across a variety of ways to represent the flow and design of an application. I have gone from paper to whiteboards to Visio to combinations of all of the above and more. What I’ve discovered is the digital formats take too long to accomplish anything so they are more of a final design asset rather than the means to get to the desired result. Whiteboards are my preferred medium for sketching wireframes and information flow. Microsoft has one of the coolest examples of wireframes participating in the flow of information called an Information Map. The example image on the aforementioned site is not the highest quality, but it demonstrates the intended purpose.

Information Map

As I mentioned earlier I don’t like going to a digital medium because I feel it takes too long to make it worth while. But I am a huge fan of the whiteboard so I’m including am image of the information map of LionHeart that I created on a whiteboard. Thus, digitizing my whiteboard information map. It’s not beautiful but it conveys the idea clear enough that I feel little to no need to rework it using Visio or some other pretty digital designer.

There are just a few important items to mention here. First, the Windows Phone platform has some strict navigation rules namely the back button always goes back to the previous page. There are times this rule can be ignored such as when going to a settings screen and selecting save. Hitting the back button after selecting save should not return to the settings screen in most cases. Essentially any screen that is treated more like a modal dialog should not be returned to via the back button. These cases should be called out in the information map. Second, certain UI aspects should be called out such as multi-select lists, pivot or panorama control, or other controls using none intuitive interactions (based on a static drawing). Finally, remember that these information maps only take the UI aspect of the application into account. Do show the layout to some of your colleges or potential consumers and make sure the flow of the app cuts down on as many touches as possible to accomplish what is important. Once the information map is complete then it’s time to move on to the project structure and start coding!

Code Architecture

This is an entire different beast. I will not be covering this topic now. Perhaps at a future time. Admittedly, code architecture is one of those religious wars that I absolutely LOVE to discuss. For now I will only say that after you have an information map completed decide on what models exist and what VMs exist. Remember if commands will be used for buttons such as with the BindableApplicationBar that VMs should be used. Also, take into account if you will be using IsolatedStorage or the local application database. LionHeart is designed around IsolatedStorage for purpose of its demo.

Simplifying the Windows Phone development experience! Codename: LionHeart

Each time you start a new project one of the first things most of us developers do is pull in code we want to reuse. If we don’t have any existing code then we try to figure out how to leverage concepts and theories from past experiences and platforms. The latter is exactly what we did during the development of my last project, a Windows Phone project. We have a ton of XAML and MVVM experience here at Interknowlogy, and a few of us had done small RECESS phone apps. None of us had done a full blown app from scratch on the phone before, but today I can say we did an awesome job! What I want to focus on are the lessons we learned from that project and how to apply them to future phone projects to help simplify the process. My coworker Tim Askins and I spent a few RECESS discussing what we could improve on and and what we thought went well. The result is what I call LionHeart.

Introduction to LionHeart

LionHeart is a demo phone app that I am working on that is applying the code lessons learned. These lessons include application lifecycle, navigation, tombstoning, MVVM on the phone, how to provide mock data vs. real data, styling, and many more. The project it self is a demo based on work my wife does as a Behavior Interventionist (BI) for children with autism. We got talking about what could potentially simplify her line of work as well as provide a compelling demo app for the phone. The resulting app will allow for BIs to create reports that are currently done on paper, then transferred to another paper and placed in a binder, then that binder is driven to the main office once a month, and then driven back to the client’s home where BIs go when then work with the children. Wow, that was a mouth full. The app will also allow BIs to view their schedule of sessions for the day/week/month/etc. from within the application. The schedule will also be integrated into the normal phone calendar from Windows Live as well. Individual client information will also be available including previous reports, charts showing progress, and whether there will be a supervisor attending the session as well. Sound like a full blown app? I’m really excited to bring this app to life. I just wish it wasn’t just a demo app.

Components of LionHeart

Let’s remind ourselves again that the reason we are am creating LionHeart is to help solidify patterns and practices on the phone that will help simplify and speed up the development process of future phone apps. Since there are so many components to LionHeart I wanted to give a brief overview of what I think some of those components will be over the next few weeks.

Framework Components

Application Components

  • HomeVM
  • Navigating to Pages with a Pivot Control and to a Specific PivotItem
  • Calendar Integration
  • Styling

With that said as I complete each post I’ll update the list with links.

Final Thoughts

When all is said and done these components should provide a solid foundation for developing on the Windows Phone platform. If you have any questions or thoughts about how to improve on our design please let me know. Happy Coding!

Validation and Updating UI Values Based on User Input in MVC 3 Razor

I’m currently working on a project leveraging ASP.NET MVC 3 and the Razor View Engine. Wow, that’s a mouth full! This is some pretty awesome stuff. I’ve been extremely impressed with the capabilities of the framework, and I continue to be impressed the more I use it and learn it.

Remote Validation

One of the coolest features I’ve found in MVC 3 has been remote validation. What is remote validation? It is a way to leverage actions on a controller to validate user input on a model object. To use it you simply apply the RemoteAttribute to the property on your model that will be an input field in a form and specify the action and controller to use. A great example of how this is done can be found here on the msdn. What I like about this is the flexibility to have a validation controller per model on very small projects, or have a dedicated validation controller that calls model validator classes. The controller will only receive the value it should validate so each property should specify a different action on the validation controller regardless of which approach you take. I prefer the model validator approach because it allows me to reuse the validation logic when a form is submitted and I need to do one last validation before the model is persisted.

Updating UI Values Based on User Input

OK, so this sounds very confusing. So let me try to explain what I wanted to do. I have a list of Entry objects and each entry has a property of type EntryDefinition. Some entries are auto generated based on the value chosen for another entry, but all entries are always displayed to the user. If an entry is auto generated it is read only, otherwise it can be modified by the user. I needed a way send values entered by the user to the server, process them and generate the auto generated values, and then display the updated values the user. This was a pain to get working! I discussed the matter with my coworker Kevin Stumpf who has much more experience working in the web world. He helped me get on the right path to solve the matter.

First, was the challenge of getting the values written to the HTML file using Razor. A helpful Stack Overflow post showed me how to render a list of complex objects. Making sure I used Html.HiddenFor for all of the properties that were not displayed to the user took some getting used to. I kept receiving null values on the server side post in my model object and didn’t understand why at first.

Next, I need to get multiple submit buttons on my form. One button for for submitting the form and a new button for sending the model to the server for updating and updating the user’s display. There were a couple of options that I found after reading this post on Stack Overflow. That post linked to this post by Andrey Shchekin, which then led me to the post by David Findley that finally solved the problem best for me. The solution was to set the name property to button for each of the submit buttons. Then set each button’s value property to whatever made sense to the user, in my case “Update” and “Submit.” Then in the action handling the post I add a new parameter of type string named button. This maps to the name of the two buttons. The value the the button parameter will be the value of the button clicked by the user. Now in the action I could check if button equaled “Update” then don’t persist any data, generate any new values and update the model with those values then return View(model) and the user will see the new values and the other values they had input earlier.

After talking more with Kevin he added that I should just hook up to the text changed of the text boxes of the source entries using JQuery then update the auto generated values automatically as the user types. This would be awesome! If there is enough time on the project I will try this.

Conclusion

As I found from my searches there are a ton of articles out there on all this stuff. I just get so excited when I find cool stuff that I like to share. Hopefully something here is useful in your quest!

Bindable Application Bar (Attached Property) – Windows Phone 7

In a prior blog post I had created a Blend Behavior for creating a bindable ApplicationBar. The problem with the Blend Behavior is it seems to have a static instance that then attaches to multiple objects. It’s very confusing to me and I need to do a lot more research on Blend Behaviors. The result has been the creation of a BindableApplicationBar attached property.

I was able to repurpose the code I had written for the Blend Behavior. The new attached property is very simple. It has a collection of ApplicationBarIconButtonDelegate objects and a collection of ApplicationBarMenuItemDelegate objects. Long names I know, I’ll work on shortening those up. As soon as the BindableApplicationBar’s DataContext is set each button delegate’s and menu item delegate’s DataContext is set as well. At this point bindings kick in and based on visibility the BindableApplicationBar adds the delegates’ ApplicationBarIconButton or ApplicationBarMenuItem objects to the correct collections on the actual ApplicationBar. Confused? Let’s show some code.

Hooking up the attached property looks like this:

<Code:BindableApplicationBar.BindableApplicationBar>
	<Code:BindableApplicationBar>
		<!--NOTE: The ability to add more than 4 buttons and change their state based on binding. 
				If they are visible then they are added to the app bar, otherwise they are removed from the app bar.
			IMPORTANT: Always change the visibilty of the buttons in the app bar before those not in the app bar
				and avoid having 2 buttons bound to the same property for visibility-->
		<Code:BindableApplicationBar.ButtonDelegates>
			<Code:ApplicationBarIconButtonDelegate IconUri="/Images/appbar_button1.png"
													Text="{Binding TextCommandHeader}"
													Command="{Binding ChangeTextCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Increase"
													Command="{Binding ChangeNumberCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Toggle"
													IsVisible="{Binding CanToggleCanChangeNumber}"
													Command="{Binding ToggleCanChangeNumberCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Hide"
													IsVisible="{Binding CanHide}"
													Command="{Binding HideToggleCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Show"
													IsVisible="{Binding CanShow}"
													Command="{Binding ShowToggleCommand}" />
		</Code:BindableApplicationBar.ButtonDelegates>
		<Code:BindableApplicationBar.MenuItemDelegates>
			<Code:ApplicationBarMenuItemDelegate Text="Random Number Text"
													Command="{Binding ChangeTextMenuCommand}" />
		</Code:BindableApplicationBar.MenuItemDelegates>
	</Code:BindableApplicationBar>
</Code:BindableApplicationBar.BindableApplicationBar>

Once the DataContext of the BindableApplicationBar and all delegate objects are set this code gets run:

private void Initialize(object dataContext)
{
	if (DataContext == dataContext)
	{
		return;
	}

	DataContext = dataContext;

	foreach (var buttonDelegate in ButtonDelegates)
	{
		buttonDelegate.DataContext = DataContext;
		if (buttonDelegate.IsVisible)
		{
			AddAppBarButton(buttonDelegate.Button);
		}
		buttonDelegate.IsVisibleChanged += AppBarButtonIsVisibleChangedHandler;
	}

	foreach (var menuItemDelegate in MenuItemDelegates)
	{
		menuItemDelegate.DataContext = DataContext;
		if (menuItemDelegate.IsVisible)
		{
			AddAppBarMenuItem(menuItemDelegate.MenuItem);
		}
		menuItemDelegate.IsVisibleChanged += AppBarMenuItemIsVisibleChangedHandler;
	}

	UpdateAppBarVisibility();
}

Something that I CANNOT find anywhere, which then became my motivation for writing my own BindableApplicationBar was the ability to have Visibility of the buttons and menu items bound as well as IsEnabled. I added an IsVisible property that drives whether or not the button or menu item is added to the ApplicationBar. Super simple. Also, the delegate objects subscribe to their object’s click event. So one could using Commands and binding, click handlers, or both just like on a normal button.

ApplicationBar.Opacity Fact

Here is an interesting fact for you. The property ApplicationBar.Opacity is 1.0D by default. What I recently learned is that the ApplicationBar.Height is 72px and if Opacity is 1 then the ApplicationBar actually takes up space in the layout of the page. However, as soon as the Opacity is .999D or not equal to 1 then the ApplicationBar no longer participates in the layout of the page. This was a pretty big bummer to the project I’m on since we need to manage our ApplicationBar quite a bit. Wait animations were starting in one spot then moving down after the ApplicationBar would hide. It was very confusing why this was happening until I read about this behavior in the documentation.

So what does all that have to do with the BindableApplicationBar here? Opacity by default is now .999D in order to have a consistent feel across the app. Why .999 not just .9? If .9 is used the ApplicationBar is noticeably transparent, however .999 looks completely Opaque.

Known Issues

The biggest issue I’m aware of right now is the possibility to try and add more than 4 ApplicationBarIconButtons to the ApplicationBar. If the developer adds 5+ button delegates they need to be very careful about managing the visibility of the buttons. Only 4 buttons can be added at a time. The 5th will throw an exception. I’m working on a solution for this, but for now the current version works well enough.

Another nice to have would be the ability to specify permanent order. Currently if 4 buttons are visible and the first is removed (visibility change) and later is readded it will now be the last button. The solution I’m toying with for the above issue would also allow me to fix this one fairly easy as well.

The last major known issue is that DataContext must be set. This means that if the page does not have a DataContext then the the BindableApplicationBar.DataContext property should be set to a string such as BindableApplicationBar.DataContext=”a”. This will cause the logic in Iinitialize(object dataContext) to run (found above).

Sample Code

Finally, the stuff everyone really cares about. Feel free to do whatever you want with the code. I’d love to hear if you’re using it and any feedback you have about the code. Hopefully this is helpful.

BindableApplicationBar Sample Code

Windows Live SDK for Windows Phone 7 – SoCal Code Camp Presentation (1/28/2012)

This was my first time presenting at any code camp. I’d like to thank those that attended and participated. They made the experience very enjoyable. You can download my slide deck here. I hope you find the information useful. Please let me know if you need any links that are not included in the slide deck.

Summary

Interest in the Windows Phone 7 platform is growing quickly and the need for apps is increasing faster still. However, not everything related to a consumer’s Live profile is available on the phone natively. On Dec. 7, 2011 Microsoft released a new Windows Live SDK which allows access to Calendars, Contacts, Documents, and more. We’ll be walking through the SDK and learn how to implement calls to Windows Live in order to support the rich functionality desired by consumers of Windows Phone 7.

Cheers and Happy Coding!

Bindable Application Bar (Blend Behavior) – Windows Phone 7

UPDATE 2/22/2012: After fighting with this for over a week and wasting more hours than I thought possible I made a discovery about Blend Behaviors. It seems that Blend Behaviors have a static lifetime. They attach and detach to objects as they come and go, but the instance seems to be static. I discovered this when the value of my Dependency Property was being reused by all instances. Not to mention I made the mistake of newing up a collection as the default for my Dependency Property, thus creating an undesired singleton. After all has been said and done. I switched over to an Attached Property approach. This approach has worked like a charm. You can read about and get the sample code for the new approach here.

Many have claimed to have created a bindable ApplicationBar for the lacking Windows Phone 7 OS. After hours of searching for one that would fit my needs I discovered that they are all lacking or not implemented in a way that was sufficient for my needs. I set out to create my own implementation with the help of Tim Askins and Travis Schilling. What we came up with was not an ApplicationBar replacement or derivative, but a new behavior that can be added to any page in XAML. Note this is NOT an attached behavior. We are inheriting from Behavior<T>.

Why a behavior?

Behaviors have no UI. If we were to use any kind of Control derivative the created control would allow placement anywhere in the UI tree. It would need to do extra work to traverse the tree and find the page as well. This also means that it could potentially be part of a UI tree that was invalid. This concept did not make sense to us. By using a Behavior we force the developer to place the behavior as a first class citizen of any page, and it is restricted to PhoneApplicationPage, but would work with derived pages as well. The behavior is also not part of the UI tree.

Any problems with using a behavior?

The behavior is designed with a collection of ApplicationBarIconButtonDelegate objects. These objects expose many of the same dependency properties which a normal button would expose such as IsEnabled, Command and CommandParameter. They also expose an IsVisible and an IconUri property. However, when these objects are being bound to in XAML they live inside of the behavior. This seem like a no brainer, one just needs to remember that means there is no DataContext to pass around. This was easily overcome by setting the page’s DataContext as the DataContext of each button in the override of the OnAttach method. Once this was done each button delegate was able to bind as expected. In the current implementation we do not handle the case where a page does not have a DataContext, however this would be easily overcome by adding an optional DataContext DependencyProperty to the behavior.

Where’s the code?

After testing the code a bit more I will post up what we have created. Assuming all goes well that will be next Wednesday or sooner.

Win Live Helper for Windows Phone 7

Today I’m proud to announce the home of WinLiveHelper on codeplex. The purpose of this library is to provide lightweight objects and the http calls required to easily interact with the Windows Live SDK that was released 7 Dec 2011. I will be starting with Calendaring and then moving to Documents. After that we’ll see what priorities come up. If you’d like to help out let me know!

Windows Phone 7 – Windows Live SDK

UPDATE 2/22/2012: As mentioned under the section Thoughts I have created a Codeplex project called WinLiveHelper. You can read more about it in this post.

Talk about good mojo! 7 days ago I was I was researching how to access Windows Live and SkyDrive from my Windows Phone 7. It just so happened to be the release date of the brand new Windows Live SDK that day, 7 Dec 2011. I now get the privilege to blog about my discoveries. Most of what I found is really good stuff. I’m going to let Microsoft do the heavy lifting on this one since their samples are quite good.

What is the Windows Live SDK?

The Windows Live SDK is a brand new SDK that encapsulates OAuth2 calls and the building of HTTP requests for Windows Live services. The SDK is very light and does not include model objects for calendars, files, etc. Microsoft has provided us with a Live Interactive SDK that walks through some of the available calls and allows the user to experiment with the JSON used.

What can I Access?

The documentation of what is available via the SDK is very comprehensive. The REST API is the one that I looked at. I’d feel like a member of the Redundant Department of Redundancy listing all of the capabilities of the API, so I’ll only mention a few: Albums, Audio, Calendars, Contacts, Folders, Files, Photos, and Videos. OK, so that’s most of them, but I’ll only talk about a few in specifics here.

Calendar

The Calendar portion of the API allows the developer to access all of the Calendars that the user has referenced in Windows Live. The developer can create, read, update, and delete a calendar. The developer can also create, read, update, and delete events on any of the calendars based on that user’s permissions on that calendar. This is a welcome API on the phone since developers can only read calendars and events in the current version of the OS.

SkyDrive (Folders and Files)

The same create, read, update, and delete capabilities that exist for calendars and contacts also exist now for SkyDrive. What I’m still working on is how to use SkyDrive to open a document on the phone from inside of a third-party application (not the Office Hub). Currently the phone only supports a Photo Chooser which cannot view Videos. I have a need to attach Videos and Files to a piece of information, and with the release of the Windows Live SDK developers can now access any uploaded file (video, audio, document, spreadsheet, etc.) that lives SkyDrive.

Thoughts

I’m hoping to create a light library of model objects that will work with JSON.NET for the phone that I’ll be able to pair with the Windows Live SDK. I’m very excited about the simplicity of the APIs and SDK. I’ve heard the horror stories of integrating Windows Live into an application prior to this SDK and set of APIs.