<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DEcESX48eSp7ImA9WhRVGE4.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825</id><updated>2012-01-17T21:33:28.071Z</updated><category term="Ribbon" /><category term="Chrysalis" /><category term="Windows Phone 7" /><category term="DataLists" /><category term="DropDownButton" /><category term="dropshadows" /><category term="Windows 8" /><category term="Metro" /><category term="MVVM" /><category term="WPF" /><category term="Cocoon" /><title>Andy On WPF, Windows 8 and Beyond</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://andyonwpf.blogspot.com/" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/AndyOnWpf" /><feedburner:info uri="andyonwpf" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEcESX4zeip7ImA9WhRVGE4.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-2913475193406692329</id><published>2012-01-17T21:33:00.000Z</published><updated>2012-01-17T21:33:28.082Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-17T21:33:28.082Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Metro" /><category scheme="http://www.blogger.com/atom/ns#" term="DataLists" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows 8" /><category scheme="http://www.blogger.com/atom/ns#" term="Cocoon" /><title>Bridging the Data Divide–An Introduction to Cocoon Data Lists</title><content type="html">When I &lt;a href="http://andyonwpf.blogspot.com/2011/11/cocoon-new-framework-for-windows-8.html"&gt;first introduced the Cocoon framework&lt;/a&gt; one of the targets was to improve the ease at which data retrieval APIs (primarily web APIs) could be integrated into modern desktop applications. In this post I will introduce two concepts, the “data list” and the “data list source”, that are used in the &lt;a href="http://cocoon.codeplex.com/"&gt;Cocoon framework&lt;/a&gt; to simplify this process when writing Windows 8 Metro-style applications, in particular those implementing the MVVM design pattern.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
The Data Divide&lt;/h2&gt;
Let us first consider a typical web API that will return a list of information in response to a web request from a desktop application. In many cases there may be a large number of items in the list, so the API will split the results into several “pages”. For example, the hypothetical web call,&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; Task&amp;lt;PersonResult&amp;gt; GetEmployeesAsync(&lt;span style="color: blue;"&gt;int&lt;/span&gt; pageNumber) {...}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
Might return the resulting data for pageNumber=1,&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;br /&gt;
&lt;div id="codeSnippet" style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;PersonResult&lt;/span&gt; &lt;span style="color: red;"&gt;TotalCount&lt;/span&gt;&lt;span style="color: blue;"&gt;="450"&lt;/span&gt; &lt;span style="color: red;"&gt;Page&lt;/span&gt;&lt;span style="color: blue;"&gt;="1"&lt;/span&gt; &lt;span style="color: red;"&gt;PageSize&lt;/span&gt;&lt;span style="color: blue;"&gt;="50"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Person&lt;/span&gt; &lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;="Bob"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Person&lt;/span&gt; &lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;="Dave"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Person&lt;/span&gt; &lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;="Amy"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    ...&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;PersonResult&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
Here, whilst there are a total of 450 items in the data set, only the first 50 are returned. If you then require any further items then additional calls must be made for the second, third, etc. pages as required.&lt;br /&gt;
&lt;br /&gt;
In contrast let us consider a modern Windows 8 Metro-style UI. Here the user generally expects to see a single list of all items that can be scrolled through as desired. For performance reasons this list should take advantage of data virtualisation to retrieve data on demand, filling in the UI smoothly as the results are retrieved (see &lt;a href="http://andyonwpf.blogspot.com/2011/12/data-virtualization-in-metro-style-apps.html"&gt;my last post on VirtualizingVector&lt;/a&gt; for more information).&lt;br /&gt;
&lt;br /&gt;
It is this “data divide” between the state-less paged result sets of web APIs and the fluid continuous lists of desktop applications that often require much code to implement correctly. This is the problem that “data lists” and “data list sources” in the Cocoon framework are desired to solve.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
“Data Lists” and “Data List Sources”&lt;/h2&gt;
&lt;br /&gt;
The approach taken by the &lt;a href="http://cocoon.codeplex.com/"&gt;Cocoon framework&lt;/a&gt; is to separate the two concerns of the web API calls (or any other data access call) and the resulting lists to display in the UI into separate components. These can then be developed separately using their own conventions, with the Cocoon framework bridging the divide.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-ka6ijr-Y0v8/TxXoLdoOlnI/AAAAAAAAAC8/Y8j_M8xj99Y/s1600/Data+List+Scheme.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="55" src="http://3.bp.blogspot.com/-ka6ijr-Y0v8/TxXoLdoOlnI/AAAAAAAAAC8/Y8j_M8xj99Y/s400/Data+List+Scheme.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
In this model a web API call (or calls) that return information on a list of information is represented as part of a “data list source”. This understands how to query the source API to retrieve the list of data as required. In addition it is your application’s own representation of what it knows about the list of data – the length of the data set, and any items that have already been downloaded. This can be reused amongst different parts of your application and in some ways acts as a local cache of the data. Multiple data list sources will be available, for simple cases where all data is returned at once and for data that is returned by pages, as well as the option for custom implementations.&lt;br /&gt;
&lt;br /&gt;
At the other end of the chain is the “data list”. This is the IList&amp;lt;T&amp;gt; implementation that is bound to the UI, either via the code behind or through a view model. Multiple data lists can be attached to the same data list source so that the application’s view of the data is consistent. Different data list implementations can determine how the data is retrieved for display; for example,&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;StaticDataList – This will retrieve all the information before display to the user &lt;/li&gt;
&lt;li&gt;VirtualizingDataList – This will use data virtualization to only retrieve the data items that are currently visible to the user &lt;/li&gt;
&lt;li&gt;IncrementalLoadingDataList – This will initially show a fixed number of items, but allow the user to expand the list if they wish to see more items &lt;/li&gt;
&lt;li&gt;DynamicDataList – This will start with an empty list, with items being added as they are retrieved from the data list source&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Between the data list and the data list source are a number of optional processing steps. For example these could constrain the list to only the first 50 items for preview, they could filter the items based on a search term, or could group the items to display as part of a grouped grid view.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
The IDataListSource Interface&lt;/h2&gt;
All of the above is orchestrated by the Cocoon.Data.IDataListSource&amp;lt;T&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; IDataListSource&amp;lt;T&amp;gt;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    Task&amp;lt;&lt;span style="color: blue;"&gt;int&lt;/span&gt;&amp;gt; GetCountAsync();&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    Task&amp;lt;T&amp;gt; GetItemAsync(&lt;span style="color: blue;"&gt;int&lt;/span&gt; index);&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
You can think of this as an asynchronous version of IList&amp;lt;T&amp;gt;, albeit a minimal version. There are two methods:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;GetCountAsync() – Returns a task that results in the number of items in the list.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;GetItemAsync(int index) – Returns a task that results in the item at the specified index.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Note that the GetItemAsync(…) method should throw an exception if ‘index’ is less than zero, however if ‘index’ is greater than the last item it should return default(T) (for reference types this will be null).&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Summary&lt;/h2&gt;
To summarize, the &lt;a href="http://cocoon.codeplex.com/"&gt;Cocoon framework&lt;/a&gt; supplies an infrastructure designed to bridge the gap between state-less web APIs and modern fluid Windows 8 Metro style applications. Over the next few blog posts (and associated code drops) I will provide a number of generic implementations of data lists and data list sources to make consuming lists of data from the web quick and easy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-2913475193406692329?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/YHK2XGMWPCM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/2913475193406692329/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=2913475193406692329" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/2913475193406692329?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/2913475193406692329?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/YHK2XGMWPCM/bridging-data-dividean-introduction-to.html" title="Bridging the Data Divide–An Introduction to Cocoon Data Lists" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-ka6ijr-Y0v8/TxXoLdoOlnI/AAAAAAAAAC8/Y8j_M8xj99Y/s72-c/Data+List+Scheme.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2012/01/bridging-data-dividean-introduction-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04ARHo8fSp7ImA9WhRXEEs.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-5758044888246569201</id><published>2011-12-14T22:25:00.001Z</published><updated>2011-12-16T18:59:05.475Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-16T18:59:05.475Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Metro" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows 8" /><category scheme="http://www.blogger.com/atom/ns#" term="Cocoon" /><title>Data Virtualization in Metro-style apps with IVirtualizingVector</title><content type="html">In my &lt;a href="http://andyonwpf.blogspot.com/2011/12/observablevector-as-replacement-for.html"&gt;last post&lt;/a&gt; I introduced an implementation of the IObservableVector&amp;lt;T&amp;gt; interface that allows Windows 8 Metro-style applications to automatically update data bound XAML items controls as the underlying data source changes. In this post I am going to delve one stage deeper by demonstrating an implementation of the IVirtualizingVector interface that enables data virtualization&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
A Background to Data Virtualization&lt;/h2&gt;
To start I will provide some background to data virtualization and explain why this is becoming essential for modern applications to improve performance with large data sets. In a traditional, non-data-virtualized application, lists of data must be fully loaded into memory before they can be displayed to the user. When this data is held in a local database or file system this may mean loading many hundred items into memory before being shown in the user interface. With modern cloud-connected applications this becomes more of an issue as they must all be downloaded across what is a relatively slow connection.&lt;br /&gt;
In web applications this problem has been solved by the concept of paging – only a small number of items are shown at any one time, and the user can move between the pages by following links. In client based applications however the user expects a more seamless experience – a single list that can be scrolled through as desired.&lt;br /&gt;
Data virtualization solves this problem by only downloading and storing in memory the data that is required, deferring the download of further items until they are scrolled into view. The user sees a single list as if they are viewing the total data set, however as they move through the list any newly visible items are obtained on demand.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Data Virtualization for Metro-Style Apps&lt;/h2&gt;
In Windows 8, Metro style applications support virtualized lists through the IVirtualizingVector interface,&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; IVirtualizingVector : IObservableVector&amp;lt;&lt;span style="color: blue;"&gt;object&lt;/span&gt;&amp;gt;, IList&amp;lt;&lt;span style="color: blue;"&gt;object&lt;/span&gt;&amp;gt;, IEnumerable&amp;lt;&lt;span style="color: blue;"&gt;object&lt;/span&gt;&amp;gt;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    &lt;span style="color: blue;"&gt;bool&lt;/span&gt; IsPlaceholder(&lt;span style="color: blue;"&gt;object&lt;/span&gt; item);&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
At first sight it is not immediately obvious how this can be used to virtualize a list, however it provides the vital link between a virtualization aware data set and a data bound user interface. An IVirtualizingVector implementation is responsible for providing any data virtualization logic,&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;In general the list should behave as you would expect for an IObservableVector&amp;lt;T&amp;gt; implementation&lt;/li&gt;
&lt;li&gt;When the items are requested the list should return the actual item if this is available, or a placeholder item if it has yet to be downloaded &lt;/li&gt;
&lt;li&gt;The IsPlaceholder(…) method may then be called with each item returned in the list, and the IVirtualizingVector implementation should return true if this is a placeholder item, otherwise false &lt;/li&gt;
&lt;li&gt;It is also the responsibility of the IVirtualizingVector implementation to download any requested items in the background and update the list as these are available.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
In return the standard Metro-style items controls will show any items for which IsPlaceholder(…) returns true as a grey rectangle,&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-ekgo7MLlCl8/TuuUGI5DLZI/AAAAAAAAACg/poEYTmglyW8/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="218" src="http://2.bp.blogspot.com/-ekgo7MLlCl8/TuuUGI5DLZI/AAAAAAAAACg/poEYTmglyW8/s400/Untitled.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
An IVirtualizingVector Implementation&lt;/h2&gt;
&lt;br /&gt;
To assist with data virtualization in .Net based Metro-style applications a base implementation is provided as part of the freely available &lt;a href="http://cocoon.codeplex.com/"&gt;Cocoon&lt;/a&gt; framework. This is provided as the Cocoon.Data.VirtualizingVector abstract class, into which you simply provide your custom data retrieval logic. You will either be requested for the number of items in the list or a specific item, and once obtained should then call the UpdateCount(…) or UpdateItem(…) methods 
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;br /&gt;
&lt;div id="codeSnippet" style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; PersonCollection : VirtualizingVector&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; FetchCount()&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    {&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;        &lt;span style="color: green;"&gt;// Perform custom code here to retrieve&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;        &lt;span style="color: green;"&gt;//     the number of items in the dataset&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;        UpdateCount(itemCount);&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    }&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; FetchItem(&lt;span style="color: blue;"&gt;int&lt;/span&gt; index)&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    {&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;        &lt;span style="color: green;"&gt;// Perform custom code here to retrieve&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;        &lt;span style="color: green;"&gt;//     the specified item from the dataset&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;         UpdateItem(index, retrievedItem);&lt;/pre&gt;
&lt;pre style="background-color: white; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;    }&lt;/pre&gt;
&lt;pre style="background-color: #f4f4f4; color: black; direction: ltr; font-family: &amp;quot;Courier New&amp;quot;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
The VirtualizingVector class then takes care of implementing IVirtualizingVector, returning of suitable placeholder objects for items as they are requested, and updating items with real data as it is made available.&lt;br /&gt;
&lt;br /&gt;
Of course this approach would still consume large amounts of memory when displaying a list with a large number of placeholder items. The VirtualizingVector class overcomes this by using the provided VirtualizingList&amp;lt;T&amp;gt; implementation. Without going into detail, this behaves as you would expect for a list with a large number of elements, whilst allocating memory efficiently to store only those items that are not virtualized.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Summary&lt;/h2&gt;
&lt;br /&gt;
In conclusion, the Cocoon framework provides an IVirtualizingVector implementation designed to enable data virtualization for Metro-style applications. The code is freely available for download from the &lt;a href="http://cocoon.codeplex.com/"&gt;Cocoon CodePlex site&lt;/a&gt; (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link). &lt;br /&gt;
In my &lt;a href="http://andyonwpf.blogspot.com/2011/11/cocoon-new-framework-for-windows-8.html"&gt;introduction to the Cocoon framework&lt;/a&gt; I stated that one of my aims was to bridge the divide between the stateless paging model of most web APIs and the “fast and fluid” interfaces of Metro-style applications. Now that I have provided the fundamentals, next time I will try to bridge this gap by introducing “data lists” and “data list sources”.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-5758044888246569201?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/t5TeOngUsj8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/5758044888246569201/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=5758044888246569201" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/5758044888246569201?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/5758044888246569201?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/t5TeOngUsj8/data-virtualization-in-metro-style-apps.html" title="Data Virtualization in Metro-style apps with IVirtualizingVector" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ekgo7MLlCl8/TuuUGI5DLZI/AAAAAAAAACg/poEYTmglyW8/s72-c/Untitled.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2011/12/data-virtualization-in-metro-style-apps.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cHQHs8cCp7ImA9WhRRF0s.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-8919247139921552574</id><published>2011-12-01T19:50:00.001Z</published><updated>2011-12-01T19:50:31.578Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-01T19:50:31.578Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Metro" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows 8" /><category scheme="http://www.blogger.com/atom/ns#" term="Cocoon" /><title>ObservableVector as a replacement for ObservableCollection in Metro-style apps</title><content type="html">&lt;p&gt;For those of you who have had previous experience in making WPF and Silverlight applications you are probably familiar with the ObservableCollection&amp;lt;T&amp;gt; class. This represents a list of items (implementing IList&amp;lt;T&amp;gt;) whilst also raising the INotifyCollectionChanged.CollectionChanged event whenever items are added, removed or moved within the collection. When such collections are databound to the various list controls in WPF and Silverlight the UI will automatically update to reflect any changes.&lt;/p&gt; &lt;h1&gt;&lt;/h1&gt; &lt;h2&gt;ObservableCollection&amp;lt;T&amp;gt; and Metro-Style Apps&lt;/h2&gt; &lt;p&gt;If you have followed the same technique when writing Windows 8 Metro-style apps you will have found that this no longer works. There are a couple of reasons for this behaviour,&lt;/p&gt; &lt;ol&gt; &lt;li&gt;In the Developer Preview version of Windows 8 the INotifyPropertyChanged interface is duplicated in both the System.ComponentModel and Windows.UI.Xaml.Data namespaces. Whilst ObservableCollection&amp;lt;T&amp;gt; implements the former, the new Metro XAML framework uses the latter.&lt;/li&gt; &lt;li&gt;Rather than INotifyCollectionChanged as implemented by ObservableCollection&amp;lt;T&amp;gt;, WinRT uses the &lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/br226052(v=vs.85).aspx"&gt;IObservableVector&amp;lt;T&amp;gt;&lt;/a&gt; interface.&lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;Observable Collections in Metro-Style Apps&lt;/h2&gt; &lt;p&gt;Whilst this issue is likely to be addressed prior to release of Windows 8, for the time being there are a few workarounds.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;The &lt;a href="http://code.msdn.microsoft.com/windowsapps/Data-Binding-7b1d67b5"&gt;Windows 8 SDK Data Binding sample&lt;/a&gt; includes an ObservableVector class that takes an existing object that implements INotifyCollectionChanged, and wraps it in an IObservableVector&amp;lt;T&amp;gt; implementation.&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.scottlogic.co.uk/blog/colin/2011/10/using-observablecollection-with-winrt-via-a-little-shim/"&gt;Colin Eberhardt has posted a similar solution on his blog&lt;/a&gt;.&lt;/li&gt; &lt;li&gt;Avi Pilosof has taken a slightly different approach by deriving a new class from ObservableCollection&amp;lt;T&amp;gt;, implementing both INotifyCollectionChanged and IObservableVector&amp;lt;T&amp;gt;.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Whilst these solve the problem, they all involve wrapping the existing ObservableCollection&amp;lt;T&amp;gt; class, resulting in events being raised for both the old and new approaches. This is ideal for cases where you wish to write interoperable code for both existing and Metro applications, but is an added overhead when you are natively writing a new Windows 8 application.&lt;/p&gt; &lt;h2&gt;A Metro-Designed Observable Collection Class&lt;/h2&gt; &lt;p&gt;In response to this I have written a ground-up ObservableVector&amp;lt;T&amp;gt; class for use in Windows 8 Metro-style applications that does not have the overhead of an underlying ObservableCollection&amp;lt;T&amp;gt;. The code has been released as part of the freely available &lt;a href="http://cocoon.codeplex.com/"&gt;Cocoon&lt;/a&gt; framework. You can use this class by creating a new instance directly,&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;IList&amp;lt;Person&amp;gt; list = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ObservableVector&amp;lt;Person&amp;gt;();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;list.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Person(&lt;span style="color: #006080"&gt;"Andrew"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Wilkinson"&lt;/span&gt;));&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;or by deriving a custom class,&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; PersonCollection : ObservableVector&amp;lt;Person&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;It is important to note however that in the current Windows Developer Preview there is a bug which means that databinding only works correctly to lists when the implement ObservableVector&amp;lt;object&amp;gt; rather than strongly typed collections. This is likely to change in the future.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In both cases the behaviour is designed to match that expected by WPF and Silverlight developers. There are a small number of subtle differences with respect to the previous ObservableCollection&amp;lt;T&amp;gt; class,&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Since IObservableVector&amp;lt;T&amp;gt; does not have the same concept of moving items it does not implement the Move() method. Instead you should remove the item and then add it to its new place in the collection.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The constructor of the ObservableVector&amp;lt;T&amp;gt; class optionally accepts an IList&amp;lt;T&amp;gt; that is wrapped by the implementation rather than copied internally – the reason for this will become apparent in later posts.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Currently no attempts are made to stop VectorChanged event handlers from modifying the original collection.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;In conclusion, the Cocoon framework provides an IObservableVector&amp;lt;T&amp;gt; implementation specifically designed from the ground-up for Metro applications. The code is freely available for download from the &lt;a href="http://cocoon.codeplex.com/"&gt;Cocoon CodePlex site&lt;/a&gt; (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Next time I will discuss data virtualisation and the IVirtualizingVector interface.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-8919247139921552574?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/9QcWjaZfIdA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/8919247139921552574/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=8919247139921552574" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/8919247139921552574?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/8919247139921552574?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/9QcWjaZfIdA/observablevector-as-replacement-for.html" title="ObservableVector as a replacement for ObservableCollection in Metro-style apps" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2011/12/observablevector-as-replacement-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMGRXo8eip7ImA9WhRRFE8.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-3662431130492217098</id><published>2011-11-27T20:07:00.001Z</published><updated>2011-11-27T20:07:04.472Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-27T20:07:04.472Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Metro" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows 8" /><category scheme="http://www.blogger.com/atom/ns#" term="Cocoon" /><title>Cocoon – A new framework for Windows 8 Development</title><content type="html">&lt;p&gt;Regular followers of my blog will know that over the last year I have been discussing a framework that I introduced for Windows Phone 7 development named Chrysalis (&lt;a href="http://chrysalis.codeplex.com/"&gt;http://chrysalis.codeplex.com/&lt;/a&gt;). Whilst not a Model-View-ViewModel (MVVM) framework itself, allowing the use of your preferred framework for this purpose, it was designed to enable view models to interact with the phone lifecycle and hardware in a simple and natural manner.&lt;/p&gt; &lt;p&gt;Following the announcement of the Windows 8 Metro-style application programming model at Microsoft’s &lt;a href="http://www.buildwindows.com/"&gt;//build&lt;/a&gt; conference, it became clear that many of the same challenges would present themselves for Windows 8 applications.&lt;/p&gt; &lt;h2&gt;The Cocoon Framework&lt;/h2&gt; &lt;p&gt;To assist with Windows 8 Metro-style applications I would like to announce the Cocoon framework (&lt;a href="http://cocoon.codeplex.com/"&gt;http://cocoon.codeplex.com/&lt;/a&gt;). This aims to build on top of the learning from the Chrysalis project to provide a simple way to develop Metro-style applications in a manner that fits naturally with the MVVM design pattern.&lt;/p&gt; &lt;p&gt;It is likely that many Metro-style apps will be connected applications, downloading data from across the internet in response to user navigation. Modern applications are expected to do this in a seamless manner, retrieving data on demand and populating the user interface in response. In some ways this is at odds with the web API programming model that is based upon individual request-response calls, with paging used to retrieve large datasets. One of the first targets of the Cocoon framework is to simplify this process – bridging the world of stateless web API calls, with the “fast and fluid” interfaces expected by users.&lt;/p&gt; &lt;h2&gt;Cocoon Framework Development&lt;/h2&gt; &lt;p&gt;Since Windows 8 is currently at an early stage, it is anticipated that the Cocoon framework will evolve alongside further releases. If functionality is introduced in the platform that duplicates that within the Cocoon framework, efforts will be made to migrate to the platform support whenever possible.&lt;/p&gt; &lt;p&gt;It is an exciting time for Windows developers, with the upcoming release of Windows 8 ushering in a new ecosystem of applications. The Cocoon framework will allow you to focus on your individual business logic, whilst ensuring that the user experience fully supports the richness of the platform.&lt;/p&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;To conclude, the first source-code drops of the Cocoon framework are freely available on CodePlex (&lt;a href="http://cocoon.codeplex.com/"&gt;http://cocoon.codeplex.com/&lt;/a&gt;). As the project evolves, new functionality will be explained on this blog so stay tuned.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-3662431130492217098?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/L53M61_8fpE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/3662431130492217098/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=3662431130492217098" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/3662431130492217098?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/3662431130492217098?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/L53M61_8fpE/cocoon-new-framework-for-windows-8.html" title="Cocoon – A new framework for Windows 8 Development" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2011/11/cocoon-new-framework-for-windows-8.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8NR348eyp7ImA9WhdaFUo.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-5345714014358077084</id><published>2011-10-25T22:05:00.001+01:00</published><updated>2011-10-25T22:08:16.073+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-25T22:08:16.073+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Chrysalis" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone 7" /><title>Chrysalis – Injection of Application Services and State</title><content type="html">&lt;p&gt;In &lt;a href="http://andyonwpf.blogspot.com/2010/12/chrysalis-application-and-session-state.html"&gt;my last post&lt;/a&gt; I introduced the concept of application and session state within a Windows Phone 7 application, and described how the Chrysalis framework makes it easy to share state between multiple pages (and hence view models) within an application, including full tombstoning support. As usual, all the source code is available on the &lt;a href="http://chrysalis.codeplex.com/"&gt;Chrysalis CodePlex site&lt;/a&gt; under the “Source Code” tab.&lt;/p&gt; &lt;h2&gt;&lt;/h2&gt; &lt;h2&gt;&lt;/h2&gt; &lt;h2&gt;Application Services&lt;/h2&gt; &lt;p&gt;To recap, Chrysalis allows multiple view models to share the same state between multiple pages by using one of the two ChrysalisService.GetService methods,&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ChrysalisService&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;      ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; T GetService&amp;lt;T&amp;gt;() { ... }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; GetService(Type serviceType) { ... }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;      ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The first time one of these methods is called, a new instance of the specified type is created (calling the default parameter-less constructor). Any subsequent calls will return the same “singleton” instance. As the method names allude to, this can be used not only for general state, but for any services that may wish to be shared throughout the application.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Furthermore, Chrysalis makes it simple for these services to persist state when the application is tombstoned. All that is required is for the service to implement the IHasSessionState interface,&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IHasSessionState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Methods ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Initialize(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; state);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; SaveState();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The first time the service is created within a session the Initialize method is called with the state parameter set to null. In this instance default values can be set along with any other initialization required by the service. Upon tombstoning the SaveState method is called from which you can return any state you wish to persist. Upon reactivation this state is passed back to the newly created instance of the service (remember – during tombstoning the application process is killed and all objects are lost) via the Initialize method.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Chrysalis and Dependency Injection&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Whilst the ChrysalisService class provides the GetService methods, this is only one way in which your view models can obtain such state information. Another method is “dependency injection”. This refers to a situation where external dependencies (in our case the state objects) are injected into our view model, rather than the view model itself having to seek them out.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In Chrysalis this is done by defining public properties for each of the services that we wish to inject into the view model. To indicate that these should be injected we add the [ChrysalisImport] attribute to the property. Finally, in the constructor we check whether Chrysalis is initialised and tell the ChrysalisService to satisfy any imports by calling the SatifyImports(…) method.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For example within the sample CalculatorViewModel included with the source download,&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CalculatorViewModel : ViewModelBase, IHasSessionState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Constructors ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; CalculatorViewModel()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ChrysalisService.Current != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;             ChrysalisService.Current.SatisfyImports(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Properties ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     [ChrysalisImport]&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; CalculatorSessionState SessionState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         get;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         set;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;This defines a property called SessionState that is marked with the [ChrysalisImport] attribute. In the constructor we notify Chrysalis that it should inject any dependencies, which when it returns will have set the property to an instance of CalculatorSessionState. As with the GetService calls this will return the same instance across all view models, creating a new object only if this is the first such reference. Note that you can define any number of properties to be injected and they will all be satisfied by the one SatisfyImports(…) call.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Using Interfaces for Dependency Injection&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Whilst being able to declaratively inject singleton instances of classes is useful, there are a number of reasons that you would wish to decouple such properties from the concrete implementations – for example to inject mock implementations for testing purposes. This is usually done by specifying an interface rather than a class type, and this too is enabled in the Chrysalis framework.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For example in the ChoosersViewModel sample included in the source code,&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [ChrysalisImport]&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IChooserExecutionService ChooserExecutionService&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     get;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     set;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;p&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; }&lt;/p&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;However, we now need a way to link the interface to the concrete implementation. In the Chrysalis framework this is done by simply attributing the interface with the ExportImplementationAttribute specifying the concrete type to use.&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [ExportImplementationAttribute(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ChooserExecutionService))]&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IChooserExecutionService&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;&lt;br /&gt;&lt;h2&gt;Comparing Chrysalis with Other Dependency Injection Frameworks&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Before I conclude I would like to take a moment to contrast dependency injection in the Chrysalis framework to other implementations. Dependency injection within Chrysalis was designed to support the very basic injection of services (to enable unit testing, etc.) and integration with the rest of the Chrysalis model – this it performs well. If you require more advanced services then it is recommended that you use a full dependency injection container implementation.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-5345714014358077084?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/uRHAViz8Bw0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/5345714014358077084/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=5345714014358077084" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/5345714014358077084?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/5345714014358077084?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/uRHAViz8Bw0/chrysalis-injection-of-application.html" title="Chrysalis – Injection of Application Services and State" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2011/10/chrysalis-injection-of-application.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAARXY5eSp7ImA9Wx9RE0s.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-4873385331479879836</id><published>2010-12-14T21:55:00.001Z</published><updated>2010-12-14T21:55:44.821Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-14T21:55:44.821Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrysalis" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone 7" /><title>Chrysalis – Application and Session State</title><content type="html">&lt;p&gt;In my last few posts I have focused on the tombstoning features of the Chrysalis Windows Phone 7 application framework. In this post I will look at the related role of application and session state, and how these can ensure that data is persisted during tombstoning using the Chrysalis framework. As usual, all the source code is available on the &lt;a href="http://chrysalis.codeplex.com/"&gt;Chrysalis CodePlex site&lt;/a&gt; under the “Source Code” tab.&lt;/p&gt; &lt;h2&gt;Application and Session State&lt;/h2&gt; &lt;p&gt;All examples of state I have discussed so far have been associated with a single page of a Windows Phone 7 application (view state), ensuring that any data entered is persisted during navigation and application tombstoning. In real applications much of the data crosses across multiple pages, and hence multiple views and view models. Application data is data that stores settings and information that is reused between multiple application instances. This includes user settings, user details as well as any downloaded data that rarely changes. Session data on the other hand is data that crosses multiple pages of an application, but is not reused between application instances, such as session keys for web services or some transient state.&lt;/p&gt; &lt;p&gt;When, and how the data is different for each of these types of state,&lt;/p&gt; &lt;ul&gt; &lt;li&gt;View state – Persisted on navigation to/from the page to the page state bag.  &lt;li&gt;Application state – Persisted and restored upon application shutdown/startup and also during tombstoning using isolated storage.  &lt;li&gt;Session state – Persisted during tombstoning to the application state bag.&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;Storing Application and Session State with Chrysalis&lt;/h2&gt; &lt;p&gt;When working with data that crosses several pages (and therefore view models) we need a way to ensure that we can store and access the same data from each page. In the ‘Calculator’ sample provided with Chrysalis, this data is stored in the CalculatorSessionState object,&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CalculatorSessionState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Properties ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Operator { get; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;This simply stores the current operator (+, –, / or *) that the calculator is using as a string. This is also displayed on the Calculator information page, and is true session state in that navigation back from the calculator page, and then returning will persist the value chosen.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Since we need to access the state from both the CalculatorViewModel and the CalculatorInformationViewModel, we need to be able to create a single instance of this state to share across both of these locations. Chrysalis provides a simple and straightforward way of creating such “singleton” objects by calling one of the ChrysalisService.GetService methods,&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ChrysalisService&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; T GetService&amp;lt;T&amp;gt;() { ... }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; GetService(Type serviceType) { ... }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;This method will return a single instance of the requested type, initializing a new instance if this is the first such request (note that this will call, and requires, a public parameter-less constructor). Now we can call this method in the constructors of the CalculatorViewModel and the CalculatorInformationViewModel and be sure that we have the same instance in each case.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Supporting Tombstoning&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;So far I have shown how to share state between pages, but what happens when the application is tombstoned (see &lt;a href="http://andyonwpf.blogspot.com/2010/09/introducing-chrysalis.html"&gt;here&lt;/a&gt; if you wish to refresh yourself on what this means)? Since the process is killed, any state will be lost. On restart we have an entirely new process so Chrysalis will create a new instance with default values.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;To provide a seamless user experience, we should persist any session state and restore it when the application is reactivated. Chrysalis makes this easy. All you have to do is to ensure that your state object implements the IHasSessionState interface. For example, the full code for CalculatorSessionState is,&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CalculatorSessionState : IHasSessionState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Properties ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Operator { get; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** IHasSessionState Methods ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; IHasSessionState.Initialize(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; state)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         SessionState sessionState = state &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; SessionState;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (sessionState == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;             Operator = &lt;span style="color: #006080"&gt;"+"&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;             Operator = sessionState.Operator;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; IHasSessionState.SaveState()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SessionState()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;             {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;                 Operator = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Operator&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;             };&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Sub-classes ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SessionState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Operator { get; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Now when the class is first initialised, Chrysalis will call the IHasSessionState.Initialize method. If the application has just been launched the ‘state’ parameter will be null and we can initialise with default values. When the application is subsequently tombstoned Chrysalis will call the IHasSessionState.SaveState method, from which we can return some state to persist until later reactivated. When this does occur a new instance of CalculatorSessionState is created, but this time our previously returned state is supplied as the parameter which we can restore.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;We have now seen how Chrysalis can easily allow you to share session state between pages. By using the &lt;a href="http://andyonwpf.blogspot.com/2010/09/chrysalis-tombstoning-support-part-i.html"&gt;Chrysalis tombstoning support&lt;/a&gt; on the view model and the IHasSessionState interface on any shared state, we should no longer worry about what will happen if our application is tombstoned. Chrysalis will ensure that any state is restored to that before we were tombstoned, and your users will have a seamless experience.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Once again, you can download a zip file of the entire source code for Chrysalis and the associated sample application from the “Source Code” tab at the &lt;a href="http://chrysalis.codeplex.com/"&gt;Chrysalis CodePlex site&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-4873385331479879836?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/CAbhCC3Qm7k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/4873385331479879836/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=4873385331479879836" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/4873385331479879836?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/4873385331479879836?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/CAbhCC3Qm7k/chrysalis-application-and-session-state.html" title="Chrysalis – Application and Session State" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2010/12/chrysalis-application-and-session-state.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMNRn8yfyp7ImA9Wx9TE0o.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-692662384557940384</id><published>2010-11-21T21:04:00.001Z</published><updated>2010-11-21T21:04:57.197Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-21T21:04:57.197Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrysalis" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone 7" /><title>Chrysalis – Tombstoning support (Part II - Implementation Details)</title><content type="html">&lt;p&gt;In my &lt;a href="http://andyonwpf.blogspot.com/2010/09/chrysalis-tombstoning-support-part-i.html"&gt;last post&lt;/a&gt; I introduced the tombstoning features of the Chrysalis Windows Phone 7 application framework. To summarise, this allowed developers using the Model-View-ViewModel presentation pattern to easily ensure that their ViewModels could maintain their state during tombstoning. In this post I will provide an overview of how Chrysalis implements this feature. As usual, all the source code is available on the &lt;a href="http://chrysalis.codeplex.com/"&gt;Chrysalis CodePlex site&lt;/a&gt; under the “Source Code” tab.&lt;/p&gt; &lt;h2&gt;The Chrysalis Service&lt;/h2&gt; &lt;p&gt;One of the first steps when using the Chrysalis framework is to register the ChrysalisService in the App.xaml file’s ApplicationLifetimeObjects section (see my &lt;a href="http://andyonwpf.blogspot.com/2010/09/chrysalis-tombstoning-support-part-i.html"&gt;last post&lt;/a&gt; for details). This takes advantage of Silverlight’s application extension services (see &lt;a href="http://msdn.microsoft.com/en-us/library/dd833084(v=VS.95).aspx"&gt;MSDN&lt;/a&gt;) which allow you to register services that run at start-up of the application. The advantage of this approach is that once registered, the rest of the application can take advantage of the features of ChrysalisService without having to use any custom base classes of pages, View Models, etc.&lt;/p&gt; &lt;p&gt;The bulk of the initialization of the ChrysalisService happens within the StartService method, which Siliverlight calls during application start-up.&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; IApplicationService.StartService(ApplicationServiceContext context)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Set this as the current ServiceManager via the static property&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     ChrysalisService.Current = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Attach to the PhoneApplicationService lifetime events&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     PhoneApplicationService phoneApplicationService = PhoneApplicationService.Current;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     phoneApplicationService.Activated += &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; EventHandler&amp;lt;ActivatedEventArgs&amp;gt;(PhoneApplicationService_Activated);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     phoneApplicationService.Deactivated += &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; EventHandler&amp;lt;DeactivatedEventArgs&amp;gt;(PhoneApplicationService_Deactivated);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     phoneApplicationService.Closing += &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; EventHandler&amp;lt;ClosingEventArgs&amp;gt;(PhoneApplicationService_Closing);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Attach to the page navigation events&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// NB: We set off a DispatcherTimer since we need to wait for the RootVisual property to be set before we can access this&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     ExecuteViaDispatcherTimer(() =&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Application.Current.RootVisual != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;                 PhoneApplicationFrame_RootVisualLoaded((PhoneApplicationFrame)Application.Current.RootVisual);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         });&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Firstly we store a static reference to our service so that we can find it at any other point within the application execution. After this we get the current &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice(VS.92).aspx"&gt;PhoneApplicationService&lt;/a&gt; (added by default to all Silverlight Windows Phone 7 applications). Since Silverlight will initialize all application services in the order we have specified in the App.xaml file, this will already have been initialized. We then attach to the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.activated(v=VS.92).aspx"&gt;Activated&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.deactivated(v=VS.92).aspx"&gt;Deactivated&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.closing(v=VS.92).aspx"&gt;Closing&lt;/a&gt; events. Note that we do not need to attach to the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.launching(v=VS.92).aspx"&gt;Launching&lt;/a&gt; event since we can identify this if our service has been initialized without the Activated event.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The next step is to attach to navigation events to and from pages within the application. Normally you would do this by using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.navigation.navigationservice(v=VS.92).aspx"&gt;NavigationService&lt;/a&gt; class accessible from the current page, but since at this point of application execution no page is present (and hence the application’s RootVisual property is null) we have no way to access this. The ChrysalisService class overcomes this problem by queuing a request using a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer(v=VS.95).aspx"&gt;DispatcherTimer&lt;/a&gt; with a delay of 0ms. Although this sounds like it should execute immediately, the contract for the DispatcherTimer merely states that it should call the callback &lt;u&gt;at least&lt;/u&gt; the specified time after starting. In fact this is queued up when the dispatcher next becomes free, conveniently after the RootVisual has been initialized.&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PhoneApplicationFrame_RootVisualLoaded(PhoneApplicationFrame frame)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Attach to the navigation events&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     frame.Navigating += &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NavigatingCancelEventHandler(NavigationService_Navigating);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     frame.Navigated += &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NavigatedEventHandler(NavigationService_Navigated);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Set the current page&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     CurrentPage = frame.Content &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; PhoneApplicationPage;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;We can then use the RootVisual (which we know for Windows Phone 7 Silverlight applications will be a &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.controls.phoneapplicationframe(VS.92).aspx"&gt;PhoneApplicationFrame&lt;/a&gt;) to attach to the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.frame.navigating(v=VS.92).aspx"&gt;Navigating&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.frame.navigated(v=VS.92).aspx"&gt;Navigated&lt;/a&gt; events. We also store a reference to the current page for future use, which is also updated on any successful navigation events.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Notifying the ViewModel of application events&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Now the ChrysalisService is able to identify all the application events of interest, we need a way to pass this to the current ViewModel. This is done via the two interfaces, IPhoneLifetimeAware and IPhoneNavigationAware.&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IPhoneLifetimeAware&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Activated();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Closed();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Deactivated();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Launched();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IPhoneNavigationAware&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; NavigatingFrom(NavigatingCancelEventArgs e);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; NavigatedTo(NavigationEventArgs e);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Since we are tracking the current page at any point of time, we can identify the ViewModel associated with it by using the DataContext of that page. If the returned object implements either of the above interfaces then we can call the relevant methods in response to application events.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Storing application page state&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;We have not yet addressed the main use of this feature, for storing state relevant to the ViewModel during tombstoning. This is done via a third interface that the ViewModel can implement (as is done by the provided ViewModelBase class), IHasSessionState.&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IHasSessionState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Initialize(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; state);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; SaveState();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;The SaveState() method is called by ChrysalisService whenever the application is Deactivated or when navigation occurs away from the respective page. From this method the ViewModel can return some state that will be automatically persisted during tombstoning.&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Similarly, the Initialize(…) method is called by ChrysalisService whenever the application is Activated or when navigation occurs to the respective page. The ViewModel can then reinstate any state required to recreate the page prior to tombstoning.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;I have now described how the &lt;a href="http://chrysalis.codeplex.com/"&gt;Chrysalis&lt;/a&gt; application framework allows developers to easily manage any state relating to individual ViewModels (and therefore to individual pages of an application). In my next post I will describe how Chrysalis allows applications to store application state that may span several pages, and how this can easily be persisted between tombstoning and application restarts as is required.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-692662384557940384?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/oGMPAEXOxy4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/692662384557940384/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=692662384557940384" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/692662384557940384?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/692662384557940384?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/oGMPAEXOxy4/chrysalis-tombstoning-support-part-ii.html" title="Chrysalis – Tombstoning support (Part II - Implementation Details)" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2010/11/chrysalis-tombstoning-support-part-ii.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQCR3w6fCp7ImA9Wx5UE0k.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-2582241002398696289</id><published>2010-09-24T20:36:00.001+01:00</published><updated>2010-10-17T21:29:26.214+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-17T21:29:26.214+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrysalis" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone 7" /><title>Chrysalis – Tombstoning support (Part I - Introduction)</title><content type="html">&lt;p&gt;As I discussed in my &lt;a href="http://andyonwpf.blogspot.com/2010/09/introducing-chrysalis.html"&gt;previous post&lt;/a&gt;, when you are writing Silverlight (or XNA) based Windows Phone 7 applications, one of the considerations you must make is regarding supporting the “tombstoning” of your application. At any point during its execution your application may receive notification that you must save any state and exit, to possibly (but not always) be restarted at a later point. This however is you application’s view – to the user they must &lt;em&gt;believe&lt;/em&gt; that you application was waiting patiently in the background, unaware of the tearing down and restarting that is actually occurring.&lt;/p&gt; &lt;p&gt;If you are following the Model-View-ViewModel presentation pattern then the best placed entity in the system to know about what state to persist when tombstoning is the ViewModel. You have to firstly ensure that the application subscribes correctly to the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.deactivated(v=VS.92).aspx"&gt;PhoneApplicationService.Deactivated&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.activated(v=VS.92).aspx"&gt;PhoneApplicationService.Activated&lt;/a&gt; events. These must pass the requests onto the ViewModel which must store its state in the correct locations. Upon reactivation the ViewModel must know that it has some stored state, retrieve it and then restore the UI to that before the deactivation.&lt;/p&gt; &lt;p&gt;Transparently handling these steps is one of the key features of the Chrysalis framework.&lt;/p&gt; &lt;h2&gt;How to use Chrysalis for Tombstoning?&lt;/h2&gt; &lt;p&gt;Supplied with yesterdays drop of the Chrysalis framework is a sample calculator application. Whilst not particularly useful, it is intended to show how Chrysalis simplifies tombstoning. At its heart is the CalculatorViewModel.&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CalculatorViewModel : ViewModelBase&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Fields ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; numberX = 10;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; numberY = 5;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// *** Properties ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; NumberX&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         get&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; numberX;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         set&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;             numberX = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;             OnPropertyChanged(&lt;span style="color: #006080"&gt;"NumberX"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;             OnPropertyChanged(&lt;span style="color: #006080"&gt;"Total"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; NumberY&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;         get&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; numberY;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;         set&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;             numberY = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;             OnPropertyChanged(&lt;span style="color: #006080"&gt;"NumberY"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;             OnPropertyChanged(&lt;span style="color: #006080"&gt;"Total"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;     &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Total&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;         get&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum42"&gt;  42:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; NumberX + NumberY;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum43"&gt;  43:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum44"&gt;  44:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum45"&gt;  45:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;This derives from Chrysalis.ViewModelBase base class and includes three properties. The properties ‘NumberX’ and ‘NumberY’ are editable and both bound to TextBoxes in the associated UI (CalculatorView.xaml). The ‘Total’ property simply returns the sum of the two other values and is bound to a read-only TextBox in the UI. Property changed notifications are raised by calling OnPropertyChanged(…) on the base class.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;At this stage everything will look familiar to the Silverlight or WPF developer, and the application will run as expected,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_hUwtjPLXAAY/TJz9qpWStJI/AAAAAAAAABw/p84fUF2c53I/s1600-h/Calculator5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Calculator" border="0" alt="Calculator" src="http://lh5.ggpht.com/_hUwtjPLXAAY/TJz9rZFL0gI/AAAAAAAAAB0/9nDQk_O5sok/Calculator_thumb3.png?imgmax=800" width="271" height="501"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The problem occurs if we now deactivate and reactivate the application. In the emulator provided with the developer tools you can do this by clicking the “Start” button to return to the start page, then clicking “Back” to return to your application. This will result in all values being reset to their initial values as we are not persisting any state. Remember though that the user should &lt;em&gt;believe&lt;/em&gt; that the application has been sitting patiently in the background, and expects all the values to be consistent with that.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;To solve this problem Chrysalis.ViewModelBase provides a couple of virtual methods that you can override.&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; SaveState() {...}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RestoreState(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; state) {...}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The SaveState() method is called when your application is being deactivated and can return some state to be persisted. The RestoreState(…) method is called when your application is being activated and returns the state so that you can restore the property values, and hence the UI.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Also, to enable the Chrysalis support we need to add a couple of lines to the App.xaml. Firstly an ‘xmlns’ definition at the top of the file to reference the Chrysalis.Services namespace, and the &amp;lt;csv:ChrysalisService/&amp;gt; item in the ApplicationLifettimeObjects section. Appart from those changes (shown in the code below) ,the rest of the App.xaml file can be left as is.&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &amp;lt;Application &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     xmlns:csv=&lt;span style="color: #006080"&gt;"clr-namespace:Chrysalis.Services;assembly=Chrysalis"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &amp;lt;Application.ApplicationLifetimeObjects&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         ...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         &amp;lt;csv:ChrysalisService/&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &amp;lt;/Application.ApplicationLifetimeObjects&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; &amp;lt;/Application&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;For our calculator sample we do this with a class ‘CalculatorViewModelState’. &lt;strong&gt;Note:&lt;/strong&gt; This class must be declared with public scope. Since this will be serialized transparently by the phone for the duration of deactivation, we need it to be public otherwise we will receive a SecurityException when the phone tries to deserialize it.&lt;/p&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// *** Overriden Base Methods ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; SaveState()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CalculatorViewModelState()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         NumberX = numberX,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         NumberY = numberY&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     };&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RestoreState(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; state)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     CalculatorViewModelState vmState = (CalculatorViewModelState)state;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (vmState != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         NumberX = vmState.NumberX;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         NumberY = vmState.NumberY;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt; &lt;span style="color: #008000"&gt;// *** Sub-classes ***&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CalculatorViewModelState&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; NumberX { get; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; NumberY { get; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;We simply set the properties and return the state within the SaveState() method, and restore the values in the RestoreState(…) method. If you now try to tombstone the application, the state will be persisted on exit, and on returning the UI will look and perform identically to how it did prior to deactivation.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Success!&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Navigation and Storing State&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;You may notice that in the sample application we have a button that takes us to a second page of the application – CalculatorInformationPage.xaml. We should also be able to restore any application state if we navigate to this page, tombstone, return to the application, and navigate back to the calculator page.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;No need to worry though, since the Chrysalis framework ensures that this occurs transparently without having to write any further code. This works by calling SaveState()/RestoreTo(..) when a user navigates away from and back to the page, and handling the persistence of the state as required.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;As you will have seen, the &lt;a href="http://chrysalis.codeplex.com/"&gt;Chrysalis&lt;/a&gt; framework allows Silverlight developers using the MVVM pattern to simplify the persistence of state during tombstoning on their applications. By simply overriding two methods, the ViewModel itself can specify what state to persist, and the framework handles all the plumbing required to store and retrieve this.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In my next posts I will be discussing how this all works under the covers and when you should be returning state vs when you should be using isolated storage. After that, I will be releasing and describing the next feature currently being added to Chrysalis related to choosers.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;Update 17/10/2010: With the latest version RestoreState(…) should check for a null state &amp;amp; MainViewModel is refactored to CalculatorViewModel.&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-2582241002398696289?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/b4MhBQd9SVY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/2582241002398696289/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=2582241002398696289" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/2582241002398696289?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/2582241002398696289?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/b4MhBQd9SVY/chrysalis-tombstoning-support-part-i.html" title="Chrysalis – Tombstoning support (Part I - Introduction)" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_hUwtjPLXAAY/TJz9rZFL0gI/AAAAAAAAAB0/9nDQk_O5sok/s72-c/Calculator_thumb3.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2010/09/chrysalis-tombstoning-support-part-i.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEFQX0_cSp7ImA9Wx5WE0k.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-2669020977196132472</id><published>2010-09-24T16:53:00.001+01:00</published><updated>2010-09-24T16:53:30.349+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-24T16:53:30.349+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrysalis" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone 7" /><title>Introducing Chrysalis</title><content type="html">&lt;p&gt;In this post I am going to introduce the new Chrysalis framework available now from CodePlex at &lt;a href="http://chrysalis.codeplex.com"&gt;http://chrysalis.codeplex.com&lt;/a&gt;. Chrysalis is in an open source framework designed to simplify the development of Silverlight based Windows Phone 7 applications. Whilst it is primarily focused on Model-View-ViewModel (MVVM) related presentation patterns, it can be applied to other designs.&lt;/p&gt; &lt;p&gt;Many times it has been commented that if you are a Silverlight developer (and to some extent a WPF developer), then you now have the skills to write Windows Phone 7 applications. And this is almost true – with the introduction of Windows Phone 7 you can now write Silverlight applications that run on the phone as native apps (with XNA the other option for more graphically rich apps). But at the same time there are a number of new concepts that you will need to consider to write high quality software that runs within the constraints of a mobile device.&lt;/p&gt; &lt;h2&gt;Tombstoning&lt;/h2&gt; &lt;p&gt;The first consideration that everyone who works with Windows Phone 7 (both in Silverlight and XNA) should be aware of is the interestingly named “tombstoning”. The MSDN documentation has an excellent section on the “&lt;a href="http://msdn.microsoft.com/en-us/library/ff817008(v=VS.92).aspx"&gt;Execution Model Overview for Windows Phone&lt;/a&gt;” so I will not go into this in detail. In summary, you have to be aware that your application may be exited automatically at any point during its execution (for example when a phone call comes in) – not pushed to the background, but killed outright. At some later point you application may be reactivated, and it is you job as a developer to ensure that all application state is restored. The end user should &lt;em&gt;believe&lt;/em&gt; that the app was sat there in the background all the time, even though you know that it was killed and restarted.&lt;/p&gt; &lt;p&gt;The Windows Phone 7 framework will warn you that you application is being deactivated with the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.deactivated(v=VS.92).aspx"&gt;PhoneApplicationService.Deactivated&lt;/a&gt; event. This is your opportunity to save any state required, either to one of a couple of state bags, or to isolated storage. When the application is restarted then you will receive the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.activated(v=VS.92).aspx"&gt;PhoneApplicationService.Activated&lt;/a&gt; event, and you can restore the UI to its former state.&lt;/p&gt; &lt;p&gt;In reality there is a lot to think about. Firstly you have to ensure that if you are using MVVM then your ViewModels receive the activation and deactivation events. This is complicated by the fact that the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.phoneapplicationservice.activated(v=VS.92).aspx"&gt;PhoneApplicationService.Activated&lt;/a&gt; event is often fired before your ViewModel is even created. In addition there is a lot of control state that may need to be maintained – currently focused control, position of scroll bars, etc.&lt;/p&gt; &lt;p&gt;Chrysalis aims to greatly simplify this process.&lt;/p&gt; &lt;h2&gt;Choosers&lt;/h2&gt; &lt;p&gt;In Windows Phone 7 there are a number of points at which you may need to interact with the built in phone UI, for example to take a photo with the camera, or to retrieve contact information. This is done using “Choosers” (&lt;a href="http://msdn.microsoft.com/en-us/library/ff769542(VS.92).aspx"&gt;MSDN article&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;When you show a chooser we once again experience tombstoning. For the duration of the user interacting with the phone UI, our application is exited, to be restarted later when the interaction has completed. Not only do we now need to restore any state within the application, we must remember that we were calling into a chooser and what we were intending to do with the result – for example if we have multiple sets of contact information on the screen, which were we updating?&lt;/p&gt; &lt;p&gt;Chrysalis aims to allow you to specify a callback within your ViewModel that will receive the result from the chooser. Combined with the tombstoning support, your application should be barely aware that the application was killed and restarted. Instead the chooser will look like any other method call and callback.&lt;/p&gt; &lt;h2&gt;Access to Hardware&lt;/h2&gt; &lt;p&gt;Although the programming model for Windows Phone 7 is entirely managed code, there are two “flavours” of application – Silverlight and XNA. In several cases features exist within XNA, but not within Silverlight. Whilst these can be accessed by simply adding the XNA assembly references, the APIs sometimes require a different mindset.&lt;/p&gt; &lt;p&gt;Chrysalis aims to provide wrappers where required to make connecting to the hardware available through the XNA framework as simple as using any of the native Silverlight controls.&lt;/p&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;To conclude, the Chrysalis framework is now available at &lt;a href="http://chrysalis.codeplex.com"&gt;http://chrysalis.codeplex.com&lt;/a&gt;. While this is only a first release I encourage you to take a look at the basis provided and keep an eye on this blog as I will describe the usage and implementation of new features as they are introduced.&lt;/p&gt; &lt;p&gt;And please provide feedback on existing or new features, either through this blog, or on CodePlex.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-2669020977196132472?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/Bn5N4HH3JSo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/2669020977196132472/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=2669020977196132472" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/2669020977196132472?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/2669020977196132472?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/Bn5N4HH3JSo/introducing-chrysalis.html" title="Introducing Chrysalis" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2010/09/introducing-chrysalis.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAAQHc8eSp7ImA9WBFVFks.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-5977760543524623233</id><published>2007-04-15T21:16:00.000+01:00</published><updated>2007-04-15T21:25:41.971+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-04-15T21:25:41.971+01:00</app:edited><title>How small can you go? - Part III</title><content type="html">&lt;p&gt;In part one of this series of posts &lt;a href="http://andyonwpf.blogspot.com/2007/01/how-small-can-you-go.html"&gt;("How small can you go?" 22 Jan 2007)&lt;/a&gt; I described how you could design a Windows Presentation Foundation (WPF) control that altered the visibility of specific areas of a UI when then containing window was resized. Compare this to the behaviour of the Office 2007 ribbon, which will hide itself to show more of the edited document when the window is below a certain size. In part II &lt;a href="http://andyonwpf.blogspot.com/2007/02/how-small-can-you-go-part-ii.html"&gt;("How small can you go? - Part II" 15 Feb 2007)&lt;/a&gt; I detailed an alternative approach that allowed a trigger to be used when any bindable property (e.g. the width of a window) was below a certain size. In this post I will complete the implementation.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;To summarise part II, we implemented an &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx" target="_blank"&gt;IValueConverter&lt;/a&gt; that would return a boolean value indicating whether a specified binding was less than a certain value. This could be used as follows,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="wlWriterEditableSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:ad2c3872-d361-49bd-b1fa-e781332f20fd" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;pre style="BACKGROUND-COLOR: white; WORD-WRAP: break-word"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;... .Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;cvt:LessThanConverter &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;x:Key&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="LessThanConverter"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;... .Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="True"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={StaticResource lessThanConverter}, ConverterParameter=200}"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;While this allowed defining a trigger for when the width was below a specific threshhold, we would have to define the trigger again for the height of the window. What we really need is some way to combine two bindings with a 'logical OR' operation.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Introducing the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.data.imultivalueconverter.aspx" target="_blank"&gt;IMultiValueConverter&lt;/a&gt;...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;An &lt;strong&gt;IMultiValueConverter&lt;/strong&gt; is similar in principle to an &lt;strong&gt;IValueConverter&lt;/strong&gt;, whereas the latter allows the conversion of a single value into another form (in our case, a &lt;strong&gt;double&lt;/strong&gt; into a &lt;strong&gt;bool&lt;/strong&gt; indicating whether the value is below a threshold), the former will take several values, and combine them into a single output value that is then used as a trigger. We therefore need an &lt;strong&gt;IMultiValueConverter&lt;/strong&gt; that will take a number of booleans and output a single boolean that represents a 'logical OR' of all the input values. We can then use the following XAML,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="wlWriterEditableSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:c66344ea-26d9-4e3f-9b96-4305ae596b91" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;pre style="BACKGROUND-COLOR: white; WORD-WRAP: break-word"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;... .Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;cvt:LessThanConverter &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;x:Key&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="lessThanConverter"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;cvt:MultiValueOrConverter &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;x:Key&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="multiValueOrConverter"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;... .Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="True"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;.Binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;MultiBinding &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Converter&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{StaticResource multiValueOrConverter}"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Binding &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;RelativeSource&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{RelativeSource Self}"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Path&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="ActualWidth"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Converter&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{StaticResource lessThanConverter}"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; ConverterParameter&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="200"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Binding &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;RelativeSource&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{RelativeSource Self}"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Path&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="ActualHeight"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Converter&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{StaticResource lessThanConverter}"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; ConverterParameter&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="200"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;MultiBinding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger.Binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This snippet declares two objects, our &lt;strong&gt;LessThanConverter&lt;/strong&gt; from before, and a new &lt;strong&gt;MultiValueOrConverter&lt;/strong&gt;. Following this we have a &lt;strong&gt;DataTrigger&lt;/strong&gt; who's binding is a &lt;strong&gt;MultiBinding&lt;/strong&gt; that takes two bindings that will return true if the width or height is less than 200. By default the &lt;strong&gt;MultiBinding&lt;/strong&gt; will only trigger if all the child bindings are true (a 'logical AND'). We change this behaviour to a 'logical OR' by specifying our multi-value converter. The trigger will now fire if either the element width OR height are less than 200.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The actual code for the multi-value converter is similar in principle to that of a single-value converter. We take an array of input values that we will assume are all boolean values. We then perform a foreach loop over them and if any are true, we return true, otherwise false. Therefore the resulting code is,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="wlWriterEditableSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:207cc07e-ea56-4aea-a150-ec7f3085f55b" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;pre style="OVERFLOW: auto; BACKGROUND-COLOR: white"&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System.Collections.Generic;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System.Text;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System.Windows.Data;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System.Globalization;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color:#000000;"&gt; SizingApplication2&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; MultiValueOrConverter : IMultiValueConverter&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; Convert(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] values, Type targetType, &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; parameter, CultureInfo culture)&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt; value &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;in&lt;/span&gt;&lt;span style="color:#000000;"&gt; values)&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (value &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;&lt;span style="color:#000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;&lt;span style="color:#000000;"&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] ConvertBack(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; value, Type[] targetTypes, &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; parameter, CultureInfo culture)&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; NotSupportedException();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If we combine this with the XAML snippet above and include a suitable setter to hide the desired parts of the UI, we now have all the behaviour we require. Advantages of this approach include not requiring any extra elements, and being able to adapt the value converters to any situation where the UI changes based upon a certain value (for example, to display a warning message when a slider is moved above a certain value, or even change its colour as a warning).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The full code for this post and an example usage is available &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=301048"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-5977760543524623233?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/zuKsofmn8cE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/5977760543524623233/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=5977760543524623233" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/5977760543524623233?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/5977760543524623233?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/zuKsofmn8cE/how-small-can-you-go-part-iii.html" title="How small can you go? - Part III" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2007/04/how-small-can-you-go-part-iii.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkADSH09fyp7ImA9WB5WF0k.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-3444214338172089415</id><published>2007-03-04T15:35:00.001Z</published><updated>2007-07-29T22:32:59.367+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-07-29T22:32:59.367+01:00</app:edited><title>It's all in the Blend</title><content type="html">Recently I've been experimenting with the new software tool Expression Blend. For those of you who do not know, &lt;a title="Expression Blend" href="http://www.microsoft.com/products/expression/en/expression-blend/default.mspx"&gt;Expression Blend&lt;/a&gt; is Microsoft's design tool for XAML and WPF applications and is available as I write in Beta 2 form. It provides a visual design workspace where you can lay out all the elements that make up a UI, and adjust their properties as required.&lt;br /&gt;&lt;div&gt;&lt;p&gt;I have been making extensive use of it to style all the elements in my ribbon UI framework that I am currently developing. For someone who has previously edited the XAML directly it provides a much quicker environment for laying out the UI, with instant feedback on all changes. It also simplifies the introduction of triggers (changes on IsMouseOver, IsPressed, etc.) and animation. As an example, shown below is the application menu button for the ribbon UI. Of course since this is WPF this is all vector based, and smoothly scales up (NB: This screen grab is from an actual live UI - rollover animations, opens a menu when clicked, etc...).&lt;br /&gt;&lt;/p&gt;&lt;img id="BLOGGER_PHOTO_ID_5038094321961625122" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_hUwtjPLXAAY/ReroF8VvZiI/AAAAAAAAAAc/9UIaj3ra-Dk/s400/RibbonAppButton.png" border="0" /&gt;&lt;br /&gt;&lt;p&gt;In its current incarnation (beta 2) there are some issues I have had. First of all I have been unable currently to get the whole of my ribbon UI in the designer. To be fair, I haven't really tried fixing this, and it is a large composition of custom controls in a WPF rendered chrome window. It also takes a bit of learning to get used to the way it places elements by default. Of course I never read the help when I started using it which could of helped, and once you understand the basic ideas it is very easy to build up the control structure desired.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;My favorite features apart from the ease at which the UI can be styled... One item I'll definitely add here is the gradient eyedropper tool. This is similar to the standard eyedropper, which can pick up individual pixel colours from the screen. However, when the gradient eyedropper tool is dragged across a region of the screen it will automatically pick up entire gradient fills. Great for designing smooth user interfaces. Also I like the simplicity by which you can apply property changes and animation upon events.&lt;/p&gt;&lt;p&gt;Let me know below if anybody else has any experiences of Expression Blend...&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update: After a request for the XAML code I have attached the basic code below (copy and paste into XamlPad to see it). The actual Expression Blend generated XAML is significantly more complex (and much less readable!), and includes all the roll-over behaviour etc.. This is the main reason I chose a designer over hand crafting the XAML. Hopefully the attached code will give you an idea how to approach such designs.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="wlWriterEditableSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:4a1b8ff5-5943-46b0-9e30-4806f0b861f7" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre style="overflow: auto; background-color: white word-wrap: none"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Page &lt;/span&gt;&lt;span style="color: #ff0000"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; xmlns:sys&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="clr-namespace:System;assembly=mscorlib"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; xmlns:x&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Page&lt;/span&gt;&lt;span style="color: #ff0000"&gt;.Resources&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Style &lt;/span&gt;&lt;span style="color: #ff0000"&gt;TargetType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{x:Type Button}"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; x:Key&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="RibbonApplicationMenuButton"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Property&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Width"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="37"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Property&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Height"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="37"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Property&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="HorizontalContentAlignment"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Center"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Property&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="VerticalContentAlignment"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Center"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Property&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Template"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter&lt;/span&gt;&lt;span style="color: #ff0000"&gt;.Value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ControlTemplate &lt;/span&gt;&lt;span style="color: #ff0000"&gt;TargetType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{x:Type Button}"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;              &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Border &lt;/span&gt;&lt;span style="color: #ff0000"&gt;BorderThickness&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0,0,0,0"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CornerRadius&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="100000,100000,100000,100000"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Opacity&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Margin&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0,0,-1,-1"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; x:Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="ShadowBorder"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Background&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#39000000"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Border &lt;/span&gt;&lt;span style="color: #ff0000"&gt;x:Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="OuterBorder"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; BorderBrush&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FF6E7D95"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; BorderThickness&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1,1,1,1"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CornerRadius&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="100000,100000,100000,100000"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                  &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Border &lt;/span&gt;&lt;span style="color: #ff0000"&gt;ClipToBounds&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="False"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; x:Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="InnerBorder"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Width&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Height&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; BorderBrush&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FFDDE2EC"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; BorderThickness&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1,1,1,1"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CornerRadius&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="10000,10000,10000,10000"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Border&lt;/span&gt;&lt;span style="color: #ff0000"&gt;.Background&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;LinearGradientBrush &lt;/span&gt;&lt;span style="color: #ff0000"&gt;EndPoint&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.505,0.489"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; StartPoint&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.512,-0.004"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;GradientStop &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Color&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FFF3F5F8"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Offset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;GradientStop &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Color&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FFC0CADB"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Offset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;LinearGradientBrush&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Border.Background&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Width&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Height&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Path &lt;/span&gt;&lt;span style="color: #ff0000"&gt;RenderTransformOrigin&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.499999990968993,0.0833333333333333"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Stretch&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Fill"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Margin&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0,15,0,0"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; x:Name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="path"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Width&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Data&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="F1 M16.5,15.5 C22.163836,15.5 27.559435,15.738094 32.466614,16.168823 L32.5,16.5 C32.5,25.336555 25.336555,32.5 16.5,32.5 7.663444,32.5 0.5,25.336555 0.5000006,16.5 L0.53338605,16.168823 C5.4405661,15.738094 10.836165,15.5 16.5,15.5 z"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Path&lt;/span&gt;&lt;span style="color: #ff0000"&gt;.Fill&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                          &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;RadialGradientBrush &lt;/span&gt;&lt;span style="color: #ff0000"&gt;MappingMode&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="RelativeToBoundingBox"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; GradientOrigin&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5,0.5"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;RadialGradientBrush&lt;/span&gt;&lt;span style="color: #ff0000"&gt;.RelativeTransform&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                              &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TransformGroup&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                                &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ScaleTransform &lt;/span&gt;&lt;span style="color: #ff0000"&gt;CenterX&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CenterY&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; ScaleX&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1.077"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; ScaleY&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1.748"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                                &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;SkewTransform &lt;/span&gt;&lt;span style="color: #ff0000"&gt;AngleX&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; AngleY&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CenterX&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CenterY&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                                &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;RotateTransform &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Angle&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CenterX&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; CenterY&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                                &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TranslateTransform &lt;/span&gt;&lt;span style="color: #ff0000"&gt;X&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="-0.002"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Y&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="-0.025"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                              &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;TransformGroup&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;RadialGradientBrush.RelativeTransform&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;GradientStop &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Color&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FFFFFFFF"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Offset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.375"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;GradientStop &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Color&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FF93A5C2"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Offset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;GradientStop &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Color&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FFF2F4F7"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Offset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.529"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                          &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;RadialGradientBrush&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Path.Fill&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Path&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ContentPresenter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Center"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Margin&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0,0,0,0"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; VerticalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Center"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Width&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt;&lt;span style="color: #ff0000"&gt; Height&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                  &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Border&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Border&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;              &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ControlTemplate&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Setter&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Style&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Page.Resources&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Button &lt;/span&gt;&lt;span style="color: #ff0000"&gt;Style&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{StaticResource RibbonApplicationMenuButton}"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Page&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-3444214338172089415?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/sfNsklRlJ00" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/3444214338172089415/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=3444214338172089415" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/3444214338172089415?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/3444214338172089415?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/sfNsklRlJ00/it-all-in-blend.html" title="It&amp;#39;s all in the Blend" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_hUwtjPLXAAY/ReroF8VvZiI/AAAAAAAAAAc/9UIaj3ra-Dk/s72-c/RibbonAppButton.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2007/03/it-all-in-blend.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEECQX48cSp7ImA9WBFXE04.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-221210824311255758</id><published>2007-02-15T21:40:00.001Z</published><updated>2007-03-19T19:31:00.079Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-19T19:31:00.079Z</app:edited><title>How small can you go? - Part II</title><content type="html">&lt;p&gt;&lt;em&gt;Updated: 19 March 2007 to resolve some errors&lt;/em&gt;&lt;/p&gt;&lt;p&gt;In my last post (&lt;a title="How small can you go?" href="http://andyonwpf.blogspot.com/2007/01/how-small-can-you-go.html"&gt;"How small can you go?" 22 Jan 2007&lt;/a&gt;) I presented a custom control that allowed you to determine if the control was below a specific size, and to alter its visual appearance based upon this. There are many cases however where altering appearance based upon size is important (for example, to make the thumb grips on scrollbars disappear when they become too small), and I felt a more generic method of performing this calculation was required.&lt;/p&gt;&lt;p&gt;Ideally this method would not require a special base class as described in my previous post. It should also be as general as possible, allowing bindings to any available dependency properties.&lt;/p&gt;&lt;p&gt;So let us consider how we currently implement triggers,&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:264e45bf-50af-4ecb-981f-3a71c16f59b6" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;pre  style="color:white;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Trigger &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="IsMouseOver"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="True"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Trigger&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Trigger &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="Width"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="150"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Trigger&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The first of these examples makes perfect sense. The &lt;strong&gt;IsMouseOver&lt;/strong&gt; property is either true or false. We apply the default style when it is false, and apply any changes specified within the Trigger when it is true. However, the &lt;strong&gt;Width&lt;/strong&gt; property does not have a small number of distinct values. Whilst the above trigger will apply if the width equals 150, it will not if it is 149,148,147,etc. or 151,152,153,etc. If only we had a less-than trigger...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now let me introduce the &lt;strong&gt;&lt;a title="IValueConverter interface" href="http://msdn2.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx" target="_blank"&gt;IValueConverter&lt;/a&gt;&lt;/strong&gt; interface. This according to the MSDN documentation "Provides a way to apply custom logic to a binding." Basically it allows you to include some logic that alters the value of the property before the trigger performs its comparison.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For example,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:edf24687-180e-43c6-b2cb-a4f252f33ae7" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;pre  style="color:white;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="True"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={StaticResource addTenConverter}, ConverterParameter=150}"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Here we specify a custom converter, whose logic simply adds ten to a value. Therefore if the &lt;strong&gt;Width&lt;/strong&gt; of our element is 140, the binding will first call our converter, which will of course return 150. Since this matches the &lt;strong&gt;Value&lt;/strong&gt; attribute, the trigger will be applied. The converter just sits between the &lt;strong&gt;Property&lt;/strong&gt; and the comparison to &lt;strong&gt;Value&lt;/strong&gt; and provides some conversion.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So how does this help us? Well, there is one more attribute we need to introduce. The &lt;strong&gt;ConverterParameter&lt;/strong&gt; attribute allows us to supply an additional parameter to our converter when it does its stuff. Now we can envisage,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:90eed4c9-a5e1-49f0-b8bc-e7582a53c119" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;pre  style="color:white;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;... .Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;cvt:LessThanConverter &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;x:Key&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="LessThanConverter"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;... .Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Value&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="True"&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={StaticResource lessThanConverter}, ConverterParameter=200}"&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTrigger&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Note that we create an instance of the converter as a static resource. The actual code behind the converter is relatively straightforward. All we do is take the supplied value, compare it to the supplied parameter, and return true if the value is less otherwise return false. In fact this is slightly more complex. Whilst a &lt;strong&gt;ValueConversionAttribute&lt;/strong&gt; may be applied to the converter class specifying the type for the parameter, when written in XAML as shown above this is ignored and a string is supplied anyway. Therefore the resulting code is,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:f535e9ad-7fc8-4868-a570-657c8fc3af33" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;pre  style="color:white;"&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System.Windows.Data;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System.Globalization;&lt;br /&gt;&lt;br /&gt;[ValueConversion(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt;), &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt;), ParameterType &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt;))]&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; LessThanConverter : IValueConverter&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; Convert(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; value, Type targetType, &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; parameter, CultureInfo culture)&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt; doubleValue &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt;)value;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt; doubleParameter;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (parameter &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;is&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt;)&lt;br /&gt;doubleParameter &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt;)parameter;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (parameter &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;is&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;)&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#000000;"&gt;!&lt;/span&gt;&lt;span style="color:#000000;"&gt;Double.TryParse((&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;)parameter, &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;out&lt;/span&gt;&lt;span style="color:#000000;"&gt; doubleParameter))&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FormatException(&lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;The parameter for this LessThanConverter could not be converted to a System.Double&lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; ArgumentException(&lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;The parameter for this LessThanConverer is of an unsupported type&lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;parameter&lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;{0} &amp;lt; {1}&lt;/span&gt;&lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#000000;"&gt;, doubleValue, doubleParameter);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; doubleValue &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; doubleParameter;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; ConvertBack(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; value, Type targetType, &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; parameter, CultureInfo culture)&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; NotSupportedException();&lt;br /&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So now we can trigger when any dependency property that is defined as a &lt;strong&gt;double&lt;/strong&gt; is less than a specified value. The original problem from &lt;a title="How small can you go?" href="http://andyonwpf.blogspot.com/2007/01/how-small-can-you-go.html"&gt;part 1&lt;/a&gt; however involved changing the appearance of a window when either of the &lt;strong&gt;Width&lt;/strong&gt; or &lt;strong&gt;Height&lt;/strong&gt; properties were below a certain threshold. We can specify two separate triggers, but this requires duplication of all the setters within them. What we really need is some way to apply a 'logical OR' operation to two or more triggers. Next time... The &lt;strong&gt;&lt;a title="IMultiValueConverter interface" href="http://msdn2.microsoft.com/en-us/library/system.windows.data.imultivalueconverter.aspx" target="_blank"&gt;IMultiValueConverter&lt;/a&gt;&lt;/strong&gt; interface.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:70fc90ca-eb27-47d8-89a9-1a9268790e28" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;, &lt;a href="http://technorati.com/tags/IValueConverter" rel="tag"&gt;IValueConverter&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Triggers" rel="tag"&gt;Triggers&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-221210824311255758?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/6MKZmQd6Ae0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/221210824311255758/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=221210824311255758" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/221210824311255758?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/221210824311255758?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/6MKZmQd6Ae0/how-small-can-you-go-part-ii.html" title="How small can you go? - Part II" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2007/02/how-small-can-you-go-part-ii.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYFR3w9fip7ImA9WBBaFU0.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-7567457923895559728</id><published>2007-01-22T22:51:00.001Z</published><updated>2007-01-22T23:05:16.266Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-01-22T23:05:16.266Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><title>How small can you go?</title><content type="html">&lt;p&gt;In the past, creation of fully sizable user interfaces was a tedious job involving writing complex and bugging "pixel-counting" code to layout controls upon a window resize event. Windows Presentation Foundation (WPF) has made the job of creating such UIs much simpler by including a straightforward layout engine within the framework. But sometimes there is a limit to how small you can resize the UI before it becomes unusable.&lt;/p&gt; &lt;p&gt;One solution is&amp;nbsp;the approach&amp;nbsp;used by the 2007 Microsoft Office System, whereby the ribbon control will disappear from view if the window is resized too small, allowing the document content to fill the space. In this post I'll describe how to implement this effect in WPF applications. I will discuss how to implement dependency properties in your custom controls and&amp;nbsp;the strange world of read-only dependency properties.&lt;/p&gt; &lt;p&gt;As a very simple example we will start with a custom control that is styled with a content area, and&amp;nbsp;a toolbar that&amp;nbsp;when sized below a certain size will be hidden&amp;nbsp;(in my WPF ribbon control this is actually a styled Window, however for simplicity here I will use a control).&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:a0d55110-e138-4bb9-a97e-e6eb327db5de" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000FF; "&gt;public&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;class&lt;/span&gt;&lt;span style="color: #000000; "&gt; SizingControl : Control&lt;br /&gt;{&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now we will add a "dependency property", a special type of property used for WPF applications that allows additional functionality such as data binding, animations and styling. We define these with the &lt;strong&gt;DependencyProperty.Register&lt;/strong&gt; static method, supplying a property name, property type and owner type. In addition, metadata may be added defining addition information such as default values. In addition we add a standard CLR property of the same name, passing the value to and from the property system with the &lt;strong&gt;DependencyObject.GetValue&lt;/strong&gt; and &lt;strong&gt;DependencyObject.SetValue&lt;/strong&gt; methods. In this case we add a dependency property to specify the size below which the control will display a different UI.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e6ca1d62-5b67-4794-8833-9b2dacf57dfb" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000FF; "&gt;public&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;static&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;readonly&lt;/span&gt;&lt;span style="color: #000000; "&gt; DependencyProperty SmallSizeProperty &lt;/span&gt;&lt;span style="color: #000000; "&gt;=&lt;/span&gt;&lt;span style="color: #000000; "&gt; DependencyProperty.Register(&lt;/span&gt;&lt;span style="color: #000000; "&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000; "&gt;SmallSize&lt;/span&gt;&lt;span style="color: #000000; "&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000; "&gt;, &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;typeof&lt;/span&gt;&lt;span style="color: #000000; "&gt;(Size), &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;typeof&lt;/span&gt;&lt;span style="color: #000000; "&gt;(SizingControl), &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;new&lt;/span&gt;&lt;span style="color: #000000; "&gt; UIPropertyMetadata(&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;new&lt;/span&gt;&lt;span style="color: #000000; "&gt; Size(&lt;/span&gt;&lt;span style="color: #000000; "&gt;0.0&lt;/span&gt;&lt;span style="color: #000000; "&gt;, &lt;/span&gt;&lt;span style="color: #000000; "&gt;0.0&lt;/span&gt;&lt;span style="color: #000000; "&gt;)));&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;public&lt;/span&gt;&lt;span style="color: #000000; "&gt; Size SmallSize&lt;br /&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;get&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;return&lt;/span&gt;&lt;span style="color: #000000; "&gt; (Size)GetValue(SmallSizeProperty);&lt;br /&gt;    }&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;set&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;    {&lt;br /&gt;        SetValue(SmallSizeProperty, value);&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Next we add a read-only dependency property that indicates whether the control is below the specified size. The &lt;a href="http://msdn2.microsoft.com/en-us/library//ms754044.aspx" target="_blank"&gt;Windows SDK&lt;/a&gt; warns against using read-only dependency properties in many cases, and suggests that such properties should only be used "for state determination". Think of this as properties of the form "IsXXX" (such as IsMouseOver).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;To register a read-only dependency property, we use the &lt;strong&gt;DependencyProperty.Register.ReadOnly&lt;/strong&gt; static method, which rather than a &lt;strong&gt;DependencyProperty&lt;/strong&gt;, returns a &lt;strong&gt;DependencyPropertyKey&lt;/strong&gt;. To set the value we can use this with the respective override of &lt;strong&gt;DependencyObject.SetValue&lt;/strong&gt;, however no suitable override of &lt;strong&gt;DependencyObject.GetValue&lt;/strong&gt; exists. In fact, the property system does not allow us to get a value of a dependency property that is marked as read-only. So how do we obtain this value? The answer is that we have to include a private field to contain the property value. Since by its very nature a read-only property may only be set by the owner class, we can always ensure that the value in the field is synchronized with that of the dependency property. To avoid writing code that breaks this rule, I tend to encapsulate this logic into a private property setter (note that property setters and getters with different accessibility is a feature of C# 2.0).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:83ea4022-2af4-4228-84a2-8de901094d46" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000FF; "&gt;private&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;bool&lt;/span&gt;&lt;span style="color: #000000; "&gt; isSmall;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;public&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;static&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;readonly&lt;/span&gt;&lt;span style="color: #000000; "&gt; DependencyPropertyKey IsSmallPropertyKey &lt;/span&gt;&lt;span style="color: #000000; "&gt;=&lt;/span&gt;&lt;span style="color: #000000; "&gt; DependencyProperty.RegisterReadOnly(&lt;/span&gt;&lt;span style="color: #000000; "&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000; "&gt;IsSmall&lt;/span&gt;&lt;span style="color: #000000; "&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000; "&gt;, &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;typeof&lt;/span&gt;&lt;span style="color: #000000; "&gt;(&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;bool&lt;/span&gt;&lt;span style="color: #000000; "&gt;), &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;typeof&lt;/span&gt;&lt;span style="color: #000000; "&gt;(SizingControl), &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;new&lt;/span&gt;&lt;span style="color: #000000; "&gt; UIPropertyMetadata(&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;false&lt;/span&gt;&lt;span style="color: #000000; "&gt;));&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;public&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;bool&lt;/span&gt;&lt;span style="color: #000000; "&gt; IsSmall&lt;br /&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;get&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;return&lt;/span&gt;&lt;span style="color: #000000; "&gt; isSmall;&lt;br /&gt;    }&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;private&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;set&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;if&lt;/span&gt;&lt;span style="color: #000000; "&gt; (value &lt;/span&gt;&lt;span style="color: #000000; "&gt;!=&lt;/span&gt;&lt;span style="color: #000000; "&gt; isSmall)&lt;br /&gt;        {&lt;br /&gt;            isSmall &lt;/span&gt;&lt;span style="color: #000000; "&gt;=&lt;/span&gt;&lt;span style="color: #000000; "&gt; value;&lt;br /&gt;            SetValue(IsSmallPropertyKey, value);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now all is required is to override the &lt;strong&gt;OnRenderSizeChanged&lt;/strong&gt; event of our control, and determine whether the control is small or not.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:86946144-e8fd-402a-9787-50d6e43ff581" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000FF; "&gt;private&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;void&lt;/span&gt;&lt;span style="color: #000000; "&gt; UpdateIsSmall(Size newSize)&lt;br /&gt;{&lt;br /&gt;    IsSmall &lt;/span&gt;&lt;span style="color: #000000; "&gt;=&lt;/span&gt;&lt;span style="color: #000000; "&gt; (newSize.Width &lt;/span&gt;&lt;span style="color: #000000; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000; "&gt; SmallSize.Width &lt;/span&gt;&lt;span style="color: #000000; "&gt;||&lt;/span&gt;&lt;span style="color: #000000; "&gt; newSize.Height &lt;/span&gt;&lt;span style="color: #000000; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000; "&gt; SmallSize.Height);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;protected&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;override&lt;/span&gt;&lt;span style="color: #000000; "&gt; &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;void&lt;/span&gt;&lt;span style="color: #000000; "&gt; OnRenderSizeChanged(SizeChangedInfo sizeInfo)&lt;br /&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #008000; "&gt;//&lt;/span&gt;&lt;span style="color: #008000; "&gt; Calculate whether the window size is smaller than the specified values&lt;/span&gt;&lt;span style="color: #008000; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;    UpdateIsSmall(sizeInfo.NewSize);&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #008000; "&gt;//&lt;/span&gt;&lt;span style="color: #008000; "&gt; Call the base method&lt;/span&gt;&lt;span style="color: #008000; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;base&lt;/span&gt;&lt;span style="color: #000000; "&gt;.OnRenderSizeChanged(sizeInfo);&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The XAML below shows how to use the control to hide a toolbar when the window is too small. We style the control with the desired content, and set a trigger on the &lt;strong&gt;IsSmall&lt;/strong&gt; property to show or hide the toolbar as required.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:ef527f0a-af5f-40ec-b2c2-bd131f5fd6f4" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Window &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;x:Class&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;SizingApplication.Window1&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; xmlns&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; xmlns:x&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Title&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;SizingApplication&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Height&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;300&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Width&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;300&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; xmlns:local&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;clr-namespace:SizingApplication&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Background&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;Silver&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Window&lt;/span&gt;&lt;span style="color: #FF0000; "&gt;.Resources&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Style &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;x:Key&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;MySizingRegion&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; TargetType&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;local:SizingControl&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Setter &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;Property&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;SmallSize&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Value&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;200,200&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Setter &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;Property&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;Template&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Setter&lt;/span&gt;&lt;span style="color: #FF0000; "&gt;.Value&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;ControlTemplate &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;TargetType&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;local:SizingControl&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;DockPanel&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;ToolBar &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;x:Name&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;toolBar&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; DockPanel.Dock&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;Top&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Height&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;50&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                                &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Label &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;Center&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;My ToolBar&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Label&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;ToolBar&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Border &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;Margin&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;10&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Background&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;White&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;DockPanel&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;ControlTemplate&lt;/span&gt;&lt;span style="color: #FF0000; "&gt;.Triggers&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Trigger &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;Property&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;IsSmall&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Value&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;True&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                                &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Setter &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;TargetName&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;toolBar&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Property&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;Visibility&amp;quot;&lt;/span&gt;&lt;span style="color: #FF0000; "&gt; Value&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;Collapsed&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Trigger&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;ControlTemplate.Triggers&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;ControlTemplate&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Setter.Value&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Setter&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Style&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Window.Resources&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;Grid&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000; "&gt;local:SizingControl &lt;/span&gt;&lt;span style="color: #FF0000; "&gt;Style&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;=&amp;quot;{StaticResource MySizingRegion}&amp;quot;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Grid&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000; "&gt;Window&lt;/span&gt;&lt;span style="color: #0000FF; "&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The full&amp;nbsp;code for this post is &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=274848"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-7567457923895559728?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/LHaa9rJfOVc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/7567457923895559728/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=7567457923895559728" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/7567457923895559728?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/7567457923895559728?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/LHaa9rJfOVc/how-small-can-you-go.html" title="How small can you go?" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2007/01/how-small-can-you-go.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIERH46eCp7ImA9WBBXFE0.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-4057178904646276452</id><published>2006-11-24T22:48:00.001Z</published><updated>2006-11-24T22:48:25.010Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-11-24T22:48:25.010Z</app:edited><title>Ribbon controls are legal!</title><content type="html">&lt;p&gt;Here is the news that Microsoft have launched a licensing program for those who wish to clone the Office 2007 UI (&lt;a title="Licensing the 2007 Microsoft Office User Interface" href="http://blogs.msdn.com/jensenh/archive/2006/11/21/licensing-the-2007-microsoft-office-user-interface.aspx" target="_blank"&gt;from Jensen Harris' blog&lt;/a&gt;). This is a royalty-free scheme whereby anyone wishing to use part of the Office 2007 user interface (e.g. the ribbon) can recreate it in their applications (note that this offering does not provide any code).&lt;/p&gt; &lt;p&gt;There are some restrictions applied however, in particular that the interface must adhere to the supplied UI guidelines. These are very detailed so places quite a burden on the programmer implementing the controls; however this should at least&amp;nbsp;ensure that the end user can confidently use a ribbon-enabled application with the existing knowledge of how the UI should work. Microsoft have done a great job in explaining the requirements - for example they describe exactly how the ribbon should resize - so I'm looking forward to having an accurate check-list of requirements to implement in my controls.&lt;/p&gt; &lt;p&gt;For more information check out the links in &lt;a title="Licensing the 2007 Microsoft Office User Interface" href="http://blogs.msdn.com/jensenh/archive/2006/11/21/licensing-the-2007-microsoft-office-user-interface.aspx" target="_blank"&gt;Jensen' blog post&lt;/a&gt;...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-4057178904646276452?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/v1slfl1Hgb4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/4057178904646276452/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=4057178904646276452" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/4057178904646276452?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/4057178904646276452?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/v1slfl1Hgb4/ribbon-controls-are-legal.html" title="Ribbon controls are legal!" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2006/11/ribbon-controls-are-legal.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIEQXY9eSp7ImA9WBFWEk0.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-1753111869549193130</id><published>2006-11-05T16:44:00.001Z</published><updated>2007-03-29T22:08:20.861+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-29T22:08:20.861+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><category scheme="http://www.blogger.com/atom/ns#" term="dropshadows" /><title>From the shadows</title><content type="html">&lt;p&gt;When styling controls that have a Popup element (e.g. menus, combo boxes, etc.) a common visual cue is a drop-shadow below the pop-up. WPF contains a DropShadowBitmapEffect that will do this all for us, hence,&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&amp;lt;Border ...&amp;gt;&lt;br /&gt;&amp;lt;Border.BitmapEffect&amp;gt;&lt;br /&gt;&amp;lt;DropShadowBitmapEffect Softness=".5" ShadowDepth="5" Color="Black"/&amp;gt;&lt;br /&gt;&amp;lt;/Border.BitmapEffect&amp;gt;&lt;br /&gt;&amp;lt;/Border&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-family:Georgia;"&gt;The result is shown on the left below. However, the DropShadowBitmapEffect is a bit overkill for our needs. It is designed to add drop-shadows to arbitrary shapes (for example the text below) whereas a pop-up is generally rectangular.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger2/5073/1078954382684306/320/DropShadowBitmapEffect.png" border="0" /&gt;&lt;br /&gt;&lt;p&gt;If you inspect the default WPF styles you will find that a drop shadow is applied via a Decorator called Microsoft.Windows.Themes.SystemDropShadowChrome. This however is hidden away in PresentationFramework.Luna.dll and designed for use by the default styles.&lt;/p&gt;&lt;p&gt;For my controls I have developed my own decorator to do a similar job. Firstly I have decided to make some assumptions to improve performance - namely that the drop-shadow colour is always black, and that it is always to the bottom-right. All that is required then is to implement a custom "Decorator". Decorators are controls that add some additional rendering to a single element (of course that element may be a Panel that contains several other elements). We can then draw a drop-shadow in the OnRender method consisting of a set of linear and radial gradients to mimic the shadow.&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Windows.Controls;&lt;br /&gt;using System.Windows.Media;&lt;br /&gt;using System.Windows&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;class ShadowChrome : Decorator&lt;br /&gt;{&lt;br /&gt;// *** Fields *** &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;private static SolidColorBrush backgroundBrush;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;private static LinearGradientBrush rightBrush;&lt;br /&gt;private static LinearGradientBrush bottomBrush;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;private static RadialGradientBrush bottomRightBrush;&lt;br /&gt;private static RadialGradientBrush topRightBrush;&lt;br /&gt;private static RadialGradientBrush bottomLeftBrush;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// *** Constructors ***&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static ShadowChrome()&lt;br /&gt;{&lt;br /&gt;MarginProperty.OverrideMetadata(typeof(ShadowChrome), new FrameworkPropertyMetadata(new Thickness(0, 0, 4, 4)));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CreateBrushes();&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// *** Overriden base methods ***&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;protected override void OnRender(DrawingContext drawingContext)&lt;br /&gt;{&lt;br /&gt;// Calculate the size of the shadow&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;double shadowSize = Math.Min(Margin.Right, Margin.Bottom);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// If there is no shadow, or it is bigger than the size of the child, then just return&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;if (shadowSize &amp;lt;= 0 &amp;#124;&amp;#124; this.ActualWidth &amp;lt; shadowSize*2 &amp;#124;&amp;#124; this.ActualHeight &amp;lt; shadowSize * 2)&lt;br /&gt;return;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// Draw the background (this may show through rounded corners of the child object)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;Rect backgroundRect = new Rect(shadowSize, shadowSize, this.ActualWidth - shadowSize, this.ActualHeight - shadowSize);&lt;br /&gt;drawingContext.DrawRectangle(backgroundBrush, null, backgroundRect);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// Now draw the shadow gradients&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;Rect topRightRect = new Rect(this.ActualWidth, shadowSize, shadowSize, shadowSize);&lt;br /&gt;drawingContext.DrawRectangle(topRightBrush, null, topRightRect);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;Rect rightRect = new Rect(this.ActualWidth, shadowSize * 2, shadowSize, this.ActualHeight - shadowSize * 2);&lt;br /&gt;drawingContext.DrawRectangle(rightBrush, null, rightRect);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;Rect bottomRightRect = new Rect(this.ActualWidth, this.ActualHeight, shadowSize, shadowSize);&lt;br /&gt;drawingContext.DrawRectangle(bottomRightBrush, null, bottomRightRect);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;Rect bottomRect = new Rect(shadowSize * 2, this.ActualHeight, this.ActualWidth - shadowSize * 2, shadowSize);&lt;br /&gt;drawingContext.DrawRectangle(bottomBrush, null, bottomRect);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;Rect bottomLeftRect = new Rect(shadowSize, this.ActualHeight, shadowSize, shadowSize);&lt;br /&gt;drawingContext.DrawRectangle(bottomLeftBrush, null, bottomLeftRect);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// *** Private static methods ***&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;private static void CreateBrushes()&lt;br /&gt;{&lt;br /&gt;// Get the colors for the shadow&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;Color shadowColor = Color.FromArgb(128, 0, 0, 0);&lt;br /&gt;Color transparentColor = Color.FromArgb(16, 0, 0, 0);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// Create a GradientStopCollection from these&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;GradientStopCollection gradient = new GradientStopCollection(2);&lt;br /&gt;gradient.Add(new GradientStop(shadowColor, 0.5));&lt;br /&gt;gradient.Add(new GradientStop(transparentColor, 1.0));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// Create the background brush&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;backgroundBrush = new SolidColorBrush(shadowColor);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// Create the LinearGradientBrushes&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;rightBrush = new LinearGradientBrush(gradient, new Point(0.0, 0.0), new Point(1.0, 0.0));&lt;br /&gt;bottomBrush = new LinearGradientBrush(gradient, new Point(0.0, 0.0), new Point(0.0, 1.0));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// Create the RadialGradientBrushes&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;bottomRightBrush = new RadialGradientBrush(gradient);&lt;br /&gt;bottomRightBrush.GradientOrigin = new Point(0.0, 0.0);&lt;br /&gt;bottomRightBrush.Center = new Point(0.0, 0.0);&lt;br /&gt;bottomRightBrush.RadiusX = 1.0;&lt;br /&gt;bottomRightBrush.RadiusY = 1.0;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;topRightBrush = new RadialGradientBrush(gradient);&lt;br /&gt;topRightBrush.GradientOrigin = new Point(0.0, 1.0);&lt;br /&gt;topRightBrush.Center = new Point(0.0, 1.0);&lt;br /&gt;topRightBrush.RadiusX = 1.0;&lt;br /&gt;topRightBrush.RadiusY = 1.0;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;bottomLeftBrush = new RadialGradientBrush(gradient);&lt;br /&gt;bottomLeftBrush.GradientOrigin = new Point(1.0, 0.0);&lt;br /&gt;bottomLeftBrush.Center = new Point(1.0, 0.0);&lt;br /&gt;bottomLeftBrush.RadiusX = 1.0;&lt;br /&gt;bottomLeftBrush.RadiusY = 1.0;&lt;br /&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This may then be used as shown in the following XAML. Note that the Margin property is used for two uses. Firstly it provides an area around the element to render the drop-shadow (this is important in a Popup since it ensures the drop-shadow is within the pop-up window), and also specifies to ShadowChrome the size to render the drop-shadow. &lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&amp;lt;ShadowChrome&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;&amp;lt;Border Margin="0,0,5,5" .../&amp;gt;&lt;br /&gt;&amp;lt;/ShadowChrome&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger2/5073/1078954382684306/320/DropDownShadow.png" border="0" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-1753111869549193130?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/7Kpr2LaOUcM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/1753111869549193130/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=1753111869549193130" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/1753111869549193130?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/1753111869549193130?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/7Kpr2LaOUcM/from-shadows.html" title="From the shadows" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>10</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2006/11/from-shadows.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcFRXc7cSp7ImA9WBBREUk.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-6569372675321374140</id><published>2006-10-29T12:06:00.001Z</published><updated>2006-10-29T17:13:34.909Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-10-29T17:13:34.909Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><category scheme="http://www.blogger.com/atom/ns#" term="Ribbon" /><category scheme="http://www.blogger.com/atom/ns#" term="DropDownButton" /><title>DropDownButtons in WPF</title><content type="html">Whilst Windows Presentation Foundation (WPF) provides good support for menus, one omission is a drop-down button. By this I mean a button, that when clicked will result in a menu dropping down from the control.&lt;br /&gt;&lt;br /&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger2/5073/1078954382684306/320/DropDownButton.png" border="0" /&gt; &lt;p&gt;&lt;/p&gt;&lt;p&gt;So I started to write my own. Easy I thought, just style a MenuItem to look like a button. Well, this doesn't work as the MenuItem control will only work if it is a child of a Menu control. I could just wrap all my DropDownButtons in Menus, but that becomes a little messy wrapping everything in extra menus. I tried a number of other approaches, none of which worked as I would like.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This was several months ago. Recently however I was informed of a couple of related blog articles at &lt;a title="Sheva's Techspace" href="http://shevaspace.spaces.live.com/blog/cns!FD9A0F1F8DD06954!453.entry" target="_blank"&gt;Sheva's Techspace&lt;/a&gt; and &lt;a title="Lester's piece on WPF" href="http://blogs.msdn.com/llobo/archive/2006/10/25/Split-Button-in-WPF.aspx" target="_blank"&gt;Lester's piece on WPF&lt;/a&gt;. In particular I liked Lester's approach. This is to use the Button's ContextMenu to apply add a context menu, and then to use code to open this on a left mouse click. A simple solution that works well. But what if I wanted to have a &lt;em&gt;real&lt;/em&gt; context-menu too?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Solution: Well, in fact ContextMenu doesn't need to be attached to a control to work. All you need to do is create a new ContextMenu object, add your MenuItems, and set IsOpen to true. So I put together the control as below.&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;public class DropDownButton : ToggleButton&lt;br /&gt;{&lt;br /&gt;// *** Dependency Properties *** &lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;public static readonly DependencyProperty DropDownProperty = DependencyProperty.Register("DropDown", typeof(ContextMenu), typeof(DropDownButton), new UIPropertyMetadata(null)); &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;// *** Constructors *** &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;public DropDownButton()&lt;br /&gt;{&lt;br /&gt;// Bind the ToogleButton.IsChecked property to the drop-down's IsOpen property &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;Binding binding = new Binding("DropDown.IsOpen");&lt;br /&gt;binding.Source = this;&lt;br /&gt;this.SetBinding(IsCheckedProperty, binding);&lt;br /&gt;} &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;// *** Properties *** &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;public ContextMenu DropDown&lt;br /&gt;{&lt;br /&gt;get&lt;br /&gt;{&lt;br /&gt;return (ContextMenu)GetValue(DropDownProperty);&lt;br /&gt;}&lt;br /&gt;set&lt;br /&gt;{&lt;br /&gt;SetValue(DropDownProperty, value);&lt;br /&gt;}&lt;br /&gt;} &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;// *** Overridden Methods *** &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;protected override void OnClick()&lt;br /&gt;{&lt;br /&gt;if (DropDown != null)&lt;br /&gt;{&lt;br /&gt;// If there is a drop-down assigned to this button, then position and display it &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;DropDown.PlacementTarget = this;&lt;br /&gt;DropDown.Placement = PlacementMode.Bottom; &lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;DropDown.IsOpen = true;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;This control derives directly from ToggleButton so we inherit the full behavior and styling of a button. We then provide a DropDown dependency property that takes a ContextMenu to show for the drop-down. In the OnClick event we simply position the menu under the control, and open it by setting IsOpen to true. Finally to tidy up, we bind the ToggleButton's IsChecked property to the drop-down menu's IsOpen property to ensure that these are synchronized.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;To use this in your own code you simply use,&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&amp;lt;ctrl:DropDownButton Content="Drop-Down"&amp;gt;&lt;br /&gt;&amp;lt;ctrl:DropDownButton.DropDown&amp;gt;&lt;br /&gt;&amp;lt;ContextMenu&amp;gt;&lt;br /&gt;&amp;lt;MenuItem Header="Item 1"/&amp;gt;&lt;br /&gt;&amp;lt;MenuItem Header="Item 2"/&amp;gt;&lt;br /&gt;&amp;lt;MenuItem Header="Item 3"/&amp;gt;&lt;br /&gt;&amp;lt;/ContextMenu&amp;gt;&lt;br /&gt;&amp;lt;/ctrl:DropDownButton.DropDown&amp;gt;&lt;br /&gt;&amp;lt;/ctrl:DropDownButton&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:d9eebd36-8fd9-41b5-8192-b7c68b472dd2" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;, &lt;a href="http://technorati.com/tags/DropDownButton" rel="tag"&gt;DropDownButton&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Ribbon" rel="tag"&gt;Ribbon&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-6569372675321374140?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/6Lh-aUkXWQs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/6569372675321374140/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=6569372675321374140" title="17 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/6569372675321374140?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/6569372675321374140?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/6Lh-aUkXWQs/dropdownbuttons-in-wpf.html" title="DropDownButtons in WPF" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>17</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2006/10/dropdownbuttons-in-wpf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04MRXs9cCp7ImA9WBBREUk.&quot;"><id>tag:blogger.com,1999:blog-8838794302949839825.post-3369796541685618569</id><published>2006-10-29T11:34:00.001Z</published><updated>2006-10-29T17:13:04.568Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-10-29T17:13:04.568Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><category scheme="http://www.blogger.com/atom/ns#" term="Ribbon" /><title>An Office 2007 style Ribbon in WPF?</title><content type="html">&lt;p&gt;For a while now I have been working on reproducing an Office 2007 Ribbon style application in Windows Presentation Foundation (WPF). This includes not just the ribbon itself, but also the full window chrome.&lt;/p&gt;&lt;p&gt;Whilst the official documentation has been in progress, blogs have been a great alternative source of information. However now I thought would be a good time to start my own blog discussing, amongst other things, how I am writing my Ribbon control.&lt;/p&gt;&lt;p&gt;Hope over the coming months you enjoy my posts and find something of interest to your own development needs. I'll focus on some of the issues that I have encountered, and will post some images of the fully working Ribbon control.&lt;/p&gt;&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:67936529-85ab-49e8-90ca-dfe51d61bf13" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Ribbon" rel="tag"&gt;Ribbon&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8838794302949839825-3369796541685618569?l=andyonwpf.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AndyOnWpf/~4/Tbl2nnq3XYw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://andyonwpf.blogspot.com/feeds/3369796541685618569/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8838794302949839825&amp;postID=3369796541685618569" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/3369796541685618569?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8838794302949839825/posts/default/3369796541685618569?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/AndyOnWpf/~3/Tbl2nnq3XYw/office-2007-style-ribbon-in-wpf.html" title="An Office 2007 style Ribbon in WPF?" /><author><name>Andrew Wilkinson</name><uri>http://www.blogger.com/profile/10117584978862298252</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://andyonwpf.blogspot.com/2006/10/office-2007-style-ribbon-in-wpf.html</feedburner:origLink></entry></feed>

