Category: Visual Studio 2010

EvenTiles from Start to Finish–Part 4

In the third part of this series about how to develop a Windows Phone application from scratch we looked at the Silverlight Toolkit for Windows Phone and page transitions. Today we will work on some functionality in the Settings Page of our application. We will take off where we finished in Part 3, and start with an empty SettingsPage (except for the application name and page title).

The purpose of our complete sample application is to create a Secondary Tile programmatically and pin that to the Start Screen of the user. The Secondary Tile has a front and a back. The text on the backside of the tile can be modified by the end user. EvenTiles is not meant to be extremely useful, it is there to help introduce lots of programming aspects to develop Windows Phone applications.

In this episode we will add a few UI Elements to the SettingsPage to realize the follow functionality:

  • The text that will be displayed on the backside of the Secondary Tile is visible;
  • The backside text can be modified;
  • If the backside text differs from a default text, a button is displayed to allow easy restoration of the default backside text, otherwise the button is invisible.

The SettingsPage gets the following layout:

image

The layout of the UI is relatively simple. In the ContentPanel of the PhoneApplicationPage we have a StackPanel containing 3 different items (a TextBlock, a TextBox plus a hidden Button) and a ToggleSwitch (that is defined in the Silverlight Toolkit for Windows Phone). The ToggleSwitch is already visible but does currently not have any functionality associated to it. The ContentPanel itself is a Grid. Initially, a Grid has one row and one column. To place UI Elements in the Grid and to position them at a particular location you typically make use of multiple rows and/or multiple columns that you first have to define. To get the desired layout, the Grid contains 3 separate rows. In the first row (being row number 0), the StackPanel is hosted. This row takes the height it needs to display all visible UI Elements of the StackPanel. The next row on the Grid takes up whatever space is left on the grid and the last row takes precisely the height it needs to display the ToggleSwitch. The XAML for the ContentPanel looks like this:

SettingsPage UI
  1. <!–ContentPanel – place additional content here–>
  2. <Grid x:Name="ContentPanel"
  3.         Grid.Row="1"
  4.         Margin="12,0,12,0">
  5.     <Grid.RowDefinitions>
  6.         <RowDefinition Height="Auto" />
  7.         <RowDefinition />
  8.         <RowDefinition Height="Auto" />
  9.     </Grid.RowDefinitions>
  10.     <StackPanel>
  11.         <TextBlock HorizontalAlignment="Left"
  12.                     TextWrapping="Wrap"
  13.                     Text="Set your own tile text (approx. 45 characters)"
  14.                     VerticalAlignment="Top"
  15.                     Margin="12,0" />
  16.         <TextBox x:Name="tbBackContent"
  17.                     TextWrapping="Wrap"
  18.                     MaxLength="45"
  19.                     d:LayoutOverrides="Height"
  20.                     TextChanged="tbBackContent_TextChanged" />
  21.         <Button x:Name="btnRestore"
  22.                 Content="Restore Default Text"
  23.                 Margin="0,0,0,3"
  24.                 d:LayoutOverrides="Height"
  25.                 Click="btnRestore_Click"
  26.                 Visibility="Collapsed" />
  27.     </StackPanel>
  28.     <toolkit:ToggleSwitch Header=""
  29.                             Grid.Row="2"
  30.                             Content="Allow using Location?" />
  31. </Grid>

You can see our Grid.RowDefinitions being defined. There is also a possibility to define Grid.ColumnDefinitions, but for this particular simple UI we only need rows. Scrolling through the XAML you can see all individual UI Elements being defined. The TextBox and the Button connect events to event handlers. For the Button, the Click event is connected to a method called btnRestore_Click. Each time the user Clicks the Button, the code that is defined in btnRestore_Click will execute. That code is defined in C#. We will take a look at the code later. The TextBox uses the TextChanged event, that will be fired each time the value of the Text property of the TextBox changes. If this happens, code inside the method tbBackContent_TextChanged will execute.

In Part 2 of EvenTiles we looked at the NavigationService that can be used to navigate from one PhoneApplicationPage to another PhoneApplicationPage. Each time the user navigates to a particular page, the OnNavigatedTo method on that page is called. You can override that method to extend its functionality. When the user navigates away from a PhoneApplication, a similar method (OnNavigatedFrom) is called that you again can override to add specific functionality you need on a particular page. In the SettingsPage of EvenTiles we are overriding both these methods to add some functionality:

OnNavigated …
  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     base.OnNavigatedTo(e);
  4.     tbBackContent.Text = App.ActualSecBackContent;
  5.     btnRestore.Visibility = tbBackContent.Text.Equals(App.DefaultSecBackContent) ? Visibility.Collapsed : Visibility.Visible;
  6. }
  7.  
  8. protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
  9. {
  10.     base.OnNavigatedFrom(e);
  11.     App.ActualSecBackContent = tbBackContent.Text;
  12. }

Both these methods contain a call to a similar method, preceded by the keyword base. These methods execute functionality that is defined in the base class of our derived PhoneApplicationPage class. To make sure that we don’t skip that code (which might contain important functionality for page navigation) we have to call those methods. Immediately under the call to the base class methods, our own functionality is added. When we are navigating to the SettingsPage, we initialize the TextBox with the currently stored backside content for a Secondary Tile that we will create later in this series. This content is defined in a string property in the App.xaml.cs file. Next we determine if the Button that can be used to restore a default text needs to be visible. This is only the case when the TextBox displays something different from a default text that is also defined in App.xaml.cs. In App.xaml.cs the default text is assigned to the actual text.

When the user is leaving the SettingsPage (for instance by pressing the Back button on the phone), we simply store the current content of the TextBox for later use.

Let’s now take a look at the event handlers for both the Button and the TextBox:

Event Handlers
  1. private void tbBackContent_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
  2. {
  3.     btnRestore.Visibility = tbBackContent.Text.Equals(App.DefaultSecBackContent) ? Visibility.Collapsed : Visibility.Visible;
  4. }
  5.  
  6. private void btnRestore_Click(object sender, System.Windows.RoutedEventArgs e)
  7. {
  8.     tbBackContent.Text = App.DefaultSecBackContent;
  9. }

If the text in the TextBox changes, the TextChanged event handler code will execute. Just like in the OnNavigatedTo method, we determine if the Button that can be used to restore a default text needs to be visible. If the Button is clicked, we simply restore the default text. Since this also fires a TextChanged event (after all, the text of the TextBox is changed), executing code in the TextChanged event handler will now result in the Button to be hidden.

In the following video you can see all the steps that are needed to add the described functionality to the SettingsPage.

Extending the SettingsPage for EvenTiles

We are still far away from having all functionality in place to actually make a Secondary Tile visible on the Start Screen. However, we need to understand a few fundamental concepts in order to create successful Windows Phone applications, so we will continue with the ground work for another couple of episodes. In the next episode we will look at persisting data in IsolatedStorage to make sure that we store data when the user stops using our application.

Where is that Mutex?

In the continuous story of Live Tiles I wanted to write about updating the Application Tile by using a PeriodicTask. This is a very nice way to update the tile without having to make use of a remote service. However, the PeriodicTask needs to get some data that is available in my application. The way to go is to store that data in a file in IsolatedStorage in the application and have the PeriodicTask retrieve the data from that same file, since it has access to IsolatedStorage.

Since the application might update data that the PeriodicTask needs and since both of them are executing independently from each other, it is a good idea to protect the data by means of a synchronization object. The documentation for Background Agents even suggests using a Mutex for this purpose.

And this is where the fun started for me. I tried to create a Mutex inside my application, and time and again I ran into an issue. The Mutex object was clearly unknown in my application, even though I did add a using directive for System.Threading.

image

It took me quite some time to figure out what was going on here, especially since the PeriodicTask that I was perfectly capable of using a Mutex. Both are Windows Phone projects, both have access to more or less the same namespaces. And yet, there was this difference in recognizing a Mutex object.

image

Taking another look at the documentation for the Mutex did not really help me, although it should have helped me, because there is a hint in the documentation that I completely missed.

image

Even though I was reading the above documentation several times, I didn’t get it. I know I had access to the System.Threading namespace and I still could not use the Mutex. So I started searching for a solution on the Internet and I was not really successful in that, although I got the indication that folks are using Mutex objects in Windows Phone Mango applications. All in all I guess I wasted at least one hour when I decided to compare references to assemblies in both the application and the PeriodicTask projects. Here I found one subtle difference.

image

The difference between the two projects is a reference to mscorlib.extensions. After adding a reference to that assembly in my application’s project, I could use the Mutex. Of course it simply comes back to reading the documentation, because it does indicate that the necessary assembly is mscorelib.extensions (in mscorlib.Extensions.dll). Ignoring that one little sentence delayed me for at least one hour. Hopefully you don’t fall in the same trap.

Running for the first time

This time I cannot be objective, because today I created an Android application for the very first time and I created a Windows Phone application (definitely not for the first time). So what I am really doing is comparing my first Android experience with my first Windows Phone experience, way over a year ago already. At that time, even with the beta tools installation was a simple one click operation, after which I could create a typical hello world application and immediately execute it on the emulator. The whole process took less than 30 minutes. Even though Silverlight was new for me, I was of course familiar with Visual Studio, C# and the .NET (Compact) Framework.

Today I did something similar. I already described my experience installing the Android development tools. Now it is time to try my first application on Android. I have to admit that I have no experience at all with Java or with Eclipse, so my comparison is a bit unfair. That is also the reason to chose a very simple Hello World application to get going. Of course this is a good idea in general, since such a simple application can quickly be used to verify if the development environment is installed correctly and to see if things simply work.

Before I could get to work, I first needed to add an Android Platform in my Eclipse environment. This additional step is necessary because Eclipse is a versatile development environment and because there are different Android versions. The other thing that needs to be done is to actually create an Android Virtual Device, which is the emulator that can be used as target to run / test applications. Building an AVD takes some time, but is not really a bad thing. At least you know that you will have a target for a specific Android version.

Creating a new project differs slightly between Windows Phone and Android. The same is true for the functionality of the application. The two differ because they are using different development environments and programming languages, but they are of similar complexity.

My Windows Phone application looks like this, created in Visual Studio 2010 Express for Windows Phone:

Visual Studio 2010 With my app

Deliberately I created all functionality in code to better compare this application to the Android application. A corresponding Android application looks like this:

Eclipse with my Android App

Compiling and deploying the Windows Phone application to the emulator was no problem at all. The emulator booted within 30 seconds after which the application was deployed and automatically started. It was a bit harder to get my Android application up an running in an emulator though. The first problem I ran into was a cryptic error I got when trying to deploy my Android application. The error was shown in the Eclipse console window:

image

It turns out that this error is caused by spaces in directory paths. I am not sure if this is an Eclipse issue or an Android SDK issue, but a solution to this problem was to create a logical link to the folder where the Android SDK was installed using a Command Prompt. This did the trick (of course after making sure inside Eclipse that the IDE now pointed to the newly created logical link).

MKLINK /J C:\Android "C:\Program Files (x86)\Android\android-sdk\"

Adding this link assured that the AVD did start. However, I still could not deploy the application to the virtual machine, this time because of another error:

image

It seems that this was simply a timeout error, because it takes quite some time to boot the AVD. Once it was entirely booted I tried running the application again and this time it was successful.

image

The scores for this exercise are clear. I needed to solve two (more or less cryptic) problems before I was able to run my application on the Android emulator. Deploying to the Windows Phone emulator caused no problems at all. Booting time for the Windows Phone emulator was around 30 seconds, the Android (3.2) emulator needed several minutes.

After installing the tools, my score was:

Windows Phone vs. Android: 1 – 0

After developing and creating a Hello World application, the scores are now:

Windows Phone vs. Android: 4 – 1

The reason why Windows Phone is a clear winner for me is the fact that deploying to the emulator just works and that the emulator boots relatively fast. The point I gave to Android might in fact belong to Eclipse. I really love maximize icon in the edit window, great for demos and something that I would not mind having in Visual Studio as well.

Over the upcoming weeks I will continue to compare Windows Phone with Android application development. So far there is a clear winner for me, but I want to really and honestly compare several aspects of developing applications on different platforms. Oh, just to be complete: My winner today is without any doubt

Windows Phone.

Ease of installation

Of course I am a bit biased, even though I am trying to be objective, independent and open minded. Over the last hour or so I have been busy setting up an Android development environment. If you are wondering why, it is not just out of curiosity, I am also preparing for a training I am taking next week. Over time it is going to be cool to find and understand differences between developing for Windows Phone and for other mobile platforms. I am planning to share my experiences in one way or another.

When I started developing Windows Phone applications, I just went to the App Hub, clicked on the link to download the free tools, and waited for Visual Studio 2010 Express for Windows Phone and Expression Blend 4 for Windows Phone to download and install. The development / design environment comes with a great emulator and within 30 minutes I was up and running (yes, I was using a slow Internet connection).

Today the story was slightly different. In order to start developing my first Android application, I had to download and install a Java SDK for which I went to Oracle. The next step was to download and install the Eclipse IDE for Java EE. Everything so far installed without any problem, but there is more to install. The next thing to install is the Android SDK, which has a nice Windows Installer. But wait ….  what is installed is the SDK Starter Package, with which you can download the SDK’s you need for your particular target. It looks like the SDK Starter Package is a specific download manager for multiple Android SDK’s. The challenge now is to find out which SDK I need. I decided to just install the latest version, being SDK Android Plaform 3.2, API 13, revision 1. Hopefully this is the right SDK to get started. Finally, the ADT plugin for Eclipse is needed. Installing the plugin is done from inside Eclipse. In order to get the plugin, you have to run through 8 different, but easy steps. Once Eclipse is restarted, it now should be possible to develop my first Android application. Now, instead of 30 minutes to install a development environment, it took me over 2 hours. However, remember, this is the very first time that I am going to work with Eclipse, a Java SDK and Android. I can imagine that experienced Android developers install the tools way faster than I did. However, so far my conclusion for the day:

Windows Phone vs. Android: 1 – 0.

Windows Phone Application Development & Debugging – Deactivation versus Tombstoning

While creating an update of an existing application I ran into a problem that sometimes occurred when the application was moved to the background. It turned out that the application behaved consistent with no exceptions raised when it was tombstoned after being moved to the background. However, the application sometimes crashed when it was deactivated and immediately became the executing application again without being tombstoned. In a later post I will explain the specific problem that caused the application to crash, for now I want to focus on ways to easily test deactivation scenarios.

Visual Studio 2010 has great support to test tombstoning scenarios for Windows Phone applications. Simply start debugging an application on a device or on device emulator and click the start button on the device (emulator). You will notice that the application moves to the background but that Visual Studio does not terminate its debugging session. Putting a breakpoint inside Activated / Deactivated event handlers shows us that the application is indeed being tombstoned / resurrected.

Visual Studio and Tombstoning

The debugger shows that the application is still running even though the application is no longer visible on the device. By using the back key on the device, it is possible to return to the application and to continue debugging it. However, if you start the application again on the device (so not using the back key), the debugger terminates. This means that a brand new instance of the application was started. Inside an application, it is possible to distinguish between a new instance being started and resurrection from being tombstoned by acting on the Launching or Activated events respectively. In both cases, the constructor of the page that becomes visible will be executed. More information about the application life cycle of a Windows Phone application can be found in this excellent series of blog entries by Yochay Kiriaty.

There are situations where an application is moved to the background without being tombstoned. In those situations, the application simply remains resident in memory, with its process being kept alive. When the application is activated again, it simply continues running without the need to create a new physical instance of the application. For end users the behavior is identical to tombstoning, after all, the application becomes invisible when another application starts executing. For developers there is a difference though, because no Launching or Activated event is raised and no constructor code (for instance for the currently visible page) is executed. To be able to consistently test application deactivation requires some additional work. One of the ways to ‘force’ deactivation over tombstoning is by starting a PhotoChooserTask. In my own application I simply use the application bar to add a new ApplicationBarIconButton to display a PhotoChooserTask.

To assure that this ApplicationBarIconButton is only visible in Debug mode, a bit of conditional compilation is needed. The following code snippet shows how to create a new ApplicationBarIconButton programmatically, add it to the ApplicationBar and add an event handler to its click event.

Adding an ApplicationBar Item
  1. #if DEBUG
  2. PhotoChooserTask _pt;
  3. #endif
  4.  
  5. public MainPage()
  6. {
  7.     InitializeComponent();
  8.  
  9. #if DEBUG
  10.     _pt = new PhotoChooserTask();
  11.  
  12.     this.ApplicationBar.IsVisible = true;
  13.  
  14.     ApplicationBarIconButton pauseButton = new ApplicationBarIconButton
  15.     {
  16.         Text = "Pause App",
  17.         IconUri = new Uri("/Images/appbar.transport.pause.rest.png", UriKind.Relative),
  18.         IsEnabled = true
  19.     };
  20.  
  21.     pauseButton.Click += new EventHandler(pauseButton_Click);
  22.     this.ApplicationBar.Buttons.Add(pauseButton);
  23. #endif
  24. }

Of course, adding a button to an existing ApplicationBar only works if the application has 3 or less ApplicationBarButtonIcons in use. An alternative could for instance be adding a MouseLeftButtonDown event handler to the application’s title. When clicking the ApplicationBarButtonIcon you created specifically for debug purposes, what you now can do is display the PictureChooserTask. This results in your application being pushed to the background, without being tombstoned.

Forcing us to the background
  1. void pauseButton_Click(object sender, EventArgs e)
  2. {
  3.     _pt.Show();
  4. }

This approach makes it relatively easy to test the different scenarios for your application going to the background and returning to the foreground again. Here are the results in a little test application.

TombstoningOrNot

In the left screen you can see the application immediately after the main page became visible. In the center screen you see the result of clicking the pause button, after which a PhotoChooserTask was activated and closed again. What you can see is that there is no Application_Deactivated / Application_Activated combination. You can also see that no constructor is called after returning from the PhotoChooserTask. In other words, the application is not tombstoned while the PhotoChooserTask is active. Finally, the right screen shows how the application returns from being tombstoned. In this case constructors are called and Application_Activated is raised.

The issue I had in one of my applications had to do with counting on constructors to be called to dynamically add a few controls to my visual tree.

Note: This blog entry is applicable for Windows Phone 7. For the next version of Windows Phone (codenamed Mango), developers can choose between tombstoning and fast application switching by setting the corresponding property in the project settings. Fast application switching could be considered as another state in the application’s life cycle, being very similar to the situation that was described in this post using the PhotoChooserTask.

Splash Screens

If you start developing a new Windows Phone 7 application, you usually start by creating a new Visual Studio 2010 project. As part of the initial project, Visual Studio creates a default splash screen for you, consisting of a waiting clock.

DefaultSplashScreen

A Windows Phone splash screen is simply a jpg file with a resolution of 800 * 480 pixels. This means that it is very simple to replace the default splash screen (which is conveniently stored in your Visual Studio project under the name SplashScreenImage.jpg). Just make sure you have a jpg file with the right resolution and also make sure that it is placed in the root of your Visual Studio project. The name must be SplashScreenImage.jpg and its Build Action must be set to Content in the Properties window. Leaving the original splash screen unchanged in your own application gives end users a somewhat boring experience. After all, a splash screen is used to give users the impression that your application starts fast, and it also occupies users while your application is loading. If all applications use the same default splash screen, it will not help giving users a fast starting impression about those applications. So it is important to provide your own splash screen. If an application does not spent much time initializing, the actual amount of time that a splash screen is displayed is very short. For one of my applications, I did create a reasonably nice splash screen, to find out that the splash screen often is displayed for less then a second. My initial thought was to delay application start to allow end users to admire my splash screen. Of course this is a very bad idea, something you should not even consider doing.

SplashScreen1

This splash screen is used in a little game that is available on Marketplace. Typically the game starts up in under a second, meaning the user hardly has time to see the splash screen. The good news is that it is at least not the default splash screen. I have to admit that I considered adding a delay in my application for users to see the splash screen. Of course, and end user might like it once to take a look at this splash screen, but after starting an application several times, the splash screen will become boring since it is just a static image.

On a side note, if you are curious about this game, you can find it here on the Windows Phone 7 Marketplace. Note: This link will work from a Windows Phone 7, or from a PC with Zune software installed.

Back to the story about splash screens though. If you are developing a Silverlight application for Windows Phone 7, take the following idea into consideration.  By far the best experience you can give end users for fast starting applications, is to take a screen shot from your application’s main page. If your application starts with some animation, make sure to take the screen shot from the initial situation (before the animation starts running).

SplashScreen2

Capture

Also, leave the application title / page title out of the splash screen. What I did for my latest application was taking the following shot from the main screen. Once the application is initialized, the application and page title animate in from the top, nice and gently. This gives a very nice experience for end users, and you don’t have to worry that your splash screen is only visible for a very short time, after all, your splash screen partly is your main page.

 

To have some nice page transitions on your main page, you can make use of functionality that is available in the November release of the Silverlight for Windows Phone Toolkit. An in-depth explanation of how to use these page transitions can be found in this MSDN  blog entry by Will Faught.

This is the code that I am using to bring in the application title and page title in an override version of the OnNavigatedTo method:

  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     base.OnNavigatedTo(e);
  4.  
  5.     if (Settings.Instance.ApplicationLaunching)
  6.     {
  7.         SlideTransition slideTransitionFadeIn = new SlideTransition { Mode = SlideTransitionMode.SlideDownFadeIn };
  8.         ITransition transitionTitle = slideTransitionFadeIn.GetTransition(this.TitlePanel);
  9.         transitionTitle.Completed += delegate { transitionTitle.Stop(); };
  10.         transitionTitle.Begin();
  11.         Settings.Instance.ApplicationLaunching = false;
  12.     }
  13. }

Only when my application is launching (a new instance of the application is started, or the application returns from being tombstoned), the animation will run. In all other situations ‘normal’ page transitions will be executed. I keep track of the application being launched in the app.xaml.cs source file like this:

  1. // Code to execute when the application is launching (eg, from Start)
  2. // This code will not execute when the application is reactivated
  3. private void Application_Launching(object sender, LaunchingEventArgs e)
  4. {
  5.     Settings.Instance.IsTrialMode = RunningMode.CheckIsTrial();
  6.     Settings.Instance.ApplicationLaunching = true;
  7. }
  8.  
  9. // Code to execute when the application is activated (brought to foreground)
  10. // This code will not execute when the application is first launched
  11. private void Application_Activated(object sender, ActivatedEventArgs e)
  12. {
  13.     Settings.Instance.IsTrialMode = RunningMode.CheckIsTrial();
  14.     Settings.Instance.ApplicationLaunching = true;
  15. }

As you can see, a little bit of code and an additional screen capture from of your application gives you a simple splash screen that is effective for fast loading applications, yet giving the end users a very nice starting experience of your application.

Configuration dependent references

When you are developing Windows Phone 7 applications, especially if you are using additional assemblies that you developed yourself, it might not be sufficient to just add a reference to those particular assemblies from inside Visual Studio 2010. For instance, take this scenario that is taken from a real Windows Phone application:

AddingReferences(1)

This application makes use of an assembly that contains lots of re-usable functionality around MVVM support, IsolatedStorage support for tombstoning purposes and a few goodies to test an application’s Trial mode support. The latter item is the one I want to talk about in more detail in this article.

On a side note: even though I partly re-invented the wheel, there is a very nice MVVM implementation available with great Windows Phone 7 support. Take a look at Galasoft’s MVVM Light, a great resource for developing ‘serious’ Windows Phone 7 applications.

If you are developing Windows Phone 7 applications, you are most likely aware of the fact that the IsTrial method of the LicenseInformation class always returns false when running your application locally from a development machine. In order to test your application’s behavior in trial mode, you probably end up with something like this:

  1. using Microsoft.Phone.Marketplace;
  2.  
  3. namespace DotNETForDevices.Tools.Controls
  4. {
  5.     public class RunningMode
  6.     {
  7.         public static bool CheckIsTrial()
  8.         {
  9. #if DEBUG_TRIAL
  10.             return true;
  11. #else
  12.             return new LicenseInformation().IsTrial();
  13. #endif
  14.         }
  15.     }
  16. }

By defining a conditional compilation symbol ‘DEBUG_TRIAL’, it is now possible to test the application as if it is running in trial mode. However, if you are lazy like me, you probably get tired of manually setting conditional compilation symbols. I am also afraid to forget undefining symbols like this one when I submit applications for verification, especially since the above code snippet lives in a separate  assembly. For me, it would be very helpful if I could create an additional configuration, that would allow me to build my entire solution for trial mode testing. Creating a new build configuration is very easy inside Visual Studio.

CreatingNewConfiguration

Inside this new configuration I can define my DEBUG_TRIAL conditional compilation symbol as well as additional symbols. Because I derived my new configuration from the existing Debug configuration, all other settings in my new configuration are copied from the existing Debug configuration. This is exactly what I want. Unfortunately though, even though I can define additional settings, at first sight it seems that Visual Studio 2010 does not help me to refer to other versions of assemblies that I add to my solution. In other words, I would really like to refer to a DebugTrial build of my additional DotNETForDevices.Tools.Controls assembly when I am building my application in the DebugTrial configuration. Of course I want Visual Studio to update to the Release configuration of all my own assemblies as well when I decide to build my solution in Release mode. If you take a look at the path to my referred assembly when I switch from Debug mode to DebugTrial or to Release mode, you will see that the referred assembly is still the original Debug assembly.

AddingReferences(2)

At first glance it seems that there is no way to be able to import my own assemblies with the same build configuration that I am using during the current build of my solution. There is a way to overcome this situation. As you might now, Visual Studio 2010 project files are XML based files, so it is possible to view them with a text editor and it is even possible to modify them. Of course you have to be very careful with modifying project files because it might lead to Visual Studio not being able to open your project any longer. If you want to modify your project files, make sure to always make a back-up of the original file.

  1. <ItemGroup>
  2.   <Reference Include="DotNETForDevices.Tools.Controls">
  3.     <HintPath>..\..\..\DotNETForDevices\Controls\Bin\Debug\DotNETForDevices.Tools.Controls.dll</HintPath>
  4.   </Reference>
  5.   <Reference Include="DotNETForDevices.Tools.Persistence">
  6.     <HintPath>..\..\..\DotNETForDevices\Persistence\Bin\Debug\DotNETForDevices.Tools.Persistence.dll</HintPath>
  7.   </Reference>
  8.   <Reference Include="Microsoft.Phone" />
  9.   <Reference Include="Microsoft.Phone.Interop" />
  10.   <Reference Include="System.Windows" />
  11.   <Reference Include="system" />
  12.   <Reference Include="System.Core" />
  13.   <Reference Include="System.Net" />
  14.   <Reference Include="System.Xml" />
  15. </ItemGroup>

Looking inside my Clicker.csproj file, it becomes clear that the paths to referred assemblies are defined in a configuration independent way. This is fine for all system assemblies, but less ideal for my own assemblies, especially since they might still be under development as well. If you take a further look inside the *.csproj file, you will see that there are configuration dependent definitions.

  1. <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  2.   <DebugSymbols>true</DebugSymbols>
  3.   <DebugType>full</DebugType>
  4.   <Optimize>false</Optimize>
  5.   <OutputPath>Bin\Debug</OutputPath>
  6.   <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
  7.   <NoStdLib>true</NoStdLib>
  8.   <NoConfig>true</NoConfig>
  9.   <ErrorReport>prompt</ErrorReport>
  10.   <WarningLevel>4</WarningLevel>
  11. </PropertyGroup>
  12. <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
  13.   <DebugType>pdbonly</DebugType>
  14.   <Optimize>true</Optimize>
  15.   <OutputPath>Bin\Release</OutputPath>
  16.   <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
  17.   <NoStdLib>true</NoStdLib>
  18.   <NoConfig>true</NoConfig>
  19.   <ErrorReport>prompt</ErrorReport>
  20.   <WarningLevel>4</WarningLevel>
  21. </PropertyGroup>

It seems that conditions can be defined very easy inside project files. If I could do something similar for paths to assemblies that I have added as references, I could add assemblies with the same build configuration as my current solution has. This guarantees me building against the right configuration of my own additional assemblies. So this is the final solution I came up with, indeed modifying the project file manually:

  1. <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  2.   <Reference Include="DotNETForDevices.Tools.Persistence">
  3.     <HintPath>..\..\DotNETForDevices\Persistence\Bin\Debug\DotNETForDevices.Tools.Persistence.dll</HintPath>
  4.   </Reference>
  5.   <Reference Include="DotNETForDevices.Tools.Controls">
  6.     <HintPath>..\..\..\DotNETForDevices\Controls\Bin\Debug\DotNETForDevices.Tools.Controls.dll</HintPath>
  7.   </Reference>
  8. </ItemGroup>
  9. <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
  10.   <Reference Include="DotNETForDevices.Tools.Controls">
  11.     <HintPath>..\..\DotNETForDevices\Controls\Bin\Release\DotNETForDevices.Tools.Controls.dll</HintPath>
  12.   </Reference>
  13.   <Reference Include="DotNETForDevices.Tools.Persistence">
  14.     <HintPath>..\..\DotNETForDevices\Persistence\Bin\Release\DotNETForDevices.Tools.Persistence.dll</HintPath>
  15.   </Reference>
  16. </ItemGroup>
  17. <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'DebugTrial|AnyCPU'">
  18.   <Reference Include="DotNETForDevices.Tools.Controls">
  19.     <HintPath>..\..\DotNETForDevices\Controls\Bin\DebugTrial\DotNETForDevices.Tools.Controls.dll</HintPath>
  20.   </Reference>
  21.   <Reference Include="DotNETForDevices.Tools.Persistence">
  22.     <HintPath>..\..\DotNETForDevices\Persistence\Bin\DebugTrial\DotNETForDevices.Tools.Persistence.dll</HintPath>
  23.   </Reference>
  24. </ItemGroup>

Changing to another build configuration now also results in referring to assemblies that correspond with that particular build configuration.

AddingReferences(3)

One very important thing to keep in mind though is that you need to manually modify the project file each time you add references to additional assemblies that you own and that you want to be build configuration aware. Other than that, I have not seen any issues by extending project files for this particular purpose. However, things might of course change with future versions of Visual Studio.