Under the Hood with Windows Universal Projects

One of the main themes coming out of the keynotes and content at this year’s //Build 2014 conference was the continued convergence of the Windows Store and Windows Phone development platforms.  One exciting result of the fact that both these platforms now target very similar Windows Runtimes (WinRT and WinPRT, respectively) is the support for the new “Universal Apps” in Visual Studio 2013 Update 2.  (Another exciting result is that the “Programming the Windows Runtime by Example” book that Jeremy Likness and I wrote is even MORE relevant!) Projects created using the Universal App templates in Visual Studio include primary projects for each targeted platform as well as a shared project whose content “magically” gets included into each of the head projects.  Currently, only Windows 8.1 and Windows Phone 8.1 primary projects are supported, though apps targeting the Xbox One will one day be included, and Xamarin has indicated they’d be joining the fun soon. image
A Universal Apps Solution, showing Windows, Windows Phone, and Shared projects

I won’t spend a ton of time discussing the “how-to” aspect of Universal Apps projects – Jeff Prosise has published a series of blog posts that present the basics of working with those projects:

I want to focus on the mechanisms working behind-the-scenes that enables these things to work.  How does the Shared content make its way into the app projects in the solution, and why does it behave differently from other sharing mechanisms?  I find that understanding the inner workings of things leads to better decision making when employing them…perhaps that’s why I enjoy reading Jeff Richter’s books.

Where did they put the hood latch on this model?

So what is going on under the hood on these projects?  To understand that we need to get inside of the projects themselves.  Remember that most of the Visual Studio project files you work with (csproj, vbproj, etc) are actually MSBuild XML files.  You can examine this yourself by either opening the project files directly in a text editor (enhanced editors like Notepad++ or Sublime Text offer a better visual experience than good-old Notepad, but in a pinch, Notepad does work.)  You can also examine the inner content of a project file from Visual Studio itself with the following steps (or see here):

  • Right click on the project you want to work with in the Solution Explorer and select Unload Project
  • Right click on the project again and click Edit <ProjectName>

Regardless of what editor you choose to use, the content of your project files will follow the MSBuild Project File XML schema that is described here.  One of the jobs of the Visual Studio IDE is to properly maintain the various MSBuild schema elements as you add, remove, or rearrange items within your projects, but nothing prevents you from doing that manually, and there are actually a few MSBuild “tricks” that you can take advantage of that aren’t provided by the Visual Studio IDE.  Keith Rome has a blog post covering Wildcard Inclusions in C# Project Files that takes specific advantage of this capability.

Pay no attention to that man behind the curtain!

With one of the application project files open for XML editing, you can start to explore the magic of the Shared project.  Scroll down to the bottom of the file and locate the Import element that includes the attribute ‘Label = “Shared”’”:

<Import Project="..\UnderTheHood.Shared\UnderTheHood.Shared.projitems" 
Label="Shared" />

The purpose of the Import Element is to bring the contents of one project file into another project file, and a quick check of the MSDN docs suggests that it’s been around since at least .NET 2.0!  In this case, it is bringing in the contents of a file with a projitems extension from the shared project’s directory.  Note however that this file is NOT the shproj file that defines the Shared Project! (What gives?!) image
The Shared project extension is actually NOT what is referenced in the project files’ Import Element!

NOTE: You may also want to notice that there’s a Root Namespace property.  Setting this value determines the namespace that is given by default to new code files created within this shared project.

The projitems file is what the shared project creates/maintains.  If you open a File Explorer window to the Shared project file location, you will find this file.  Opening the file in a text editor (you can’t open it in Visual Studio while the shproj file is loaded, since it is already being referenced) will show that it is just another MSBuild file that includes the files that have been added to it  (if your text editor supports change notifications, add a new file to the Shared project while the projitems file is opened in the text editor and notice that when you save the project, the projitems file will be updated.)

So as you add, remove, or manipulate items in the shared project, the contents of the projitems file is updated, and this file’s contents in turn are simply incorporated into your app project files via the Import elements in their MSBuild XML.  This is why you can use #if declarations that are scoped to one project or another to differentiate behavior.

But wait, there’s (partially) more!

Remember that there’s more that you can do to affect your shared files’ integration behavior than simply throwing a bunch of #if and #else blocks throughout the shared code (ew!).  Don’t forget about partial classes and their often-overlooked cousins, partial methods. Partial methods first came on to the scene as a tool to allow developers to introduce code that strategically extended designer-generated files without having to worry about designer regeneration obliterating their code without having to create subclasses and override virtual methods.  When a partial class includes a partial method, private methods can call into that partial method, and partial extensions can choose whether or not to provide an implementation of the partial method. Wait…what?  Perhaps an example. I’ve added a new class to the shared project:

namespace UnderTheHood
{
    public partial class PartialClass
    {
        public void DoSomethingInteresting()
        {
            DoSomethingPlatformSpecific();
        }

        partial void DoSomethingPlatformSpecific();
    }
}

Note the lack of implementation for the DoSomethingPlatformSpecific method. Now in the Windows 8.1 project I’ve provided an implementation of the DoSomethingPlatformSpecific method:

namespace UnderTheHood
{
    public partial class PartialClass
    {
        partial void DoSomethingPlatformSpecific()
        {
            Debug.WriteLine("I am a Windows 8.1 implementation.");
        }
    }
}

And a slightly different implementation in the Windows Phone 8.1 project:

namespace UnderTheHood
{
    public partial class PartialClass
    {
        partial void DoSomethingPlatformSpecific()
        {
            Debug.WriteLine("I am a Windows Phone 8.1 implementation.");
        }
    }
}

Now calling the public DoSomethingInteresting method will call into whatever platform-specific DoSomethingPlatformSpecific implementation is in the current project, allowing for platform-specific customizations to occur in the platform-specific projects, rather than mixing them in the shared projects with #if and #else statements.  If new platforms are added to the Universal Project “universe” (sorry), you don’t have to worry about the #if statements becoming these big messes that include a lot of code that is greyed out by Visual Studio depending on which project it thinks is currently in scope. Bear in mind that partial methods differ from abstract methods in that they do not have to be overridden/implemented.  If no implementation is provided, the call into the partial method won’t fail or cause any negative side effects…it is simply a no-op.  As a consequence, there are a few rules to follow when working with partial methods:

  • They must return void (if they had return types, an implementation would be required)
  • That can have ref parameters, but not out parameters (if no implementation is provided, the ref parameter is unmodified)
  • Partial methods are inherently private in scope.
  • They can be static, and can be generic.
  • Delegates can only refer to implementations of static methods.

The bottom line

So hopefully now you have a better understanding of how these magical new shared projects work in Visual Studio.  Much of the technology they use has been in the DNA of our project files for a while.  Visual Studio 2013 Update 2 has been enhanced to include some nice new IDE updates in order to surface these features in a way that makes them very useful for writing reusable code.  This new compile-time reusability combines quite nicely with the post-compile reusability that is offered by Portable Class Libraries. If you want to learn more about them, Jeff Prosise will be delivering a session on universal apps at the Software Design & Development conference in London next month. The talk will delve into what universal apps are and how they’re structured, and he promises to have plenty of samples to share as he goes over the ins and outs of writing apps that target separate but similar run-times.  You might also benefit from watching Jeff’s video entitled Introduction to WinRT on WintellectNOW. If you’re not already a subscriber, you can sign up with the promo code Garland-13 and enjoy two weeks of access for free. Also, did I happen to already mention that Jeremy Likness and I had written a book about using the Windows Runtime?

Advertisement

Managing Windows Azure Mobile Services (WAMS) Server Scripts with Microsoft Visual Studio Tools for Git

Windows Azure Mobile Services (WAMS) has come a long way in a few short months.  At the 2013 Build conference in San Francisco, Microsoft announced more than the service’s General Availability date – it also showed that the service had been integrated into the Visual Studio 2013 Preview in several key places.  These included a “Connected Services Manager” that will augment an existing project to connect with a new or preexisting WAMS instance, an entry for WAMS in the Server Explorer panel that allows viewing and editing the server-side data table business logic scripts (with access to the other WAMS script elements expected to be added over time), and a Push Notification Wizard that facilitates connecting an existing Windows Store app to a WAMS instance.  These features are detailed in this post on the Visual Studio Blog.  The expectation is that these integration points are expected to be enhanced as Visual Studio 2013 is updated to its RTM version.

One of the more recent features added to WAMS itself has been the integration of Git-based source control for the server scripts (as of this writing, this feature is currently in Preview.)  This integration provides several advantages for managing a WAMS service’s scripts.  First, it allows for scripts to be edited locally /offline using desktop file editing tools, including Visual Studio.  Changes can be managed through the local Git repository until they are ready to be synchronized to the server.  What’s more, this arrangement also allows access to some of the WAMS script-related content that is not (presently) available through the WAMS management portal (though access to these files can also be obtained from the command-line management tools.)

To mostly round out the collection of the tools will be discussed here, the Team Foundation Server Power Tools team at Microsoft has released the Visual Studio Tools for Git, which is an extension that allows Visual Studio’s Team Explorer to integrate with Git.  This integration includes using the Team Explorer GUI to manage and connect to local repositories, as well as to track changed elements in a selected repo, and managing branches, commits, and syncs in that repo.  As of this writing, the extension is at version 0.9.5.

This post will explore how the new integrated Visual Studio tools for Git can be used to provide GUI-based source-controlled management for client-side editing of the scripts belonging to a Windows Azure Mobile Services instance.

Enabling Source Control in a WAMS Instance

The first step in the process is to enable Git Source Control for the account which owns the WAMS instance, if it has not already been set up for that account.  This process is documented here.  Basically, the steps entail:

  • – If this is the first time a Mobile Service Git repository is being set up for the current Azure subscription:
    • – From the WAMS Management Portal “Dashboard” page for the desired service, select “Set up source control”
    • – Provide a username and password to be used for access to mobile service Git repositories within the subscription.  These credentials can be changed later by selecting the “Reset your source control credentials” link on a WAMS Dashboard page for any Mobile Service attached to the same subscription.
  • – Copy the Git URL from the service instance’s Configure tab.

image

Connect to the Git Repository from Visual Studio

The next step is to connect to the server-side repository that was just created and clone it to the local machine.  This (and many of the remaining steps) can be accomplished via several Git tools, including the command line, but the focus here is on using Visual Studio (for the most part, I prefer to leave the command line to build scripts and for hacking into the Matrix.)  Once the Visual Studio Tools for Git extension has been downloaded and installed, open Visual Studio 2013 and select the Team Explorer pane (if necessary, it can be found in the View menu.) 

Select Connect (the icon looks like a the male end of a 2-prong extension cord)

image

In the ensuing Connect dialog, select Clone to do the initial setup of the local repo as a clone of the server repository.  This will show a couple of text boxes – the top one is used to provide the URL to the remote repository – paste the URL that was copied earlier from the WAMS Management Portal.  In the second one, type in or browse to the local directory path into which the repository should be cloned.

image

When you press the Clone button, you will be prompted for your server-side Git repository credentials.

image

…and after entering these credentials, you will have a local clone of the WAMS repository.

Examining the WAMS File Structure and Script Files

If you right-click on the new repository entry in the Team Explorer Connection Panel, you will see context menu options which include one for opening the repository in File Explorer.

image

 

The folder you open will contain a file and single subfolder titled “service”.  Within the service folder are the folders that contain the WAMS script content.  These folders and their purpose are listed below:

  • api: contains 2 files per Custom API defined in the WAMS portal.  The first file is a JavaScript (api name.js) file containing the script itself and the second is a JSON metadata file (api name.json) that describes the permission level required for each custom api script action.
  • scheduler: contains a JavaScript file (scheduled job name.js) for each defined scheduler script.
  • shared: contains scripts and/or Node.js modules that can be reused by other scripts in the service instance.  Note that there is no browser in the portal (at present) for files in this folder.
  • tables: contains between 1-5 files per defined table in the WAMS instance.  These files minimally include a JSON metadata file (table name.json)  For any modified table action script (read, insert, update, delete), there is also a corresponding JavaScript file (table name.operation.js)

Note #1: Each folder also includes a text md file that describes the intended contents of the folder and any layout constraints for each file. 

Note #2: For the most part, with the exception of the “shared” folder, the files should be “seeded” by creating the desired named item server-side and then syncing the repository.  WAMS often has to spin up other infrastructure elements in addition to just the scripts, such as database tables and entries for the scheduler. 

For Table scripts, the table can be created in the Visual Studio Server Explorer, but the individual table operation script files won’t be brought down by a Sync operation until the corresponding scripts is modified in some way – the change can be as simple as adding a comment.  Once the file has been altered and saved to the server, using Sync will fetch the file to the local repository.  The WAMS instance context menu (with the Create Table option) in the Server Explorer is shown below, along with a script that has been modified with nothing but a comment.

image              image

The screenshot below shows after the file above has been saved to the server from within the Server explorer, after doing a Sync of the Git repositories, the local folder has been updated with the table’s corresponding read script file.

image

Note that generating files this way is probably best left only for initially “seeding” the files, thus leaving day-to-day editing to an operation that is covered by source control and includes change tracking, etc.

Working with the Visual Studio Git Tools

From the Connections panel, opening one of the repositories (double-click or right-click and select Open) displays the Home panel for the selected repository.

image

Once the necessary files have been synced to the local repository, the files within the folders in the repository can be edited on the local machine and the changes will be tracked by Git.  These changes can be seen in Visual Studio by bringing up the Changes Panel.  In the illustration below, the “read” script file for the “blogdemo” table has been modified locally (in fact, it was opened in Visual Studio and edited there to take advantage of Visual Studio’s JavaScript editing tools.  Any text editor could have been used, however.)

image

Note that there’s also an entry for “demosharedcontent.js” in the Untracked Files listing.  To include the file, simply drag it (or its containing folder) up and drop it in the “Included Changes” section:

image

Once the collection of changed files that is to be committed to the local repository is ready, a commit message (comment) can be entered and the Commit button can be pressed.  Pressing the Commits link from this panel, returning to the home panel and selecting the Commits button, or selecting the Commits pulldown at the top of the TFS explorer will show the current set of outgoing and incoming Commits available for Syncing with the Server.

image

Pressing the Sync button once again synchronizes the script changes with the WAMS service.  Examining the table script in the WAMS Management Portal shows that the change in fact has been uploaded to the server:

image

If the Sync results in conflicts that Git cannot resolve, (the same word was changed both in the client and the server, for example) the Sync will indicate so, and a list of conflicts will be displayed:

image

The conflicts can be examined in detail and adjusted using the 3-way merge tool that comes with Visual Studio (with apologies for my typos):

image

Once the Merge is committed, it can be synced to the server.

The final working panel that hasn’t been shown yet is the Branches panel, which allows management of branches in the selected local repository.

image

Wrapping Up

While Windows Azure Mobile Services currently benefits from several points of integration into the Visual Studio 2013 IDE, the addition of the Visual Studio Tools for Git offers an additional tool to help with the management of server-side scripts.  For what it’s worth, the Visual Studio Tools for Git also works with Visual Studio 2012, and supports the same kinds of source control management as was shown here in Visual Studio 2013 Preview, except that Visual Studio 2012 lacks the additional WAMS integration points such as the entry in the Server Explorer.  Nonetheless, look for the integration of these tools to become even richer as WAMS, Visual Studio 2013 , and even the Visual Studio Tools for Git are enhanced over the next few months.

Using the New Caller Information Attributes for Reliable Property Change Notifications

As anyone who has implemented the INotifyPropertyChanged interface knows, the fact that the PropertyChangedEventArgs takes a property name as a string means that you are one fat-fingered mistake away from a bug that can sometimes be difficult to track down.  If the property name supplied in the string doesn’t match the actual property name, the data binding (or other operations) that relies on this interface doesn’t work properly.

   1: public Int32 MyProperty

   2: {

   3:     get { return _myProperty; }

   4:     set

   5:     {

   6:         if (_myProperty != value)

   7:         {

   8:             _myProperty = value;

   9:             OnPropertyChanged("MyProperty");

  10:         }

  11:     }

  12: }

Lambda expressions and Expression Trees in .Net 3 brought a solution to the problem, where the compile-time checking could help ensure that a correct value was provided.  I blogged about this back in 2010 (https://blog.dotnetgator.com/2010/06/21/finding-binding-trouble/), and even cited my (then-future) coworker Jeremy Likness’s treatment of the same topic (http://csharperimage.jeremylikness.com/2010/06/tips-and-tricks-for-inotifypropertychan.html).

   1: public Int32 MyProperty

   2: {

   3:     get { return _myProperty; }

   4:     set

   5:     {

   6:         if (_myProperty != value)

   7:         {

   8:             _myProperty = value;

   9:             OnPropertyChanged(() => MyProperty);

  10:         }

  11:     }

  12: }

Now there’s a new feature in .Net 4.5 that provides yet another opportunity to ensure that INotifyPropertyChanged is implemented correctly – possibly in a simpler fashion than ever before, and with better performance than the Expression Tree/Lambda expression approach.

.Net 4.5 includes 3 new “Caller Information” attributes  – CallerFilePathAttribute, CallerLineNumberAttribute, and CallerMemberNameAttribute.  These three attributes are scoped to individual method parameters, and when used, they apply the indicated value from the CALLING METHOD to the called method’s attributed parameter at run time.  In our case, we’re interested in the CallerMemberName attribute, which we can use to automatically retrieve the property that is trying to raise the property change notification:

   1: private void OnPropertyChanged([CallerMemberName] String caller = null)

   2: {

   3:     var handler = PropertyChanged;

   4:     if (handler != null)

   5:     {

   6:         handler(this, new PropertyChangedEventArgs(caller));

   7:     }

   8: }

Note that the Caller Information attributes require a default value be supplied.

This reduces the overhead of a property in the class that provides this method to the following:

   1: public Int32 MyProperty

   2: {

   3:     get { return _myProperty; }

   4:     set

   5:     {

   6:         if (_myProperty != value)

   7:         {

   8:             _myProperty = value;

   9:             OnPropertyChanged();

  10:         }

  11:     }

  12: }

Of course, one important question is how does this method perform in comparison to either just providing a string, or using the Lambda/Expression Tree approach?  In my tests with iterations of between 1,000-500,000 property changes I saw between ~10-30% performance improvement over the Lambda/Expression Tree approach, and performance between ~20-30% lower than using a directly supplied string.

Note that the latest version of the MSDN documentation illustrating the implementation of the INotifyPropertyChanged interface (as of this writing) show the use of the CallerMemberName attribute – http://msdn.microsoft.com/en-us/library/ms229614(v=vs.110).aspx

DevBoston (Waltham) Presentation Content

Many thanks to the attendees of my presentation tonight covering Developing Cloud Enabled Windows Phone Applications with Windows Azure.  I apologize once again for the technical network-related gremlins that decided to attack us tonight…hopefully the workaround covered the necessary ground and everyone was able to see the concepts I was trying to show.

As promised, I have posted the content for the presentation here.  This includes the slide deck with the various resource links, as well as the final project.  As I mentioned, I have “sanitized” the configuration of the project to omit my specific Access Control (ACS) settings.  This involved changing the AccessControlResources.xaml file in the phone project and the Web.config file in the web role project.  Look for the text [your-xxx-here] for where to substitute your own ACS information.

Because the network issues prevented us from accessing the NuGet site or repository, I wanted to be sure to list the packages that were used in these projects:

Phone.Storage Adds support in the phone project to access Azure Storage.
WindowsAzure.Storage.Proxy.AccessControl Adds support in the server-side MVC3 based web role to field secured storage requests using ACS to generate the authentication token
Phone.Storage.AccessControl Adds support in the phone project for interacting with ACS-secured storage, including a login page with the ACS-aware login control.
WindowsAzure.Notifications Adds support in the server-side MVC3 based web role to handle registration & storage for Push Notification endpoints
Phone.Notifications.BasePage Adds support in the phone project (including a UI page) for enabling notifications in the application and registering with server-side push notification endpoint.
MPNSRecipe Adds the MPNS Recipe, used in the worker role project.

Boston .Net Code Camp Presentation Content

I would like to thank the organizers and attendees of the recent 16th (wow!) Boston Code Camp where I did a talk on Developing Cloud-Enabled Windows Phone Applications with Windows Azure – and special thanks to everyone who stuck it out once the snow started falling in order to catch my talk.  Obviously, it took longer than expected to get this content posted – Nashua got hit especially hard by the storm, including a 75% city-wide power outage the day following the Code Camp event, along with accompanying telecom and even cellular outages.  I am happy to say that I finally got my power turned back on mid-week, and am slowly but surely digging out of the mountain of backlog that piled up during the multi-day outage.

The content can be found here.  Because I demoed ACS, some of the items that are placed in the project would normally reference my “real” Azure account…they have been removed and replaced with the phrase “YOUR CONTENT HERE.”  You will need to replace these values with your own from the Azure ACS management portal in order to be able to run the provided code.  Also, in order to use the Azure Emulator, be sure to run Visual Studio in Admin mode when working with this project.

Boston Azure User Group Presentation Materials

Many thanks to the organizers and attendees of the Boston Azure User Group where I had the chance to speak this past week on Developing Cloud-Enabled Windows Phone Applications with Windows Azure.  I hope everyone who attended enjoyed the presentation as much as I enjoyed doing it.  I certainly appreciate everybody having stuck through considering the A/C glitch causing the room temperature to get a little uncomfortable.

Speaking of weather, I think my house is now as prepared as it is going to be for the upcoming arrival of hurricane Irene to New Hampshire…I really didn’t think I’d be dealing with these anymore after my 15 years in Florida – that we “paid our dues” in New England with our annual rounds of Nor’easters and other winter “fun.”  Nonetheless, the slide deck and code from the presentation have been posted, and can be found here.

The sample code is broken into 5 parts across 4 solutions as follows:

  1. Membership (Windows Azure Toolkit for Windows Phone)
  2. Storage (Windows Azure Toolkit for Windows Phone)
  3. Notification Services (Windows Azure Toolkit for Windows Phone)
  4. AppFabric Service Bus
  5. OData (Azure Data Marketplace and SQL Azure)

Key “markers” have been placed into the code files as comments that start with the word “NOTE” (a handy way to see *most* of them is to make use of the Visual Studio Task List pane, however, there are a few in the config files that don’t get picked up by this pane.)  The code has been sanitized to point to local storage and/or to remove any keys I had put in that were specific to the sites and accounts I was using for the demo.  Please substitute your own private values where necessary.

New England Code Camp 15 Presentation Materials

I have uploaded the content from my talks at yesterday’s (5/7/2011) New England Code Camp 15.  I had two talks – Introduction to Windows Phone 7 Development with Silverlight and Advanced Windows Phone 7 Development with Silverlight.  The content for my first talk can be found here, and the content for the second talk can be found here.  The content includes:

  • Presentation slides, which include the reference links I mentioned during the talk.
  • The sample code.  In the second presentation I discussed the Bing Maps control.  I have removed my Map Key and replaced it with the text “YOUR_KEY_HERE.”  To remove the licensing warning that appears when running the project, be sure to get an application key from the Bing Maps Developer Portal and replace the temporary text.

After having done various phone talks over the past year, I decided I needed to overhaul the content prior to this presentation.  This was done both in order to relate the contents of the presentation to something that more closely resembled an actual app, as well as in anticipation of including the upcoming “Mango” content.  I think the presentation got closer on those fronts, but it still needs some tuning (especially the first half, which ran a bit long…my apologies to the attendees for having to rush through some of the material.)

I have also discovered an interesting defect in the application that occurred after adding the code to handle saving page-state when the app is tombstoned.  What happens is that the closing of the DatePicker control (from the Silverlight for Windows Phone Toolkit) sets the value of the property before an OnNavigatedTo event is called, which resets the value to what was serialized when the control first appears.  The net result is that the DatePicker control ceases to change the date.  I included a quick fix for this in the code published above, and will be taking a deeper look at this control in the coming days, with a more thorough post to follow.

LightTouch Enhancements–Popups and “Layered” Controls

While I am actively working on adding new functionality to the LightTouch library (such as adding the Pinch Gesture to bring parity with the GestureListener for Windows Phone from the Silverlight for Windows Phone Toolkit) for an upcoming release, a couple of issues came to light that made adding a new release appropriate.  As the title of this post suggests, these issues relate to support for touch in Popups (especially ChildWindow controls) and for controls where different layers of the control’s visual tree make use of different behaviors.

Support for Popups / Child Windows

At the heart of LightTouch is the Manipulation2DBehavior.  Much of the functionality behind this behavior is discussed here.  One of the basic methods’ responsibilities is to determine, based on the coordinates of the touch event, what controls are under that point and which of those controls have the Manipulation2DBehavior attached.  To do this lookup, the VisualTreeHelper.FindElementsInHostCoordinates function is used, with Application.Current.RootVisual supplied for the relative UIElement.  This is where difficulty with popups occurred.  Popup controls exist outside of the Visual Tree of the application’s RootVisual.  This can be seen in the following UI, with its Visual Tree as reported by Silverlight Spy.  Note how the Popup control appears as a sibling to the MainPage element.

image

image

So in order to locate the controls with behaviors in the popup, we have to use the Popup as the relative UIElement for the call to VisualTreeHelper.FindElementsInHostCoordinates.  Now to find the popup in the Visual Tree…this can be accomplished with the VisualTreeHelper.GetOpenPopups call.  Unfortunately, this call does not document how the list is populated relative to the Z-order of the ChildWindow (in case multiple ChildWindows are being displayed, issues of UI-propriety with this approach notwithstanding.)  Empirically, it seems that the topmost child window (if present) is the first in the list, so if any ChildWindows are being shown, we locate the first one in the list, and use it as the argument to FindElementsInHostCoordinates.  From there on, things progress as they had previously.

Supporting “Layers”

Shrek: “NO!  Layers.  Onions have layers.  Ogres have layers.   Onions have layers.  You get it?  We both have layers”
Donkey: “Oh, you both have layers.  Oh.  You know, not everybody likes onions.  What about cake?  Everybody loves cake!”
– Shrek (2001)

So what do I mean about layers?  In this case, I am referring to a situation where multiple related controls under a given point in a visual tree have Manipulation Behaviors attached.  An example would be a ListBox control with the ListBoxTouchScrollBehavior attached, and the underlying data template for the items in the list box having a GestureListener attached with a handler for a DoubleTap event.  The original implementation stopped at the first matching behavior, resulting in the ListBox scrolling, but ignoring the DoubleTap event.  The new implementation now identifies and processes all Manipulations under the given touch point.  This is similar to a Bubbling event, with a couple of key differences.  First, there is no notion of “handled.”  Second, the relationships do not have to exist in common branches of the same visual tree.

Available for Download

The latest code is up on CodePlex and the Alpha-2 release has been built based on these changes, which can be downloaded here.  I hope people find it helpful.

New Hampshire .Net (Seacoast) User Group Presentation Materials

I have uploaded the content from my Introduction to Windows Phone 7 Development with Silverlight talk at the New Hampshire .Net Seacoast User Group meeting last night in Portsmouth. The content can be found here, and includes:

  • Presentation slides, which include the reference links I mentioned during the talk.
  • The sample code, broken into 2 projects. Because the Notification Services portion of the talk adds extra projects to the solution ad is a little more complex to build and launch, that portion has been broken out into its own separate zip file.

For the Notification Services portion of the demo, the web project should be launched first, followed by the phone project (since the phone app calls the web site to register its URL for receiving notifications.) If the solution is run with the web project set as the default start project, the application bits do get deployed to the phone, but the debugger is not hooked up (unless multiple startup projects are used.) If debugging of the phone app is desired, it can be achieved by right clicking on the phone project and selecting Debug / Start New Instance. Also, this time the Notification Services demo includes the Push Notification Server-Side Helper recipe.

As usual, I have “sanitized” the uploaded code content by removing my personal Bing Maps application key. For information on how to obtain your own map key, please check out the Bing Maps Developer Portal.

I have also added a project that  shows the technique for “immediately” updating the application’s tile via a temporary Notification Services endpoint.  This is based on the code first presented here

The posted Slide Deck includes the slides that call out new content in the upcoming “Mango” release of WP7, and I have edited one slide to include one IMPORTANT new addition to the phone SDK that I forgot to previously include – support for Sockets.

Many thanks to Pat Tormey for inviting me to be the inaugural speaker for this new user group, as well as to Mark Mullin and Global Relief Technologies for providing a great site.  Also many thanks are deserved by the attendees, who asked some of the best questions I have gotten since I started doing these talks.

New for Windows Phone (Now) – the Async CTP

As is often the case when big events happen, sometimes some important announcements can get overlooked and/or overshadowed.  Mix 2011 certainly featured big news, including Silverlight 5 Beta, the Windows Phone 7.5 features, IE10, and the latest in the MVC framework.  However, in all of the hoopla, the release of the SP1 refresh of the Microsoft Visual Studio Async CTP SP1 Refresh, as well as some of the important changes, may have gone unnoticed.

There are a few important things to note regarding the Async CTP Refresh:

  • It includes an “As-Is” Go-Live license for use in production environments (albeit with some stern warnings about why you should really consider NOT using it in production code.)
  • It includes support for .Net, Silverlight 4, and Windows Phone 7.0.

Let me restate that last point.  The Async CTP works with Windows Phone 7 today.  No need to wait for the Mango update.

Now Just “await” a Minute…

As a CTP, and with the “As Is” license, there is no guarantee that this will eventually make it into the framework, and even if it does, it may take a very different form.  That being said, it is a great opportunity to see where things are headed and to offer feedback to the development team as to how to best shape this functionality to be as useful as it can be. 

That’s Nice.  How Long do I have to “await” to See Some Code?

So what do the Async tools bring to the table?  Among other things, it allows asynchronous code to be written without the “disruption” that currently occurs when that is being done today.  While a full discussion of asynchrony and the problems it solves and the new ones it presents are beyond the scope of this discussion, some brief coverage is merited.  Writing synchronous code today follows the pattern of “do something, wait for it to finish, then proceed.”  Altering this to be asynchronous (often) changes the pattern either the Asynchronous Programming Model/APM (“Call BeginXXX to start the operation, then EndXXX to wait for it to be completed”) or to the Event-Asynchronous Pattern/EAP (“start doing something, and raise an event that I am listening for when you are done.”)  When the completion of one asynchronous operation needs to trigger another one, code can get complicated and messy.  This situation is particularly apparent to those who use Silverlight and the related Silverlight for Windows Phone, as all I/O operations in Silverlight are inherently asynchronous.  The Async CTP brings a third model – the Task-based Asynchronous Pattern/TAP. 

The TAP model features the use of the async and await keywords to allow asynchronous code to be written in a much more linear fashion.  Under the covers, the compiler will generate all of the necessary “goo”, allowing the development to focus on the problem at a higher level.  The following code may help to visualize what this all means.

In the code that follows, a WebClient is spun up to return the data at a given URL.  The number of bytes in that data is returned as the result of the function.  This is the synchronous version of the code.

Code Snippet
  1. private void button1_Click(object sender, RoutedEventArgs e)
  2. {
  3.     var count = DoSomething();
  4.     MessageBox.Show(count.ToString());
  5. }
  6.  
  7. private Int32 DoSomething()
  8. {
  9.     var webClient = new WebClient();
  10.     var data = webClient.DownloadString(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland&quot;));
  11.     var results = data.Length;
  12.     return results;
  13. }

Note that this code blocks the UI when called, and cannot be used in Silverlight or Silverlight for Windows Phone applications.  So what if you don’t want to block the UI while retrieving the information (or better yet, what if you cannot, as is the case with Silverlight?)  Bring in asynchrony, but notice how it changes the nature of the function.  Where the desire had been to call a function to retrieve a result, now the function is called to eventually signal a response, which must be subscribed to by the calling code.

Code Snippet
  1. private void DoSomethingEAP()
  2. {
  3.     var webClient = new WebClient();
  4.     webClient.DownloadDataCompleted += HandleWebClientDownloadDataCompleted;
  5.     webClient.DownloadStringAsync(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland&quot;));
  6. }
  7.  
  8. private void HandleWebClientDownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
  9. {
  10.     var data = e.Result.Length;
  11.     MessageBox.Show(data.ToString());
  12. }

This is somewhat compressed and contained when inline lambda expressions are brought to bear, but the fundamental problem still exists.  The function has been modified because of its asynchronous implementation. 

Code Snippet
  1. private void DoSomethingEAPLambda()
  2. {
  3.     var webClient = new WebClient();
  4.     webClient.DownloadDataCompleted += (o, e) =>
  5.     {
  6.         var data = e.Result.Length;
  7.         MessageBox.Show(data.ToString());
  8.     };
  9.     webClient.DownloadStringAsync(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland&quot;));
  10. }

Now lets see how using the Async tools change things. 

Code Snippet
  1. private async void button1_Click(object sender, RoutedEventArgs e)
  2. {
  3.     var count = await DoSomethingAsync();
  4.     MessageBox.Show(count.ToString());
  5. }
  6.  
  7. private async Task<Int32> DoSomethingAsync()
  8. {
  9.     var webClient = new WebClient();
  10.     var data = await webClient.DownloadStringTaskAsync(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland&quot;));
  11.     var results = data.Length;
  12.     return results;
  13. }

Note that the functions now much more closely resemble the initial synchronous version. 

I’m Tired of “awaiting”.  Get Me the Bits.

This was just a light overview.  There are many other combinations and applications for the TAP.  Hopefully, this was enough to pique some curiosity.  If interested, the download for the Microsoft Visual Studio Async CTP SP1 Refresh is available at http://msdn.microsoft.com/en-us/vstudio/async.  This includes documentation, samples, and walkthroughs.  The tools require Visual Studio 2010 SP1.  Check out Eric Lippert’s announcement of the release (and additional links) at http://blogs.msdn.com/b/ericlippert/archive/2011/04/13/refreshing-the-async-ctp.aspx.