May 2011 - Posts
Introduction
The official answer is you can’t. Even with the In-Process Side by Side execution (SxS) feature, introduced in .NET 4.
The SxS feature was intended to be used when COM is involved. For example, if you got an application that loads plugins, like outlook, and it loads 2 COM plugins, one is using .NET 4 and the other is using .NET 2.0 then it will load two versions of the CLR into the process using the new SxS feature.
What if I simply have a .NET 2 application or DLL that needs to access a .NET 4 DLL?
Personally I’ve encountered two scenarios when I had to solve this problem:
- I had a 3rd-party control that would load only in a .NET 3.5 application, but I had to use it in a .NET 4 application.
- I wanted to write a plug-in for Windows Live Writer, which must use .NET 2.0, but I needed to use in my plug-in a .NET 4 DLL.
So, what can we do if no COM is involved?
Well, simply add COM to the mixture..
The idea is that you can expose the required classes from your DLL (which uses .NET Framework X) as COM classes (using COM Interop), and then use those classes from your other DLL (which uses .NET Framework Y). Since you are crossing a COM interface, in-process SxS will kick in and work its magic.
Steps to work around the problem
Create a .NET 4 DLL
Suppose we have a .NET 4 DLL which does some .NET 4 functionality. In the attached example our .NET 4 class prints the CLR version, which should be 4. This DLL is compiled with .NET Framework 4.
using System;
namespace Net4Assembly
{
public class MyClass
{
public void DoNet4Action()
{
Console.WriteLine("CLR version from DLL: {0}", Environment.Version);
}
}
}
Create a .NET 2 EXE
Here we create a .NET 2 EXE which will eventually call the .NET 4 DLL, currently all it does is write it’s own CLR version.
using System;
namespace Net2Assembly
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("CLR version from EXE: {0}", Environment.Version);
}
}
}
Create a .NET 4 to .NET 2 adapter
Here we create a .NET 4 DLL that exposes the same functionality we need from our original .NET 4 DLL only it exposes it in a COM-friendly way. In this example, it only needs to delegate the call to the original implementation, but in more advanced scenarios it should translate the parameters to something more COM friendly. In addition to changing the parameters the classes also implement interfaces (as required by COM) and are marked with ComVisible and Guid attributes to allow access using COM.
Here is our COM visible interface:
using System;
using System.Runtime.InteropServices;
namespace Net4ToNet2Adapter
{
[ComVisible(true)]
[Guid("E36BBF07-591E-4959-97AE-D439CBA392FB")]
public interface IMyClassAdapter
{
void DoNet4Action();
}
}
And our COM visible class, which delegates its calls to the original class.
using System;
using System.Runtime.InteropServices;
using Net4Assembly;
namespace Net4ToNet2Adapter
{
[ComVisible(true)]
[Guid("A6574755-925A-4E41-A01B-B6A0EEF72DF0")]
public class MyClassAdapter : IMyClassAdapter
{
private MyClass _myClass = new MyClass();
public void DoNet4Action()
{
_myClass.DoNet4Action();
}
}
}
Note: we could have combined Net4Assembly.MyClass and Net4ToNet2Adapter.MyClassAdapter into the same class but I wanted to keep the example general. In real life application you often can’t change the original object and thus you are forced to create a wrapper.
Add support to the adapter for registration-free COM activation
Important note: this part is not really necessary for the .NET 4 to .NET 2 interop to work. But without it you will need to start using he registry for registering your .NET COM components and most projects would rather to avoid it if possible. If this is not a problem just register your objects in the registry and move to the next step.
To add support for registration-free COM we need to create two application manifest files.
The first application manifest specifies dependent assemblies for the client executable. Note that since this manifest replaces the default .NET manifest I’ve added some extra standard manifest stuff (trustinfo), but only the first part is really needed for the registration-free COM to work. To add it, add a file to the client project named app.manifest (“Add new item” –> “Application Manifest”) and change the project properties to use this file.
Following is the content of app.manifest for the Net2Aseembly.exe client in our example:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<assemblyIdentity
type = "win32"
name = "Net2Assembly"
version = "1.0.0.0"
/>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Net4ToNet2Adapter"
version="1.0.0.0" />
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
If you want to utilize File and Registry Virtualization for backward
compatibility then delete the requestedExecutionLevel node.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
The second application manifest, describes the COM components which are exposed in the assembly. It needs to be set as the application manifest which resides as a native Win32 resource inside the DLL.
Unfortunately, this can’t be done as easily as the previous manifest. In Visual Studio 2010, the relevant field in the project properties is disabled when the project is of type Class Library. So we must go to the Net4ToNet2Adapter.csproj file and change it ourselves. The change is easy, just add the following lines in the relevant place:
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
Following is the content of app.manifest for the Net4ToNet2Adapter.dll in our example:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="Net4ToNet2Adapter"
version="1.0.0.0" />
<clrClass
clsid="{A6574755-925A-4E41-A01B-B6A0EEF72DF0}"
progid="Net4ToNet2Adapter.MyClassAdapter"
threadingModel="Both"
name="Net4ToNet2Adapter.MyClassAdapter"
runtimeVersion="v4.0.30319"
/>
</assembly>
Use our .NET 4 DLL via COM
Now all you need to do is create an instance of your .NET 4 class from your .NET 2 executable using COM:
using System;
using Net4ToNet2Adapter;
namespace Net2Assembly
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("CLR version from EXE: {0}", Environment.Version);
Type myClassAdapterType = Type.GetTypeFromProgID("Net4ToNet2Adapter.MyClassAdapter");
object myClassAdapterInstance = Activator.CreateInstance(myClassAdapterType);
IMyClassAdapter myClassAdapter = (IMyClassAdapter)myClassAdapterInstance;
myClassAdapter.DoNet4Action();
}
}
}
Note: Since the interface IMyClassAdapter should be duplicated in the client, I’ve added the source file IMyClassAdapter.cs as a link to the client project.
The result
The result of running this simple console application is:

I think the image speaks for itself.
I’ve uploaded the full source of this example to MSDN Code Gallery.
That’s it for now,
Arik Poznanski.
Recently I came across the need to customize the look of the standard message box in the application. To do this I’ve decided to create a new class named WPFMessageBox, which will have the same interface as the standard one, will behave the same way and finally would be fully customizable, the WPF way, using control templates.
Following is the result of this effort.

Note: In the image you can see an example for a message box customization. Of course you are limited only by your imagination. The default control template looks like the standard message box.
Features
- The class WPFMessageBox has the exact same interface as the current WPF MessageBox class.
- Implemented as a custom control, thus fully customizable via standard WPF control templates.
- Has a default control template which looks like the standard MessageBox.
- Supports all the common types of message boxes: Error, Warning, Question and Information.
- Has the same “Beep” sounds as when opening a standard MessageBox.
- Supports the same behavior when pressing the Escape button as the standard MessageBox.
- Provides the same system menu as the standard MessageBox, including disabling the Close button when the message box is in Yes-No mode.
- Handles right-aligned and right-to-left operating systems, same as the standard MessageBox.
- Provides support for setting the owner window as a WinForms Form control.
How to use it?
Using the WPFMessageBox class is (exactly) as simple as presenting a standard MessageBox.
Instead of writing:
MessageBoxResult result = MessageBox.Show("message text", "caption", MessageBoxButton.YesNoCancel, MessageBoxImage.Error);
simply write:
MessageBoxResult result = WPFMessageBox.Show("message text", "caption", MessageBoxButton.YesNoCancel, MessageBoxImage.Error);
All of the methods of the original MessageBox are supported:
public static class WPFMessageBox
{
public static MessageBoxResult Show(string messageBoxText);
public static MessageBoxResult Show(string messageBoxText, string caption);
public static MessageBoxResult Show(Window owner, string messageBoxText);
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button);
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption);
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button);
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult);
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options);
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult);
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options);
}
How to customize it?
The main point of creating this WPF message box was to customize it, right? so I’d better show you how this is done.
To customize the WPFMessageBox we use the standard control templates way:
<Style TargetType="msgbox:WPFMessageBoxControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type msgbox:WPFMessageBoxControl}">
<!-- your new template here -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
where the msgbox prefix is defined as follows:
xmlns:msgbox="clr-namespace:MessageBoxUtils;assembly=WPFMessageBox"
Of course, you can use Blend to do the customizations.
Can I see a real example of such customization?
Sure, following is the control template for the message box you see in the image. Note the binding you need to use to properly set the visibility of the buttons and the image.
<Style TargetType="{x:Type msgbox:WPFMessageBoxControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type msgbox:WPFMessageBoxControl}">
<Grid Background="LightBlue" FlowDirection="{Binding ContentFlowDirection}">
<Grid.RowDefinitions>
<RowDefinition Height="55" />
<RowDefinition Height="2" />
<RowDefinition Height="*" />
<RowDefinition Height="40" />
<RowDefinition Height="55" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Message}" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2" TextWrapping="Wrap" TextAlignment="Left" HorizontalAlignment="{Binding ContentTextAlignment}" VerticalAlignment="Top" Margin="10 10 10 10" />
<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Background="Yellow">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0 0 5 0" >
<Button Content="_Yes" Visibility="{Binding YesNoVisibility}" Command="{Binding YesCommand}" IsDefault="{Binding IsYesDefault}" Margin="5 5 5 5" Height="24" Width="80" />
<Button Content="_No" Visibility="{Binding YesNoVisibility}" Command="{Binding NoCommand}" IsDefault="{Binding IsNoDefault}" Margin="5 5 5 5" Height="24" Width="80" />
<Button Content="O_K" Visibility="{Binding OkVisibility}" Command="{Binding OkCommand}" IsDefault="{Binding IsOkDefault}" Margin="5 5 5 5" Height="24" Width="80" />
<Button Content="_Cancel" Visibility="{Binding CancelVisibility}" Command="{Binding CancelCommand}" IsDefault="{Binding IsCancelDefault}" Margin="5 5 5 5" Height="24" Width="80" />
</StackPanel>
</Border>
<StackPanel Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<Image Source="{Binding MessageImageSource}" HorizontalAlignment="Left" VerticalAlignment="Center" Height="32" Width="32" Margin="10 0 0 0" />
<Image Source="{Binding MessageImageSource}" HorizontalAlignment="Left" VerticalAlignment="Center" Height="32" Width="32" Margin="10 0 0 0" />
<Image Source="{Binding MessageImageSource}" HorizontalAlignment="Left" VerticalAlignment="Center" Height="32" Width="32" Margin="10 0 0 0" />
<Image Source="{Binding MessageImageSource}" HorizontalAlignment="Left" VerticalAlignment="Center" Height="32" Width="32" Margin="10 0 0 0" />
<Image Source="{Binding MessageImageSource}" HorizontalAlignment="Left" VerticalAlignment="Center" Height="32" Width="32" Margin="10 0 0 0" />
<Image Source="{Binding MessageImageSource}" HorizontalAlignment="Left" VerticalAlignment="Center" Height="32" Width="32" Margin="10 0 0 0" />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Where can I get it?
I’ve uploaded the source to a new CodePlex project named WPF MessageBox.
That’s it for now,
Arik Poznanski.
Today (24.05.2011) I’ve delivered two sessions about “Using Windows 7 Features in .NET applications” in Sela Haifa Open House which was presented in Philips building in Haifa.
Dear Philips (and other) developers, I had a great time presenting today's Windows 7 sessions. Thank you for coming!

In the sessions I talked about how to use new Windows 7 features like the new Taskbar, sensors API, the Ribbon control supplied with Windows 7, Application restart and Recovery and plenty of Multi-Touch.
We’ve seen numerous examples, mainly in C++ Win32, WinForms and WPF.

You can download both the presentations and the demos here.
That’s it for now,
Arik Poznanski.
Sela Technology Center is proud to present Sela Developer Days 2011 which will be held on June 26-30.

One stage - hottest topics - Israel and world lead experts.
A rare opportunity to hear all about the next big things in our technological world.
- 25 full-day workshops
- 15 lead experts
- 5 days
You can find the full agenda on the conference website.
Although I recommend ALL the lectures, I believe my blog readers will most enjoy the following workshops:
See you there!
That's it for now,
Arik Poznanski.

Yesterday (18.05.2011) I’ve delivered two sessions about “Using Windows 7 Features in .NET applications” in the Israeli .NET User Group, at Microsoft offices in Ra’anana.
I want to thank all the attendees who came to hear the sessions, I truly enjoyed it.
In the sessions I talked about how to use new Windows 7 features like the new Taskbar, sensors API, the Ribbon control supplied with Windows 7, Application restart and Recovery and plenty of Multi-Touch.
We’ve seen numerous examples in C++ Win32, C# WinForms, C# WPF and C# Silverlight.

Since we were a little short on time, I couldn’t answer everyone's questions. So if you got an unanswered question, feel free to contact me by mail (find it on my blog left panel) or using the blog contact form.
You can download both the presentations and the demos here.
That’s it for now,
Arik Poznanski.
Recently I got involved in a big project where we had a single solution with approximately 100 projects.
Why 100 Projects in a Solution?
The reason for a 100 projects solution is that like in many modular systems these days, we have the following three tiers:
- A few core / common projects every project will use.
- A large amount of modules, independent of each other. This tier directly depends on tier 1.
- A few end-projects which loads the different modules. This tier indirectly depends on tier 2.

So, yes, we could create several solutions with each tier compiling only when needed and using DLL reference instead of project references, but the amount of changes in all the tiers was still large enough and I’ve already seen this kind of build process fail miserably. So this was no go.
Build time took 15 minutes for the whole solution. Since we enforced a gated check-in policy in the company, this was really a pain point for the developers.
Note that the developers’ computers were strong enough, with 8GB ram, Intel Core i7 CPU and SSD disks.
So I’ve started investigating what can be done to improve the situation.
Step 1: Build Projects in Parallel
Although the PC has 8 logical cores, the build system in Visual Studio 2010, when using C#, still uses only a single core! (Note this is not the case in C++ build system).
So after browsing the web, I’ve found how you can manually trigger msbuild yourself as a Visual Studio external tool to compile your solution in parallel.

More details on how to set this up can be found in the following post by Scott Hanselman: http://www.hanselman.com/blog/HackParallelMSBuildsFromWithinTheVisualStudioIDE.aspx
After setting this up I’ve got an approximate build time of 10.2 minutes. Not bad for a few minutes of work! Also, got the following beautiful image out of my CPUs, where you can really see them at work:

Step 2: Beware of Copy Local = True
In our 100-projects solution lots of projects reference each other, obviously. In addition to these references we also reference several 3rd party components, practically from each module.
All the above caused that whenever we would compile the solution, over 4.5 GB of files were written. The majority (95%) of the writes were DLLs which were copied to the output folder of each project.
To check out how many writes are done in your compilation check out this post.
Anyway, 4.5 GB takes a long time to write, even on an SSD drive.
So the next step was to eliminate those writes. To do this, we changed almost all of the “Copy local” settings in all the referenced DLLs from the default True to False. This will prevent the referenced DLLs to be copied to the output folder of each project.

Note: some file names were blacked to protect the client’s properties.
In addition we also changed the output folder of all the projects to a single folder, so all generated DLLs are copied to the one and only place where we actually run them. Doing so dropped the writes while compiling to under 200 MB, a huge time saver. Specifically, build time dropped to 7.5 minutes!
Step 3: Use RAM Disk
A RAM disk is a logical disk which resides entirely on the RAM.
It is extremely fast (faster than any SSD), but it is erased on every power-down, so only use it for temporary files.
Of course, you should have enough RAM to spare for this disk (the memory is pre-allocated for the disk use only), but on an 8GB PC, it’s usually not an issue.
There are several programs you can use to set up a RAM disk. I used DataRam RamDisk which supplies a free version with the ability to create a RAM disk up to 4 GB (1 or 2 GB should be sufficient for any build).
Configuration of the RAM disk is very easy:

After you download, install and format your new RAM disk, you can move your single output folder to it. If you want to keep your output folder in the same build drive you can simply create a symbolic link between the current output folder and a folder on the RAM disk. This way makes the using of the RAM disk optional, only for users with sufficient memory.
To create a symbolic link between your build folder and your new RAM disk folder use the following line:
mklink /D C:\Dev\MyCurrnetBuildFolder\Source\bin R:\bin
where R: is your RAM disk folder.
Note: you should change the path according to your build folder and your RAM drive settings.
Result: Adding the RAM disk reduced compilation time to less than 5 minutes! This is a 66% reduction of the original time!
Summary
In this post we’ve seen how you can decrease build time. Of course, I can’t make any guarantees. Every project has its own characteristics and problems, but the steps provided can probably reduce the build time if you’re fit the profile of standard line-of-business application.
That’s it for now,
Arik Poznanski.
In case you missed one of my previous Windows 7 sessions, here is your chance to catch it.

On May 24th I’ll be giving two sessions about “Using Windows 7 Features in .NET Applications”, as part of Sela Haifa Open House.
On the first session “The 7 Show: From XP to Win 7” we will talk about new features in Windows 7 that will modernize your application.
We will learn how to work with the new Taskbar, how to work with Sensors, how to use the Ribbon interface and more.
The session will be rich with examples in .NET, WPF and WinForms.
On the second session “Touch Everywhere” we will see how to use the Multi-touch feature which comes out of the box in Windows 7.
We will learn about the possible level of support (Good, Better & Best) and learn about helper libraries that provide a convenient API when working with multi-touch devices.
The session will include many examples in all the common UI technologies: C++, WinForms, WPF and Silverlight.
The entrance is free, but requires registration.
Hope to see you there!
That’s it for now,
Arik Poznanski.
In the following post I’ll show you how you can measure how many read and writes (in bytes) your build takes. This may prove useful since the amount of writes can have a tremendous effect on the build total time. More on how to shorten your build time in a future post.
Step 1: Download Process Monitor
The key for measuring the build read and writes is to download the great tool by Sysinternals, Process Monitor.
Process Monitor is a tool which monitors all the processes in your system for several activities, like: file-access, registry, etc. It has rich support for filtering and summarizing the information.

Step 2: Setup a filter on your build process
Select the “Filter” menu and then “Filter…” menu item.
Now add a new filter with “Process Name” is “devenv.exe”, or “msbuild.exe”, depending on how you build your project.

Also disable all activities but the “file system” activity, since we want to focus on these alone.

Step 3: Run your build process
Clear the captured data from the process monitor to get a clean screen.

Now invoke your build process with your favorite tool: Visual Studio or msbuild.
Step 4: Get the results
Select the “Tools” menu and then “File Summary…” menu item.

Note: some file names were blacked to protect the client’s properties.
Step 5: Check by folder
Present the file summary by folders to get a better understanding on which folders you get most of the writes.

This is it. Here you can already see exactly how many read and writes you are doing and also how much time was invested in those writes (check the File Time column).
In a future post I’ll cover how you can decrease build time using this information.
That’s it for now,
Arik Poznanski.

On May 18th I’ll be giving two sessions about “Using Windows 7 Features in .NET Applications”, as part of the monthly .NET User Group sessions, in Microsoft offices, Ra’anana, Israel.
On the first session “The 7 Show: From XP to Win 7” we will talk about new features in Windows 7 that will modernize your application.
We will learn how to work with the new Taskbar, how to work with Sensors, how to use the Ribbon interface and more.
The session will be rich with examples in .NET, WPF and WinForms.
On the second session “Touch Everywhere” we will see how to use the Multi-touch feature which comes out of the box in Windows 7.
We will learn about the possible level of support (Good, Better & Best) and learn about helper libraries that provide a convenient API when working with multi-touch devices.
The session will include many examples in all the common UI technologies: C++, WinForms, WPF and Silverlight.
The entrance is free, but requires registration.
Hope to see you there!
That’s it for now,
Arik Poznanski.
Before we continue, I trust that you know exactly the meaning of tombstone state in a Windows Phone 7 application. If this is not the case, simply read Yochay’s great posts on the application execution model (Part 1, Part 2, Part 3).

Every Windows Phone 7 application needs to manages tombstoning correctly to provide a better user experience and pass the application certification requirements.
When your application goes into tombstone state, it is your responsibility to save all the application and page state, so that when the page gets reloaded it can recover properly and reload the previous data. This was the user doesn’t even realizes that the application process got terminated and reloaded.
To ease the handling of the tombstone state I’ve created a simple StateManager class which helps serializing the data when going into tombstone state and deserializing the data when you get back.
How to Use StateManager?
Suppose your current page has the following data members you want to save across tombstoning:
- LastPosts
- Posts
- Comments
- Images
Now all you need to do is to save them when the application goes into tombstone state and reload them when it gets back from tombstone state.
Saving the Data
The proper place for the code that saves the data resides in the OnNavigatedFrom method. In this method you should call the helper extension method SaveState for each member of the page that you want to save, passing the value and the key on which to save it:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
this.SaveState("LastPostsKey", LastPosts);
this.SaveState("PostsKey", Posts);
this.SaveState("CommentsKey", Comments);
this.SaveState("ImagesKey", Images);
}
Loading the Data
The proper place for the code that loads the data when returning from tombstone state resides in OnNavigatedTo method. In this method you should call the helper extension method LoadState for each member of the page that you want to load, passing the key related to the member’s value:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
LastPosts = this.LoadState<ObservableCollection<RssItem>>("LastPostsKey");
Posts = this.LoadState<ObservableCollection<RssItem>>("PostsKey");
Comments = this.LoadState<ObservableCollection<RssItem>>("CommentsKey");
Images = this.LoadState<ObservableCollection<ImageItem>>("ImagesKey");
}
Definition of StateManager
So how is the StateManager class defined? It is as simple as the following two extension methods:
/// <summary>
/// State Manager
/// </summary>
public static class StateManager
{
/// <summary>
/// Saves a key-value pair into the state object
/// </summary>
/// <param name="phoneApplicationPage">The phone application page.</param>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
public static void SaveState(this PhoneApplicationPage phoneApplicationPage, string key, object value)
{
if (phoneApplicationPage.State.ContainsKey(key))
{
phoneApplicationPage.State.Remove(key);
}
phoneApplicationPage.State.Add(key, value);
}
/// <summary>
/// Loads value from the state object, according to the key.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="phoneApplicationPage">The phone application page.</param>
/// <param name="key">The key.</param>
/// <returns>The loaded value</returns>
public static T LoadState<T>(this PhoneApplicationPage phoneApplicationPage, string key)
where T : class
{
if (phoneApplicationPage.State.ContainsKey(key))
{
return (T)phoneApplicationPage.State[key];
}
return default(T);
}
}
Note: this code was first published as part of the “Using Pivot and Panorama Controls” lab found in the Windows Phone Training Kit for Developers, which I wrote for Microsoft.
That’s it for now,
Arik Poznanski.