<?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" gd:etag="W/&quot;CkQASHs-fip7ImA9WxJUEk8.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943</id><updated>2009-07-10T11:05:49.556+01:00</updated><title>Neil Mosafi</title><subtitle type="html">Occasional Blogger</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>44</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/NeilMosafi" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;Dk8ASXg6eip7ImA9WxJWEUQ.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-6243573038673312521</id><published>2009-06-17T00:15:00.002+01:00</published><updated>2009-06-17T00:27:28.612+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-17T00:27:28.612+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><title>BDD Everywhere - don't underestimate your target audience</title><content type="html">&lt;p&gt;I have recently moved from doing TDD to BDD, using &lt;a href="http://ampgt.com/"&gt;Scott&lt;/a&gt;'s excellent &lt;a href="http://code.google.com/p/specunit-net/"&gt;SpecUnit.Net&lt;/a&gt; with, I have to say, some real success.&lt;/p&gt;

&lt;p&gt;BDD was the subject matter being discussed at May's London Altnet beers.  After the talk I was discussing with some people about their approach to doing BDD. What was being presented was the idea that BDD specs are useful only at the outer layers of the application and once you get more low level, you should revert to normal style TDD tests.&lt;/p&gt;

&lt;p&gt;I don't agree.  I have been writing BDD specs for every single class I write, and have recently upgraded our build system (rock on TeamCity) to make the spec reports.  Saying BDD is just for the outer layers is ignoring the fact that the users of application know a lot more about their business than you do.&lt;/p&gt;

&lt;p&gt;I'll give an example.  We are building a system for the traders to view their trades - in what is known in the financial world as a "blotter".  Being a WPF application, we build the ViewModels first and then build some sort of data access component.  So the requirement is that all the trades made today should be displayed on the blotter when the user refreshes it.  Here is a set of specs which say that&lt;/p&gt;

&lt;p&gt;&lt;em&gt;when the user refreshes the blotter and no trades have been made today&lt;br /&gt;
- should display a message saying there are no trades&lt;br /&gt;
- refresh button should be enabled&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;when the user refreshes the blotter and two trades have been made today&lt;br/&gt;
- should be two trades displayed in the blotter&lt;br/&gt;
- should display the earlier trade on the first row&lt;br/&gt;
- should display the later trade on the second row&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So now we write some tests for that, and flesh out our implementation.  During this time we create an interface ITradeProvider with a method GetTradesForToday(), and use a mocking framework to stub out the calls to that method using our favourite mocking framework.&lt;/p&gt;

&lt;p&gt;Our user/customer/business analyst would definitely find those specs useful, and may even give some feedback or changes, which is great.  But what about the TradeProvider implementation? Is that worth doing it for?  Some would say no, but I would say.  We could start off with something like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;when loading todays trades&lt;br/&gt;
- should load todays trades&lt;br/&gt;
- should not load trades from a previous date&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's not really saying anything useful is it.  Or is it?  Imagine you show this to your users and/or business analysts.  They're gonna ask:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"What on earth does that mean?  When loading today's trades, should load today's trades?  It doesn't make sense!  We're a bank, we have loads of trade systems, which one are you getting the trades from?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Oh right, well I was going to get them from the MYZ team's Oracle database which we got the trades from on the last project I worked on"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Ok, that's fine, but that's only going to work for trades outside of Asia.  For the trades on the Asian stockmarkets, we're going to have to get the data from the AYN team located in Singapore.  They have a web interface for looking at the trades and I think they provide some sort of service for you to retrieve it from"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Oh OK, thanks! I'll update the specs and get back to you to review them again!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You may think this is a fairly contrived example, but it's the sort of thing you will come up with time and time again. As developers, we move from project to project all the time, and we often make assumptions based on previous projects.  Users, on the other hand, are getting you to build a system to provide value to &lt;em&gt;their&lt;/em&gt; business.  They are likely to know it a lot better than you!  Business Analysts especially have a very detailed knowledge of all the internal systems and what their responsibilities are (though they may not have the kind of deep technical knowledge you have of communications protocols, etc).&lt;/p&gt;

&lt;p&gt;So think twice about abandoning BDD for the lower layers of the system.  Write the specs, share them, invite everyone you possibly can to review them.  The earlier problems are found in a system, the cheaper they are to fix. That's been proven through countless studies.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-6243573038673312521?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=PFsc3AjPJgQ:xcnysOSTCXs:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=PFsc3AjPJgQ:xcnysOSTCXs:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=PFsc3AjPJgQ:xcnysOSTCXs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=PFsc3AjPJgQ:xcnysOSTCXs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=PFsc3AjPJgQ:xcnysOSTCXs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=PFsc3AjPJgQ:xcnysOSTCXs:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=PFsc3AjPJgQ:xcnysOSTCXs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=PFsc3AjPJgQ:xcnysOSTCXs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=PFsc3AjPJgQ:xcnysOSTCXs:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/PFsc3AjPJgQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/6243573038673312521/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=6243573038673312521" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6243573038673312521?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6243573038673312521?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/05/bdd-everywhere-dont-underestimate-your.html" title="BDD Everywhere - don't underestimate your target audience" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0UESX8_cSp7ImA9WxJXEEk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-5878441911040946777</id><published>2009-06-03T18:09:00.002+01:00</published><updated>2009-06-03T18:13:28.149+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-03T18:13:28.149+01:00</app:edited><title>Evidence Based Scheduling</title><content type="html">&lt;p&gt;A co-worker just sent me this article from Joel Spolsky: &lt;a href="http://www.joelonsoftware.com/items/2007/10/26.html"&gt;http://www.joelonsoftware.com/items/2007/10/26.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I'd expect from Joel, it's a very well written article, and definitely worth a read.  Has anyone got any experience doing this?  I've always thought that tracking individual velocity was a bit fascist, but perhaps it could prove useful?&lt;/p&gt;

&lt;p&gt;Also, has anyone tried running a project using FogBugz.  Is it any good?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-5878441911040946777?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=T-29HDnsemg:eLu3cNDej4s:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=T-29HDnsemg:eLu3cNDej4s:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=T-29HDnsemg:eLu3cNDej4s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=T-29HDnsemg:eLu3cNDej4s:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=T-29HDnsemg:eLu3cNDej4s:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=T-29HDnsemg:eLu3cNDej4s:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=T-29HDnsemg:eLu3cNDej4s:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=T-29HDnsemg:eLu3cNDej4s:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=T-29HDnsemg:eLu3cNDej4s:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/T-29HDnsemg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/5878441911040946777/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=5878441911040946777" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5878441911040946777?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5878441911040946777?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/06/evidence-based-scheduling.html" title="Evidence Based Scheduling" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DE4ASX45fyp7ImA9WxJRFkg.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-1327040012213603934</id><published>2009-05-18T14:59:00.006+01:00</published><updated>2009-05-18T15:29:08.027+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-18T15:29:08.027+01:00</app:edited><title>Extension methods make your code more readable</title><content type="html">&lt;p&gt;There has been a long standing argument for and against using extension methods.  Recently I am on the quest to write code which is as readable as possible.  That really is my prime aim - I want someone who is simply scanning my code to be able to, at a high level, understand exactly what is going on in that function.  All other aims come second to that (e.g. until a requirement comes along which says otherwise).&lt;/p&gt;

&lt;p&gt;Well, six months ago, I would never have made this statement - "Extension methods are a massive help here!". Honestly, they just are.  I know people hate them because you can't really tell where the method comes from, and it looks wierd, and it breaks OO because you should inherit to add functionality (well actually, I disagree with that statement being made blindly)...&lt;/p&gt;

&lt;p&gt;So I have a function which takes in some dates and returns a status depending on how the dates compare.  Here is a simplified version of the function:&lt;/p&gt;

&lt;pre style="overflow:auto"&gt;
public Status GetStatus(DateTime now, DateTime modifiedOn, DateTime createdOn)
{
  if (modifiedOn.Date == now.Date)
    return Status.Amended;
  else if (createdOn.Date == now.Date)
    return Status.New;
  else
    return Status.Unchanged;
}
&lt;/pre&gt;

&lt;p&gt;So what's wrong with that?  Well you have no idea what the if statement is actually doing!  Tell me, if you scan that quickly, can you tell what the business rule is here?  I am pretty sure most people will have to scan that a few times to get what is going on there.  I considered adding a comment, but comments are a definite code smell (see &lt;a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt;) so this is how I changed it (using an extension method)&lt;/p&gt;

&lt;pre style="overflow:auto"&gt;
public Status GetStatus(DateTime now, DateTime modifiedOn, DateTime createdOn)
{
  if (modifiedOn.SameDayAs(now))
    return Status.Amended;
  else if (createdOn.SameDayAs(now))
    return Status.New;
  else
    return Status.Unchanged;
}
&lt;/pre&gt;

&lt;p&gt;Simple but effective methinks.  I think it's definitely clearer (though could perhaps be made even better).  Do you agree?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-1327040012213603934?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=wz4qyC8o4go:ij_aMhlX2AI:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=wz4qyC8o4go:ij_aMhlX2AI:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=wz4qyC8o4go:ij_aMhlX2AI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=wz4qyC8o4go:ij_aMhlX2AI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=wz4qyC8o4go:ij_aMhlX2AI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=wz4qyC8o4go:ij_aMhlX2AI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=wz4qyC8o4go:ij_aMhlX2AI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=wz4qyC8o4go:ij_aMhlX2AI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=wz4qyC8o4go:ij_aMhlX2AI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/wz4qyC8o4go" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/1327040012213603934/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=1327040012213603934" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1327040012213603934?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1327040012213603934?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/05/extension-methods-make-your-code-more.html" title="Extension methods make your code more readable" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;A0ACRXo5cSp7ImA9WxJRE0U.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-1385768723850715916</id><published>2009-05-15T13:03:00.004+01:00</published><updated>2009-05-15T13:16:04.429+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-15T13:16:04.429+01:00</app:edited><title>A shout out to Benjamin Mitchell</title><content type="html">&lt;p&gt;&lt;a href="http://benjaminmitchell.blogspot.com"&gt;Benjamin has recently started blogging&lt;/a&gt; (and about time too!).  I have worked as a developer on one of his teams before, and he is a good guy to work for and really knows his stuff.  He's one of those PMs who is always looking to improve his team's knowledge, skills and processes.&lt;/p&gt;

&lt;p&gt;I hope to see postings about Agile techniques and Lean Development, and hopefully some good anecdotes too!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-1385768723850715916?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=cylZHzvCQA8:MGz58swJsJc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=cylZHzvCQA8:MGz58swJsJc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=cylZHzvCQA8:MGz58swJsJc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=cylZHzvCQA8:MGz58swJsJc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=cylZHzvCQA8:MGz58swJsJc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=cylZHzvCQA8:MGz58swJsJc:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=cylZHzvCQA8:MGz58swJsJc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=cylZHzvCQA8:MGz58swJsJc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=cylZHzvCQA8:MGz58swJsJc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/cylZHzvCQA8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/1385768723850715916/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=1385768723850715916" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1385768723850715916?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1385768723850715916?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/05/shout-out-to-benjamin-mitchell.html" title="A shout out to Benjamin Mitchell" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUICRn8-eyp7ImA9WxJRE0U.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-2622058791318061340</id><published>2009-05-14T17:53:00.003+01:00</published><updated>2009-05-15T12:39:27.153+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-15T12:39:27.153+01:00</app:edited><title>I am on Twitter</title><content type="html">Well, after much nagging by my good friend &lt;a href="http://nortools.blogspot.com"&gt;Mr Norton&lt;/a&gt;, followed by a number of people at the AltNet Beers the other night ("what, you aren't on Twitter mate???"), I have finally succumbed and signed up.  You can find me at &lt;a href="http://twitter.com/nmosafi"&gt;http://twitter.com/nmosafi&lt;/a&gt;.

I hope to be posting about all my fun and frustrations at work, and hopefully will avoid doing so whilst completely hammered!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-2622058791318061340?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=yU3aZwyq1wo:7oQF9obC3U4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=yU3aZwyq1wo:7oQF9obC3U4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=yU3aZwyq1wo:7oQF9obC3U4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=yU3aZwyq1wo:7oQF9obC3U4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=yU3aZwyq1wo:7oQF9obC3U4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=yU3aZwyq1wo:7oQF9obC3U4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=yU3aZwyq1wo:7oQF9obC3U4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=yU3aZwyq1wo:7oQF9obC3U4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=yU3aZwyq1wo:7oQF9obC3U4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/yU3aZwyq1wo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/2622058791318061340/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=2622058791318061340" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/2622058791318061340?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/2622058791318061340?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/05/i-am-on-twitter.html" title="I am on Twitter" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0EAQ3c5eCp7ImA9WxJREk8.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-6307495906617994636</id><published>2009-05-13T09:28:00.008+01:00</published><updated>2009-05-13T16:47:22.920+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-13T16:47:22.920+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term="AltNet" /><title>Last night's AltNet Beers</title><content type="html">&lt;p&gt;Firstly, thanks to &lt;a href="http://serialseb.blogspot.com/"&gt;Seb&lt;/a&gt; for organising the ALT.NET beers conference last night.  I had a great time and met some very interesting people who I hope to see at future conferences.&lt;/p&gt;&lt;p&gt;The first topic was on two related questions, which were something along the lines of "why would I use a non-relational database" and "how would I architect a database differently if I was writing more than I was reading".&lt;/p&gt;

&lt;p&gt;Personally, I wasn't really getting the question here.  The whole thing about "writing more than I read" made no sense to me - why bother writing it if you're never going to read it.  The speaker was unable to really identify where his pain points are with his system.  I felt that there was an interesting discussion to be had, but the conversation didn't seem to inspire many people and it wasn't carried too far.  I would welcome this discussion continuing elsewhere and if it does I would be keen to take part in it.&lt;/p&gt;

&lt;p&gt;We talked a bit about document databases here, &lt;a href="http://ayende.com/"&gt;Ayende&lt;/a&gt; naturally getting involved as he has designed (not built, mind) a document database before.  The idea is that if you want to store fairly unstructured data, you would use a document database. Again, this isn't something I know much about and I wasn't sure what the benefits of a document database are over, say, storing the document on a file system and then indexing the information you want to search separately (e.g in a relational database for querying, or search appliance for searching).&lt;/p&gt;

&lt;p style=" font-style: italic; "&gt;Note: I was going to discuss this further outside with Ayende but the topic changed to BDD which is something I have recently starting doing so I wanted to hang around for that one!  If you're reading then perhaps we can discuss it next time?&lt;/p&gt;

&lt;p&gt;So as I said, we moved onto BDD which &lt;a href="codebetter.com/blogs/ian_cooper"&gt;Ian Cooper&lt;/a&gt; summed up excellently with a great analogy, which I won't repeat here.  What it bogs down to is that whilst test driven development is about ensuring that we do things right, behaviour driven development is about ensuring that we do the right thing.  Given that we had a bunch of Lean/Kanban enthusiasts there, I thought it quite appropriate topic.  With BDD you minimise rework by getting things done right the first time, this will naturally help to  you can increase throughput and decrease wastage, which is what Lean's all about.&lt;/p&gt;

&lt;p&gt;So having recently started a new job (which explains my lack of recent blog posts) I am trying to introduce BDD to the team, using SpecUnit.Net.  They don't do TDD at all, and I think BDD is not only easier to adopt but also adds much more value.   I am actually new to BDD, having consistenly read about it I'd not had the chance to actually try it on a proper project.  I am impressed with the effect and the way it makes you think about your code, so much so that I couldn't see myself not developing in this way ever again!&lt;/p&gt;

&lt;p&gt;Anyway I actually had some interesting conversations after the event about BDD.  I will try to gather my thoughts about this soon and perhaps capture them on a future blog post.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-6307495906617994636?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=a62hLklTXzA:1fw72OMI2yI:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=a62hLklTXzA:1fw72OMI2yI:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=a62hLklTXzA:1fw72OMI2yI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=a62hLklTXzA:1fw72OMI2yI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=a62hLklTXzA:1fw72OMI2yI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=a62hLklTXzA:1fw72OMI2yI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=a62hLklTXzA:1fw72OMI2yI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=a62hLklTXzA:1fw72OMI2yI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=a62hLklTXzA:1fw72OMI2yI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/a62hLklTXzA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/6307495906617994636/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=6307495906617994636" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6307495906617994636?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6307495906617994636?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/05/last-nights-altnet-beers.html" title="Last night's AltNet Beers" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0YBQno7fip7ImA9WxVUFEw.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-5506483517418617722</id><published>2009-03-18T23:32:00.001Z</published><updated>2009-03-18T23:32:33.406Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-18T23:32:33.406Z</app:edited><title>Silverlight 3… why WPF any more?</title><content type="html">&lt;p&gt;Just reading about &lt;a href="http://timheuer.com/blog/archive/2009/03/18/silverlight-3-whats-new-a-guide.aspx"&gt;Silverlight 3&lt;/a&gt; and amazed by the amount of new features which are being added… just look at &lt;a href="http://timheuer.com/blog/archive/2009/03/18/silverlight-3-whats-new-a-guide.aspx"&gt;the list&lt;/a&gt;!&lt;/p&gt;  &lt;p&gt;It begs the questions is there actually anything left in WPF that Silverlight now can’t do?&amp;#160; It now even supports running outside of the browser!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-5506483517418617722?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=svvq_uuuKLM:B6tga58RAaY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=svvq_uuuKLM:B6tga58RAaY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=svvq_uuuKLM:B6tga58RAaY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=svvq_uuuKLM:B6tga58RAaY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=svvq_uuuKLM:B6tga58RAaY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=svvq_uuuKLM:B6tga58RAaY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=svvq_uuuKLM:B6tga58RAaY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=svvq_uuuKLM:B6tga58RAaY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=svvq_uuuKLM:B6tga58RAaY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/svvq_uuuKLM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/5506483517418617722/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=5506483517418617722" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5506483517418617722?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5506483517418617722?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/03/silverlight-3-why-wpf-any-more.html" title="Silverlight 3… why WPF any more?" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;CU8HSH04cSp7ImA9WxVUE08.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-7351624968598766718</id><published>2009-03-17T21:02:00.001Z</published><updated>2009-03-17T21:03:59.339Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-17T21:03:59.339Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="COMET" /><title>COMET: The Bayeux Protocol and ASP.NET support</title><content type="html">&lt;p&gt;In my &lt;a href="http://neilmosafi.blogspot.com/2009/03/comet-pushing-to-web-browser.html"&gt;previous post&lt;/a&gt; I discussed the merits of the COMET technique for pushing data to the browser over standard web protocols.&lt;/p&gt;  &lt;p&gt;The basic idea behind COMET is that the browser keeps an HTTP connection open and the server uses it to send data back.&amp;#160; This contrasts with HTTP’s Request/Response paradigm where the browser is specifically requesting data when it needs it.&amp;#160; There are two main types of COMET – Streaming and Long-Polling.&amp;#160; For Streaming COMET, the browser opens a single connection and keeps it open indefinitely, receiving events from the server when they are ready to be sent and immediately processing them.&amp;#160; With Long-Polling, a connection is opened and is kept open until the server has data to send to the browser (or data is sent immediately if waiting).&amp;#160; Once the data is received, a new connection is immediately opened which again blocks until data is ready to be received, and so on.&lt;/p&gt;  &lt;p&gt;Over the last several years a protocol for COMET, known as &lt;a href="http://svn.cometd.org/trunk/bayeux/bayeux.html"&gt;Bayeux&lt;/a&gt;, has been formalised by the &lt;a href="http://dojofoundation.org"&gt;dojo foundation&lt;/a&gt;.&amp;#160; The protocol specifies the wire format for messaging between client and server as well as the transport mechanisms involved, and supports both streaming and long-polling over standard HTTP transports.&amp;#160; It’s essentially a specification for a pub/sub &lt;a href="http://msdn.microsoft.com/en-us/library/ms978583.aspx"&gt;message bus&lt;/a&gt;, where clients can publish messages to channels and subscribe to messages on those channels.&amp;#160; A number of client libraries have support for Bayeux style comet messaging, most notably &lt;a href="http://dojotoolkit.org/"&gt;the Dojo Toolkit&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;There are also a number of server frameworks for COMET out there, including one from Dojo themselves – &lt;a href="http://cometdproject.dojotoolkit.org/"&gt;cometd&lt;/a&gt; - which implements Bayeux and integrates with their client framework.&amp;#160; There are also commercial COMET servers out there, such as LightStreamer and Liberator, which actually offer .NET integration and support for integrating with enterprise messaging systems such as Tibco RV.&amp;#160; However, searching around I have been unable to find any that run within ASP.NET (well definitely not free ones anyway) and I think it’s a very important thing to support within ASP.NET - custom servers are fine, but you can’t exactly run them on shared hosting providers!&lt;/p&gt;  &lt;p&gt;One of the main challenges to developing a COMET server which runs within IIS is the threading model of ASP.NET (I believe Apache has the same issues, but not sure).&amp;#160; With ASP.NET, each request is serviced by a single thread from the thread pool.&amp;#160; This basically rules out being able to support Streaming COMET, as we would have to keep a thread aside for each client, and there a limited number of threads in the thread pool.&amp;#160; So this leaves the Long-Polling option.&amp;#160; This is wholly possible within ASP.NET as it has support for asynchronous processing, meaning we can put the thread back on the thread pool until we actually have data to send back to the client.&lt;/p&gt;  &lt;p&gt;And this is what I am working on now. The project is called AspComet and is available at the &lt;a href="http://aspcomet.googlecode.com/"&gt;AspComet Google Code Website&lt;/a&gt; via SVN.&amp;#160; It’s pretty basic at the moment and it just supports a small test case, however it’s built against the Bayeux spec and therefore can be used with any client library which supports Bayeux (I am testing with dojo of course).&lt;/p&gt;  &lt;p&gt;In the next post, I will describe a bit about how it works and walk through a sample simple chat application built using it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-7351624968598766718?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=mIaoA3p1WZs:Iqf5HScEAFw:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=mIaoA3p1WZs:Iqf5HScEAFw:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=mIaoA3p1WZs:Iqf5HScEAFw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=mIaoA3p1WZs:Iqf5HScEAFw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=mIaoA3p1WZs:Iqf5HScEAFw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=mIaoA3p1WZs:Iqf5HScEAFw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=mIaoA3p1WZs:Iqf5HScEAFw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=mIaoA3p1WZs:Iqf5HScEAFw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=mIaoA3p1WZs:Iqf5HScEAFw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/mIaoA3p1WZs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/7351624968598766718/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=7351624968598766718" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/7351624968598766718?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/7351624968598766718?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/03/comet-bayeux-protocol-and-aspnet.html" title="COMET: The Bayeux Protocol and ASP.NET support" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;D0EER3YzcCp7ImA9WxVVFEk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-5838423801993177358</id><published>2009-03-07T17:06:00.001Z</published><updated>2009-03-07T17:06:46.888Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T17:06:46.888Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Browser" /><category scheme="http://www.blogger.com/atom/ns#" term="COMET" /><title>COMET: Pushing to the web browser</title><content type="html">&lt;p&gt;A technology which is making a lot of advances in the world of the web is COMET. COMET is the name given to a group of techniques for pushing data to the browser using JavaScript. Being a Request/Response architecture, HTTP is not really designed for sending data to the browser on demand, COMET enables this.&lt;/p&gt;  &lt;p&gt;So a bit of background here. Traditional “AJAX applications” often continually poll for changes and update the screen accordingly.&amp;#160; In fact, in ASP.NET, a very easy solution is to combine an asp:Timer class with an asp:UpdatePanel and simply re-render the changing content every few seconds and send back the updated HTML.&amp;#160; Taking this to a more advanced level, it’s possible to send data back to the browser (typically as JSON) and then use DOM manipulation to update the elements viewed on the screen.&lt;/p&gt;  &lt;p&gt;To give a more concrete example, imagine a simple “chat room” application.&amp;#160; A simple solution could be to render a div with the list of chat messages in it, wrapped in an UpdatePanel, and then provide a text box for entering chat messages.&amp;#160; When the user presses “enter” within the textbox, an AJAX request is made to send the message back to the server, and the server adds this message to the list of chat messages.&amp;#160; The update panel can then be refreshed using a timer.&lt;/p&gt;  &lt;p&gt;What are the problems with this?&amp;#160; Two things – scalability and latency.&lt;/p&gt;  &lt;p&gt;Firstly, we are sending back the rendered HTML each time - this is not the most efficient use of bandwidth (i.e. each chat message is likely wrapped in a few elements).&amp;#160; Secondly, every time the UpdatePanel is refreshed, the entire chat history has to be sent back.&amp;#160; As this grows this will be become problematic as the amount of data being processed and sent over the network will increase exponentially with the number of users contributing to the chat.&amp;#160; Finally, as we are polling (say once every 5 seconds) there is a lag involved between when a user enters a chat message and when another user receives the message.&amp;#160; These are potentially not major issues, but in this day and age the average web user’s expectations are quite high - they expect lightweight, fast and responsive web user interfaces!&lt;/p&gt;  &lt;p&gt;We can solve each of these problems in turn.&amp;#160; To resolve the first issue, we can remove the update panel, and replace it with an AJAX call made using a standard JavaScript “setTimeout()” function.&amp;#160; Instead of sending back HTML using an UpdatePanel, we send back an array of JavaScript objects encoded as JSON.&amp;#160; Each object represents a single chat message and could have the following properties – ID, Source, Message.&amp;#160; The AJAX response handler would render the appropriate HTML from the JSON objects (for example, using ASP.NET 4’s client side templating).&lt;/p&gt;  &lt;p&gt;Once you have JSON objects coming back to the browser, the second issue becomes easy to solve.&amp;#160; The browser can send back the ID of the last message it received, and the server only needs to send back those messages which were received after that.&lt;/p&gt;  &lt;p&gt;It’s when we try to resolve the latency issue that the this technique becomes problematic.&amp;#160; The only real solution using plain old polling is to increase the polling frequency, which leads to a huge waste of server resources.&lt;/p&gt;  &lt;p&gt;So we come back to COMET, which is a technique (some might say hack, but I disagree) of pushing data to the browser using standard HTTP requests.&amp;#160; There are alternatives to this approach, namely using browser plugins.&amp;#160; Flash and Silverlight both have support for raw sockets, and Silverlight has the “polling duplex” WCF transport (which I may discuss in a later post).&amp;#160; However, COMET is a solution which has been designed from the ground up to use standard web technologies and run over HTTP.&amp;#160; I will discuss the technical details of COMET further in the next post… this post is really just an introduction and to point out that I have started working on a project which will enable COMET via ASP.NET hosted in IIS!&lt;/p&gt;  &lt;p&gt;More to come…    &lt;br /&gt;Neil&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-5838423801993177358?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=4ObF1olShpA:kfsa0UWSEmE:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=4ObF1olShpA:kfsa0UWSEmE:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=4ObF1olShpA:kfsa0UWSEmE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=4ObF1olShpA:kfsa0UWSEmE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=4ObF1olShpA:kfsa0UWSEmE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=4ObF1olShpA:kfsa0UWSEmE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=4ObF1olShpA:kfsa0UWSEmE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=4ObF1olShpA:kfsa0UWSEmE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=4ObF1olShpA:kfsa0UWSEmE:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/4ObF1olShpA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/5838423801993177358/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=5838423801993177358" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5838423801993177358?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5838423801993177358?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/03/comet-pushing-to-web-browser.html" title="COMET: Pushing to the web browser" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;AkUGR3o4eSp7ImA9WxVQEkg.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-6596555544380548146</id><published>2009-01-29T15:30:00.002Z</published><updated>2009-01-29T19:43:46.431Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T19:43:46.431Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><title>Another great error message from MS</title><content type="html">&lt;p&gt;Spent the last 2 hours trying to diagnose an error message.&amp;#160; I am writing a batch file which simply executes a SQL script using sqlcmd.&amp;#160; This is the command:&lt;/p&gt;  &lt;pre class="code"&gt;sqlcmd -S %SQLServerName% -E -i InstallSql.sql &amp;gt; InstallSql.txt&lt;/pre&gt;

&lt;p&gt;For the life of me, I have no idea what is going wrong.&amp;#160; The error message is incredibly useful&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sqlcmd: Error: Microsoft SQL Server Native Client 10.0 : Syntax error, permission violation, or other nonspecific error&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ok, so it could be one thing, or maybe it’s another, oh actually it could be anything at all really.&amp;#160; Essentially they're saying YOU ARE ON YOUR OWN WITH THIS ONE, trial and error is the only way.&lt;/p&gt;

&lt;p&gt;Anyone got any ideas what this could be? I’m gonna throw my laptop out of the Window soon!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-6596555544380548146?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=XyB0gDdcT-A:igniwwvHgQc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=XyB0gDdcT-A:igniwwvHgQc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=XyB0gDdcT-A:igniwwvHgQc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=XyB0gDdcT-A:igniwwvHgQc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=XyB0gDdcT-A:igniwwvHgQc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=XyB0gDdcT-A:igniwwvHgQc:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=XyB0gDdcT-A:igniwwvHgQc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=XyB0gDdcT-A:igniwwvHgQc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=XyB0gDdcT-A:igniwwvHgQc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/XyB0gDdcT-A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/6596555544380548146/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=6596555544380548146" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6596555544380548146?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6596555544380548146?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/01/another-great-error-message-from-ms.html" title="Another great error message from MS" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;D08NRXc4fyp7ImA9WxVQEUU.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-8649192859043836782</id><published>2009-01-28T23:36:00.002Z</published><updated>2009-01-28T23:38:14.937Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-28T23:38:14.937Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><title>Azure Event Log and log4net</title><content type="html">&lt;p&gt;I have been experimenting with Windows Azure recently for hosting a small application I wrote.&amp;#160; Thus far I am fairly impressed; despite a few periods of downtime and the odd bug with deployments, things seem to be stabilising fairly quickly and it’s all working well now (well I can’t complain as it’s currently free!)&lt;/p&gt;  &lt;p&gt;Azure’s hosting platform provides a number of services which allow you to interact with the platform.&amp;#160; These are mostly through the &lt;a href="http://horsemanstorage.blob.core.windows.net"&gt;Microsoft.ServiceHosting.ServiceRuntime.RoleManager&lt;/a&gt; class.&amp;#160; For example, you are able to retrieve configuration settings from the service configuration file, access local non persistent resources, and log messages to the Azure Event Log, via the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.servicehosting.serviceruntime.rolemanager.writetolog.aspx"&gt;RoleManager.WriteToLog&lt;/a&gt; method.&lt;/p&gt;  &lt;p&gt;Messages can be copied from the log to any Azure Storage account simply by clicking a button on the configuration menu of the hosting instance:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_BrWlEQlsE3c/SYDsBSkaodI/AAAAAAAAADM/Ie9ro8KCngQ/s1600-h/image3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_BrWlEQlsE3c/SYDsBpsvSjI/AAAAAAAAADQ/ibPiPUt49a8/image_thumb1.png?imgmax=800" width="696" height="88" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;These logs are copied to the “blobs” area of your chosen Azure Storage account (there are also tables and remote queues) and Microsoft have provided a fairly simple REST API for managing the data stored within the account.&amp;#160; There is also a .NET api which wraps the REST API but I am yet to look at it (I will do once I build a persistence layer for my application).&lt;/p&gt;  &lt;p&gt;A few tools have been written for viewing the log files – &lt;a href="http://www.codeplex.com/azurestorageexplorer/"&gt;Azure Storage Explorer&lt;/a&gt; seems to be the best that' I’ve tried, those there may be more which I’ve not found yet.&amp;#160; You simply put the URLs of the REST endpoints into the config file and you get a nice viewer which lets you see all the messages and delete&lt;/p&gt;  &lt;p&gt;Now all my applications tend to standardise on &lt;a href="http://logging.apache.org/log4net/"&gt;log4net&lt;/a&gt; for logging messages, which provides configurable and customisable routing of logging messages to pretty much any target you want.&amp;#160; I wrote a simple log4net appender which can be used to route messages to the Azure Event Log.&amp;#160; Here is the source code&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;AzureAppender &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;AppenderSkeleton
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;protected override void &lt;/span&gt;Append(&lt;span style="color: #2b91af"&gt;LoggingEvent &lt;/span&gt;loggingEvent)
    {
        &lt;span style="color: #2b91af"&gt;RoleManager&lt;/span&gt;.WriteToLog(GetLogName(loggingEvent), loggingEvent.RenderedMessage);
    }

    &lt;span style="color: blue"&gt;private static string &lt;/span&gt;GetLogName(&lt;span style="color: #2b91af"&gt;LoggingEvent &lt;/span&gt;loggingEvent)
    {
        &lt;span style="color: blue"&gt;if &lt;/span&gt;(loggingEvent.Level == &lt;span style="color: #2b91af"&gt;Level&lt;/span&gt;.Critical)
            &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EventLogNames&lt;/span&gt;.Critical;

        &lt;span style="color: blue"&gt;if &lt;/span&gt;(loggingEvent.Level == &lt;span style="color: #2b91af"&gt;Level&lt;/span&gt;.Error)
            &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EventLogNames&lt;/span&gt;.Error;

        &lt;span style="color: blue"&gt;if &lt;/span&gt;(loggingEvent.Level == &lt;span style="color: #2b91af"&gt;Level&lt;/span&gt;.Warn)
            &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EventLogNames&lt;/span&gt;.Warning;

        &lt;span style="color: blue"&gt;if &lt;/span&gt;(loggingEvent.Level == &lt;span style="color: #2b91af"&gt;Level&lt;/span&gt;.Info)
            &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EventLogNames&lt;/span&gt;.Information;

        &lt;span style="color: blue"&gt;if &lt;/span&gt;(loggingEvent.Level == &lt;span style="color: #2b91af"&gt;Level&lt;/span&gt;.Verbose)
            &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EventLogNames&lt;/span&gt;.Verbose;

        &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EventLogNames&lt;/span&gt;.Error;
    }

    &lt;span style="color: blue"&gt;private static class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;EventLogNames
    &lt;/span&gt;{
        &lt;span style="color: blue"&gt;public const string &lt;/span&gt;Critical = &lt;span style="color: #a31515"&gt;&amp;quot;Critical&amp;quot;&lt;/span&gt;;
        &lt;span style="color: blue"&gt;public const string &lt;/span&gt;Error = &lt;span style="color: #a31515"&gt;&amp;quot;Error&amp;quot;&lt;/span&gt;;
        &lt;span style="color: blue"&gt;public const string &lt;/span&gt;Warning = &lt;span style="color: #a31515"&gt;&amp;quot;Warning&amp;quot;&lt;/span&gt;;
        &lt;span style="color: blue"&gt;public const string &lt;/span&gt;Information = &lt;span style="color: #a31515"&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;;
        &lt;span style="color: blue"&gt;public const string &lt;/span&gt;Verbose = &lt;span style="color: #a31515"&gt;&amp;quot;Verbose&amp;quot;&lt;/span&gt;;
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Note that log4net has lots more log levels than Azure supports, so I just default to Error if I get a message which is not one of the matching levels.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-8649192859043836782?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=aURb1_RNlK4:EbvPj21TWao:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=aURb1_RNlK4:EbvPj21TWao:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=aURb1_RNlK4:EbvPj21TWao:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=aURb1_RNlK4:EbvPj21TWao:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=aURb1_RNlK4:EbvPj21TWao:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=aURb1_RNlK4:EbvPj21TWao:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=aURb1_RNlK4:EbvPj21TWao:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=aURb1_RNlK4:EbvPj21TWao:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=aURb1_RNlK4:EbvPj21TWao:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/aURb1_RNlK4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/8649192859043836782/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=8649192859043836782" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/8649192859043836782?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/8649192859043836782?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2009/01/azure-event-log-and-log4net.html" title="Azure Event Log and log4net" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUQERHg8eSp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-1048868910388535482</id><published>2008-07-28T14:55:00.006+01:00</published><updated>2009-01-29T15:35:05.671Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T15:35:05.671Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>Microsoft Sponsors Open Source Apache</title><content type="html">&lt;p&gt;Given that Microsoft have invested lots of time and money in their own web server (IIS), this is a true endorsement of changes afoot at Microsoft &lt;a href="http://news.bbc.co.uk/1/hi/technology/7528857.stm"&gt;http://news.bbc.co.uk/1/hi/technology/7528857.stm&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I personally think this makes complete sense for them. I truly believe as we move to a more service delivered software models, the value of source code (or software IP) becomes less important, as licence revenue becomes less of a percentage of total revenue for the big boys such as MS. &lt;/p&gt;  &lt;p&gt;For companies like Microsoft, interoperability is very important and its relevance is definitely growing. For example, I am sure that to allow users to be able to transfer services currently running on a LAMP architecture to run on Microsoft's own hosted Windows &amp;quot;cloud&amp;quot; architecture is going to be important for them in future (even if it's not running on a .NET platform). &lt;a href="http://port25.technet.com/archive/2008/07/25/oscon2008.aspx"&gt;Here is some more detailed info&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Interestingly enough, their competitor Apple seems to be going in the other direction with their iPhone SDK, for which &lt;a href="http://discussions.apple.com/thread.jspa?messageID=7563732"&gt;the licence agreement&lt;/a&gt; apparently does not allow people to build &lt;a href="http://www.linux.com/feature/131752"&gt;open source software&lt;/a&gt;... hmm!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-1048868910388535482?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=TDYX4Z7fHZ8:cQljnqr-TnU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=TDYX4Z7fHZ8:cQljnqr-TnU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=TDYX4Z7fHZ8:cQljnqr-TnU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=TDYX4Z7fHZ8:cQljnqr-TnU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=TDYX4Z7fHZ8:cQljnqr-TnU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=TDYX4Z7fHZ8:cQljnqr-TnU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=TDYX4Z7fHZ8:cQljnqr-TnU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=TDYX4Z7fHZ8:cQljnqr-TnU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=TDYX4Z7fHZ8:cQljnqr-TnU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/TDYX4Z7fHZ8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/1048868910388535482/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=1048868910388535482" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1048868910388535482?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1048868910388535482?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/07/microsoft-sponsors-open-source-apache.html" title="Microsoft Sponsors Open Source Apache" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUIBQnw4cCp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-3984867508327415720</id><published>2008-07-23T14:56:00.006+01:00</published><updated>2009-01-29T15:39:13.238Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T15:39:13.238Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><title>Is INotifyPropertyChanged an anti-pattern?</title><content type="html">&lt;p&gt;Something is starting to bother me recently about data binding and the INotifyPropertyChanged interface.  It's just that &lt;em&gt;EVERY&lt;/em&gt; class you write ends up having to implement it (I am generally talking about writing WPF/Silverlight applications here).  And that's just not sitting well with me!&lt;/p&gt;

&lt;p&gt;It doesn't sit well because I believe it violates the principles of separations of concern.  The major annoyance for me lies with calculated properties (those which are derived from another).  Lets start with a simple class, Order, which contains two properties, ItemPrice and Quantity (other fields and methods omitted for sake of brevity):&lt;/p&gt;
&lt;pre&gt;public class Order : INotifyPropertyChanged
{
  public decimal ItemPrice 
  { 
    get { return this.itemPrice; }
    set 
    {
       this.itemPrice = value;
       this.RaisePropertyChanged("ItemPrice");
    }
  }

  public int Quantity 
  { 
    get { return this.quantity; }
    set 
    {
       this.quantity= value;
       this.RaisePropertyChanged("Quantity");
    }
  }
}&lt;/pre&gt;
&lt;p&gt;We need to add a property TotalPrice to this entity which will expose the total price of the order.  What do we do here?  This is a calculated value so should clearly be read only, and I usually implement the calculation within the property itself.  What I have found myself doing many times in the past (and I have seen done in a lot of examples) is:&lt;/p&gt;
&lt;pre&gt;public class Order : INotifyPropertyChanged
{
  public decimal ItemPrice 
  { 
    get { return this.itemPrice; }
    set 
    {
       this.itemPrice = value;
       this.RaisePropertyChanged("ItemPrice");
       this.RaisePropertyChanged("TotalPrice");
    }
  }

  public int Quantity 
  { 
    get { return this.quantity; }
    set 
    {
       this.quantity= value;
       this.RaisePropertyChanged("Quantity");
       this.RaisePropertyChanged("TotalPrice");
    }
  }

  public decimal TotalPrice
  {
    get { return this.ItemPrice * this.Quantity; }    
  }
}&lt;/pre&gt;
&lt;p&gt;This is nasty.  We have had to modify our other two properties just because we have added this new one.  It works, but as you add more and more dependent properties your code gets messy.  Those properties shouldn't need to know that the TotalPrice property exists!&lt;/p&gt;

&lt;p&gt;That pattern breaks down completely when you start using inheritance in your domain objects.  Imagine if I now require a new type of domain object, SalesOrder, where I want to express the fact that there is a commission (expressed as a fraction) which needs to be paid to some salesperson on this order:&lt;/p&gt;
&lt;pre&gt;public class SalesOrder : Order
{
  public decimal SalesCommision
  { 
    get { return this.salesCommision}
    set 
    {
       this.salesCommisionPercentage = value;
       this.RaisePropertyChanged("SalesCommision");
       this.RaisePropertyChanged("TotalCommission");
    }
  }

  public decimal TotalCommission
  { 
    get { return this.TotalPrice * this.SalesCommission; }
  }
}&lt;/pre&gt;
&lt;p&gt;Uh-oh!  It's come a bit unstuck here.  If the price changes in the base class, my UI is not going to redisplay the total commission! This could be great for my sales person but not so great for my accountant!&lt;/p&gt;

&lt;p&gt;So what do we do here to get around this?  We clearly can't modify our base class, so how about we listen to our own property notifications, like thus:&lt;/p&gt;
&lt;pre&gt;public class SalesOrder : Order
{
  // Properties defined as previously //

  protected override void RaisePropertyChanged(string propertyName)
  {
     base.RaisePropertyChanged(propertyName);
     if (propertyName == "TotalPrice")
     {
        this.RaisePropertyChanged("TotalCommission");
     }
  }
}&lt;/pre&gt;

&lt;p&gt;Here we override the method which raises the event, check if the relevant dependent property is being raised, and if so we raise a changed event on our commission property.  This works, but YUCK!  Just imagine having to unit test all this! :-(&lt;/p&gt;

&lt;p&gt;Note that we end up with the same problem if we use composition.  Imagine that instead of storing the sales commission on our entity, it was actually stored on a related SalesPerson entity and we need to calculate it from there.  Now we need to know that if the sales person's commission changes, the order's total commission has changed:&lt;/p&gt;
&lt;pre&gt;public class SalesOrder : Order
{
  public SalesPerson SalesPerson
  { 
    get { return this.salesPerson; }
    set 
    {
       if (this.salesPerson != null)
       {
          this.salesPerson.PropertyChanged -= HandleSalesPersonPropertyChanged;
       }

       this.salesPerson = value;
       this.RaisePropertyChanged("SalesPerson");
       this.RaisePropertyChanged("TotalCommission");

       this.salesPerson.PropertyChanged += HandleSalesPersonPropertyChanged;
    }
  }

  public decimal TotalCommission
  { 
    get { return this.TotalPrice * this.SalesPerson.Commission; }
  }

  protected virtual void HandleSalesPersonPropertyChanged(object sender, PropertyChangedEventArgs e)
  {
     if (e.PropertyName == "Commission")
     {
        this.RaisePropertyChanged("TotalCommission");
     }
  }
}&lt;/pre&gt;

&lt;p&gt;We subscribe to the PropertyChanged event on our sales person, and when its commision is changed, we act accordingly.&lt;/p&gt;

&lt;p&gt;I think this is all a mess, and it just gets worse and worse as you build up your domain model and add more classes and more relations.  It's easy to forget one of these dependencies.  If you are building a fairly complex UI on top of this (e.g. one which allows you to drill down and navigate through the relationships and make changes to objects), I'm so sure you will introduce bugs due to not raising the event, I know it's happened to me!&lt;/p&gt;

&lt;p&gt;On my next (real) WPF project this is definitely something I will be thinking about seriously.&lt;/p&gt;

&lt;p&gt;Anyway I would be interested to know what people think about this.  Is this a problem which other people have faced?  How do you architect your applications to avoid this complexity?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-3984867508327415720?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=LJglkI4KQsQ:wqisvIrRpfo:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=LJglkI4KQsQ:wqisvIrRpfo:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=LJglkI4KQsQ:wqisvIrRpfo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=LJglkI4KQsQ:wqisvIrRpfo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=LJglkI4KQsQ:wqisvIrRpfo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=LJglkI4KQsQ:wqisvIrRpfo:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=LJglkI4KQsQ:wqisvIrRpfo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=LJglkI4KQsQ:wqisvIrRpfo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=LJglkI4KQsQ:wqisvIrRpfo:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/LJglkI4KQsQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/3984867508327415720/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=3984867508327415720" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/3984867508327415720?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/3984867508327415720?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/07/is-inotifypropertychanged-anti-pattern.html" title="Is INotifyPropertyChanged an anti-pattern?" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">13</thr:total></entry><entry gd:etag="W/&quot;CUEMQXczfCp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-6227477046183586895</id><published>2008-07-19T00:26:00.008+01:00</published><updated>2009-01-29T15:41:20.984Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T15:41:20.984Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverstone" /><title>Refactoring Silverstone - Removing static container and cleaning up the Shell</title><content type="html">&lt;p&gt;Hey readers, hope all is good!  Firstly to apologise on having been fairly quiet on the Silverstone / Silverlight blog postings, especially with regards to my series on architecting Silverlight applications using the MVC patterns (&lt;a href="http://neilmosafi.blogspot.com/2008/05/architecting-silverlight-applications_19.html"&gt;most recent article here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So, Silverlight Beta 2 came out and I spent some time absorbing those changes and trying to work out how they affect what I was doing.  I have also made some alterations to the Silverstone framework to remove some code smells I was experiencing when wiring the Views and ViewModels together in preparing part 4 of the series.&lt;/p&gt;

&lt;p&gt;One thing that Beta 2 adds is much better support for bubbling of RoutedEvents.  This is a great change, but it actually caused a problem for my CommandManager class!  The CommandManager was relying on the mouse and keyboard events bubbling up from their target element to the application root in order to provide automatic invalidation of the CanExecuteChanged handler on registered commands.  Now that Silverlight has more advanced handling of these events, they no longer bubble up to the application root (as the textbox/button/whatever marks them as e.Handled=true).  This is the correct behaviour and mirrors WPF, but it means my technique no longer works, making the ViewModels slightly more complex as they need to manually raise the CanExecuteChanged event.&lt;/p&gt;

&lt;p&gt;Once Silverlight gets event tunnelling, which I'm sure (hope!) will be incorporated into the next release, I will add this back in as we will be able to capture the events before they are actually handled by the target element (e.g. PreviewKeyDown / PreviewMouseDown).&lt;/p&gt;

&lt;p&gt;So I now have a basic view working, and will be creating the other views soon and blogging the next part in the near future.&lt;/p&gt;  

&lt;p&gt;As I mentioned, whilst working on this, I made a few refactorings to Silverstone (and to the sample code):&lt;/p&gt;

&lt;p&gt;The Ioc Container is no longer a static class.  This always bothered me - why have a static class here?  So I made it a non static and also made it implement an interface (IContainer).  The added bonus of this (and the real reason I did it) is that other components can access the container without going through a static reference.  So, the container now registers itself with itself, and you can get it passed to your class simply by adding a constructor parameter of type IContainer.&lt;/p&gt;

&lt;p&gt;Once I did that, I refactored the Shell class, which was looking rather nasty from the client API side of things!  If you remember in &lt;a href="http://neilmosafi.blogspot.com/2008/05/architecting-silverlight-applications.html"&gt;Part 2&lt;/a&gt; of my series, I was writing a LoginViewModel but I was having to pass the other related views into the constructor in order that I could navigate to them upon certain actions (see the comments saying &lt;em&gt;This is just an empty view interface for now&lt;/em&gt; *shudder*).  I think having to do this makes iterative development much harder as you need to create fakes and register them with the Ioc container just to have your class be constructed!&lt;/p&gt;

&lt;p&gt;So instead, the Shell now uses the IContainer to get the views from it and all I need to do is pass the type of the View interface to the Shell and it can do everything from there, like so:&lt;/p&gt;
&lt;pre&gt;this.shell.Navigate&amp;lt;IFriendListView&amp;gt;();&lt;/pre&gt;
&lt;p&gt;Finally, I moved the entire sample code into the actual Silverstone SVN repository, which makes it much easier for me to develop the two things side by side!  So if you want to an early preview of the code, you can &lt;a href="http://silverstone.googlecode.com/svn/trunk/"&gt;get it from svn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will be posting the entire solution once it's finished, and hopefully uploading it to some hosting area in the cloud.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-6227477046183586895?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=NG_QyVnrLFE:vCtFS3Z4klg:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=NG_QyVnrLFE:vCtFS3Z4klg:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=NG_QyVnrLFE:vCtFS3Z4klg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=NG_QyVnrLFE:vCtFS3Z4klg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=NG_QyVnrLFE:vCtFS3Z4klg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=NG_QyVnrLFE:vCtFS3Z4klg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=NG_QyVnrLFE:vCtFS3Z4klg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=NG_QyVnrLFE:vCtFS3Z4klg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=NG_QyVnrLFE:vCtFS3Z4klg:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/NG_QyVnrLFE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/6227477046183586895/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=6227477046183586895" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6227477046183586895?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/6227477046183586895?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/07/refactoring-silverstone-removing-static.html" title="Refactoring Silverstone - Removing static container and cleaning up the Shell" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DkQNRH47eip7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-2933556277492293678</id><published>2008-07-09T16:34:00.004+01:00</published><updated>2009-01-29T15:53:15.002Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T15:53:15.002Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><title>An unmanaged version of WPF coming?</title><content type="html">&lt;p&gt;This sounds incredibly interesting - it appears Microsoft are working on &lt;a href="http://www.aeroxp.org/2008/06/windows-7-introducing-winfx-minus-net/"&gt;what looks like a native version of WPF&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Anyone heard about this or know any more about this - I would love to know some details!  An unmanaged version would be great and would probably yield massive performance issues even for unmanaged WPF as a lot of the grunt work would presumably be able to be pushed to unmanaged code.&lt;/p&gt;

&lt;p&gt;Could this be the return of the Microsoft's old Cairo project (which now seems to be being worked on by an external group of developers if I'm not mistaken - &lt;a href="http://www.cairoshell.com/"&gt;www.cairoshell.com&lt;/a&gt;)&lt;p&gt;

&lt;p&gt;Thoughts?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-2933556277492293678?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=7RiM-dS-wj4:2o_nMFQB2Qk:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=7RiM-dS-wj4:2o_nMFQB2Qk:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=7RiM-dS-wj4:2o_nMFQB2Qk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=7RiM-dS-wj4:2o_nMFQB2Qk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=7RiM-dS-wj4:2o_nMFQB2Qk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=7RiM-dS-wj4:2o_nMFQB2Qk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=7RiM-dS-wj4:2o_nMFQB2Qk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=7RiM-dS-wj4:2o_nMFQB2Qk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=7RiM-dS-wj4:2o_nMFQB2Qk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/7RiM-dS-wj4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/2933556277492293678/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=2933556277492293678" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/2933556277492293678?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/2933556277492293678?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/07/unmanaged-version-of-wpf-coming.html" title="An unmanaged version of WPF coming?" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;Dk8BRHcyfSp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-1486095665602232315</id><published>2008-07-06T23:21:00.007+01:00</published><updated>2009-01-29T16:00:55.995Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T16:00:55.995Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linq" /><title>Using Linq's Expression Trees to Enable Better Refactoring</title><content type="html">&lt;p&gt;How many times have you seen code like this:&lt;/p&gt;
&lt;pre&gt;public DateTime StartDate
{
  get { return this.startDate; }
  set
  {
    this.startDate = value;
    this.RaisePropertyChanged(this, "StartDate");
  }
}&lt;/pre&gt;
&lt;p&gt;I know I have!  There are many areas of .NET development where you are required to specify the name of a property or method as a string.  This is fine, but if you rename the property, there is a chance that you will forget to update the string too, which is definitely not good!&lt;/p&gt;

&lt;p&gt;.NET 3.5 and Linq introduces a new feature called expression trees in the C#3 compiler.  Compilers typically generate an &lt;a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;AST (abstract syntax tree)&lt;/a&gt; from the code you write, which is then checked and transformed into machine code (or in .NET case, MSIL).  By using an expression tree, you tell the C# compiler not to compile your code into MSIL, but instead to create a representation of the code in object form.  This tree can then be navigated through methods on the Expression objects.&lt;/p&gt;

&lt;p&gt;Using an expression tree, we can simply write a method which will return the name of whichever method or property is being called (I used an extension method):&lt;/p&gt;

&lt;pre&gt;public static class Extensions
{
    public static string GetPropertyName&amp;lt;T,S&amp;gt;(this T obj, Expression&amp;lt;Func&amp;lt;T,S&amp;gt;&amp;gt; expr)
    {
        return ((MemberExpression) expr.Body).Member.Name;
    }
}&lt;/pre&gt;

&lt;p&gt;To call this is fairly simple, we rewrite the previous code as:&lt;/p&gt;

&lt;pre&gt;public DateTime StartDate
{
  get { return this.startDate; }
  set
  {
    this.startDate = value;
    this.RaisePropertyChanged(this, this.GetPropertyName(p =&gt; p.StartDate));
  }
}&lt;/pre&gt;

&lt;p&gt;The code above creates a lambda which returns the value of StartDate method and passes it to the GetPropertyName() method.  If this lamdba was to be executed, it would return the startDate, however the GetPropertyName() function never executes the lambda, it simply peeks into the code being called and returns the name of the property.&lt;/p&gt;

&lt;p&gt;This technique is starting to be used everywhere and it's so useful.  Code as strings is &lt;em&gt;nasty&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;Have a great day...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-1486095665602232315?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=23Qwi9cnTyc:iMXw5hcYPuQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=23Qwi9cnTyc:iMXw5hcYPuQ:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=23Qwi9cnTyc:iMXw5hcYPuQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=23Qwi9cnTyc:iMXw5hcYPuQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=23Qwi9cnTyc:iMXw5hcYPuQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=23Qwi9cnTyc:iMXw5hcYPuQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=23Qwi9cnTyc:iMXw5hcYPuQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=23Qwi9cnTyc:iMXw5hcYPuQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=23Qwi9cnTyc:iMXw5hcYPuQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/23Qwi9cnTyc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/1486095665602232315/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=1486095665602232315" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1486095665602232315?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1486095665602232315?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/07/using-expression-trees-to-enable-better.html" title="Using Linq's Expression Trees to Enable Better Refactoring" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUEFQ384eip7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-9202369448282338797</id><published>2008-07-06T02:44:00.005+01:00</published><updated>2009-01-29T16:46:52.132Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T16:46:52.132Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><title>Selecting the Detail Level to View at Runtime in WPF - An even better way!</title><content type="html">&lt;p&gt;Regarding my &lt;a href="http://neilmosafi.blogspot.com/2008/07/selecting-detail-level-to-view-at.html"&gt;previous post&lt;/a&gt; Josh &lt;a href="http://www.codeproject.com/KB/WPF/SelectDetailLevels.aspx?msg=2625790#xx2625790xx"&gt;rightly commented&lt;/a&gt; that this technique could lead to lots of extra visuals being created that are never displayed, which for large data loads is not desirable and definitely a waste of resources.  Josh also made a number of other salient points which are worth reading.&lt;/p&gt;

&lt;p&gt;Well it was upon reading this comment that it struck me that there was in fact no need to be creating (and hiding lots of visuals) when they are not used!  We simply need a SINGLE content presnter, and just change the template of that with a trigger, like so:&lt;/p&gt;

&lt;pre style="overflow:auto"&gt;  &amp;lt;DataTemplate x:Key="SelectorTemplate"&amp;gt;
    &amp;lt;Grid&amp;gt;
      &amp;lt;ContentPresenter x:Name="proxyDataPresenter" Content="{Binding}" /&amp;gt;
    &amp;lt;/Grid&amp;gt;
    &amp;lt;DataTemplate.Triggers&amp;gt;
      &amp;lt;DataTrigger Binding="{Binding ElementName=detailLevelSlider, Path=Value}" Value="1"&amp;gt;
        &amp;lt;Setter TargetName="proxyDataPresenter" Property="ContentTemplate" 
                Value="{StaticResource LowTemplate}" /&amp;gt;
      &amp;lt;/DataTrigger&amp;gt;
      &amp;lt;DataTrigger Binding="{Binding ElementName=detailLevelSlider, Path=Value}" Value="2"&amp;gt;
        &amp;lt;Setter TargetName="proxyDataPresenter" Property="ContentTemplate" 
                Value="{StaticResource MediumTemplate}" /&amp;gt;
      &amp;lt;/DataTrigger&amp;gt;
      &amp;lt;DataTrigger Binding="{Binding ElementName=detailLevelSlider, Path=Value}" Value="3"&amp;gt;
        &amp;lt;Setter TargetName="proxyDataPresenter" Property="ContentTemplate" 
                Value="{StaticResource HighTemplate}" /&amp;gt;
      &amp;lt;/DataTrigger&amp;gt;
    &amp;lt;/DataTemplate.Triggers&amp;gt;
  &amp;lt;/DataTemplate&amp;gt;&lt;/pre&gt;

&lt;p&gt;The simplicity baffles me and it really works a treat... again this kind of thing just makes me appreciate the sheer power of WPF and it's declarative style of programming.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-9202369448282338797?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=SrL-bQLpXC0:LuRUGqLAuk4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=SrL-bQLpXC0:LuRUGqLAuk4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=SrL-bQLpXC0:LuRUGqLAuk4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=SrL-bQLpXC0:LuRUGqLAuk4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=SrL-bQLpXC0:LuRUGqLAuk4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=SrL-bQLpXC0:LuRUGqLAuk4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=SrL-bQLpXC0:LuRUGqLAuk4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=SrL-bQLpXC0:LuRUGqLAuk4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=SrL-bQLpXC0:LuRUGqLAuk4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/SrL-bQLpXC0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/9202369448282338797/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=9202369448282338797" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/9202369448282338797?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/9202369448282338797?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/07/selecting-detail-level-to-view-at_06.html" title="Selecting the Detail Level to View at Runtime in WPF - An even better way!" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;AkUASXgzcCp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-5371897452744228567</id><published>2008-07-05T22:08:00.003+01:00</published><updated>2009-01-29T16:57:28.688Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T16:57:28.688Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WPF" /><title>Selecting the Detail Level to View at Runtime in WPF - An alternate way?</title><content type="html">&lt;p&gt;I recently read &lt;a href="http://joshsmithonwpf.wordpress.com/2008/07/05/fifty-articles-and-going-strong/"&gt;Josh Smith&lt;/a&gt;'s &lt;a href="http://www.codeproject.com/KB/WPF/SelectDetailLevels.aspx"&gt;post on codeproject&lt;/a&gt; which explained how to use a Slider control to dynamically apply a WPF data template a runtime.  If you haven't read it, I suggest you &lt;a href="http://www.codeproject.com/KB/WPF/SelectDetailLevels.aspx"&gt;read it&lt;/a&gt; before continuing.&lt;/p&gt;

&lt;p&gt;So I have come up with an alternative solution which is done in pure XAML.  This is a technique which I have used on previous projects and it involves creating a "surrogate" data template which simply passes control to another data template via a content presenter.  Because a data template is used to do this, it has access to the inheritance context so does not require any freezable hacks to find the slider or other data templates.&lt;/p&gt;

&lt;p&gt;Note that in order to make this a pure xaml solution I replaced the data source (which was originally in code) with an XmlDataProvider nested in the XAML document.  Hence that lovely Pam girl does not appear in my version, which will probably disappoint most people...&lt;/p&gt;

&lt;p&gt;Anyway check it out below, simple copy and paste in XamlPad/Kaxaml to see it working!&lt;/p&gt;
&lt;pre style="overflow:auto"&gt;&amp;lt;Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&amp;gt;
  &amp;lt;DockPanel&amp;gt;  
    &amp;lt;DockPanel.Resources&amp;gt;
    
      &amp;lt;XmlDataProvider x:Key="Data" XPath="/people"&amp;gt;
        &amp;lt;x:XData&amp;gt;
          &amp;lt;people xmlns=""&amp;gt;
            &amp;lt;person name="Neil" age="29" gender="M" /&amp;gt;
            &amp;lt;person name="Jane" age="40" gender="F" /&amp;gt;
            &amp;lt;person name="Jack" age="23" gender="M" /&amp;gt;
          &amp;lt;/people&amp;gt;
        &amp;lt;/x:XData&amp;gt;
      &amp;lt;/XmlDataProvider&amp;gt;        
    
      &amp;lt;DataTemplate x:Key="LowTemplate"&amp;gt;
        &amp;lt;TextBlock Text="{Binding XPath=@name}" /&amp;gt;
      &amp;lt;/DataTemplate&amp;gt;
    
      &amp;lt;DataTemplate x:Key="MediumTemplate"&amp;gt;
        &amp;lt;TextBlock&amp;gt;
            &amp;lt;TextBlock Text="{Binding XPath=@name}" /&amp;gt;
            &amp;lt;Run&amp;gt;(&amp;lt;/Run&amp;gt;
            &amp;lt;TextBlock Text="{Binding XPath=@age}" Margin="-4,0" /&amp;gt;
            &amp;lt;Run&amp;gt;)&amp;lt;/Run&amp;gt;
          &amp;lt;/TextBlock&amp;gt;
      &amp;lt;/DataTemplate&amp;gt;
    
      &amp;lt;DataTemplate x:Key="HighTemplate"&amp;gt;
        &amp;lt;TextBlock&amp;gt;
          &amp;lt;TextBlock Text="{Binding XPath=@name}" /&amp;gt;
          &amp;lt;Run&amp;gt;(&amp;lt;/Run&amp;gt;
          &amp;lt;TextBlock Text="{Binding XPath=@age}" Margin="-4,0" /&amp;gt;
          &amp;lt;Run&amp;gt;) -&amp;lt;/Run&amp;gt;
          &amp;lt;TextBlock Text="{Binding XPath=@gender}" /&amp;gt;
        &amp;lt;/TextBlock&amp;gt;
      &amp;lt;/DataTemplate&amp;gt;
      
      &amp;lt;DataTemplate x:Key="SelectorTemplate"&amp;gt;
        &amp;lt;Grid&amp;gt;
          &amp;lt;ContentPresenter x:Name="lowPresenter" 
                Content="{Binding}" ContentTemplate="{StaticResource LowTemplate}" 
                Visibility="Collapsed" /&amp;gt;
          &amp;lt;ContentPresenter x:Name="mediumPresenter" 
                Content="{Binding}" ContentTemplate="{StaticResource MediumTemplate}" 
                Visibility="Collapsed" /&amp;gt;
          &amp;lt;ContentPresenter x:Name="highPresenter" 
                Content="{Binding}" ContentTemplate="{StaticResource HighTemplate}" 
                Visibility="Collapsed" /&amp;gt;
        &amp;lt;/Grid&amp;gt;
        &amp;lt;DataTemplate.Triggers&amp;gt;
          &amp;lt;DataTrigger 
                Binding="{Binding ElementName=detailLevelSlider, Path=Value}" 
                Value="1"&amp;gt;
            &amp;lt;Setter TargetName="lowPresenter" 
                       Property="Visibility" 
                       Value="Visible" /&amp;gt;
          &amp;lt;/DataTrigger&amp;gt;
          &amp;lt;DataTrigger 
                Binding="{Binding ElementName=detailLevelSlider, Path=Value}" 
                Value="2"&amp;gt;
            &amp;lt;Setter TargetName="mediumPresenter" 
                       Property="Visibility" 
                       Value="Visible" /&amp;gt;
          &amp;lt;/DataTrigger&amp;gt;
          &amp;lt;DataTrigger 
                Binding="{Binding ElementName=detailLevelSlider, Path=Value}" 
                Value="3"&amp;gt;
            &amp;lt;Setter TargetName="highPresenter" 
                       Property="Visibility" 
                       Value="Visible" /&amp;gt;
          &amp;lt;/DataTrigger&amp;gt;
        &amp;lt;/DataTemplate.Triggers&amp;gt;
      &amp;lt;/DataTemplate&amp;gt;
      
    &amp;lt;/DockPanel.Resources&amp;gt;
      
    &amp;lt;StackPanel 
      DockPanel.Dock="Bottom" 
      Background="LightGray"
      Margin="4" 
      Orientation="Horizontal"
      &amp;gt;
      &amp;lt;TextBlock 
        Margin="2,0,4,0" 
        Text="Detail Level:" 
        VerticalAlignment="Center" 
        /&amp;gt;
      &amp;lt;Slider 
        x:Name="detailLevelSlider"
        DockPanel.Dock="Bottom" 
        Minimum="1" Maximum="3" 
        SmallChange="1" LargeChange="1" 
        IsSnapToTickEnabled="True" TickFrequency="1"
        Value="0" 
        Width="120" 
        /&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
    
    &amp;lt;ScrollViewer&amp;gt;
      &amp;lt;ItemsControl
        ItemsSource="{Binding Source={StaticResource Data}, XPath=person}"
        ItemTemplate="{StaticResource SelectorTemplate}"
        /&amp;gt;
    &amp;lt;/ScrollViewer&amp;gt;
    
  &amp;lt;/DockPanel&amp;gt;
&amp;lt;/Page&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-5371897452744228567?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=Dcm3vEqdSbI:yFsRQzVplhI:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=Dcm3vEqdSbI:yFsRQzVplhI:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=Dcm3vEqdSbI:yFsRQzVplhI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=Dcm3vEqdSbI:yFsRQzVplhI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=Dcm3vEqdSbI:yFsRQzVplhI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=Dcm3vEqdSbI:yFsRQzVplhI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=Dcm3vEqdSbI:yFsRQzVplhI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=Dcm3vEqdSbI:yFsRQzVplhI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=Dcm3vEqdSbI:yFsRQzVplhI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/Dcm3vEqdSbI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/5371897452744228567/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=5371897452744228567" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5371897452744228567?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/5371897452744228567?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/07/selecting-detail-level-to-view-at.html" title="Selecting the Detail Level to View at Runtime in WPF - An alternate way?" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;AkQEQ305fyp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-4047931089702073412</id><published>2008-06-21T00:14:00.005+01:00</published><updated>2009-01-29T16:58:22.327Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T16:58:22.327Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>Silverlight 2.0 Beta 2 - Update on creating a user control to be used as a base class</title><content type="html">&lt;p&gt;It appears I was wrong in my &lt;a href="http://neilmosafi.blogspot.com/2008/06/silverlight-20-beta-2-creating-user.html"&gt;previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The ContentPropertyAttribute is seemingly ignored!  Although it compiles, and can be edited in Blend, you get a XamlParseException when you try to run it:&lt;/p&gt;

&lt;p&gt;"ShellBase does not support Grid as content"&lt;/p&gt;

&lt;P&gt;The solution is to manually specify the content property in your Xaml (which kind of sucks!).  Strange as this all used to work in Beta 1 (although there were other issues involving namespace parsing which have now been fixed).  The correct Xaml looks like this:&lt;/p&gt;

&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ShellBase&lt;/span&gt;&lt;span style="color: red;"&gt; x&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;Class&lt;/span&gt;&lt;span style="color: blue;"&gt;="Silversocial.Client.Views.Shell"&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;="http://schemas.microsoft.com/client/2007"&lt;/span&gt; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;x&lt;/span&gt;&lt;span style="color: blue;"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;="clr-namespace:Silverstone;assembly=Silverstone"&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ShellBase.Content&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Grid&lt;/span&gt;&lt;span style="color: red;"&gt; Background&lt;/span&gt;&lt;span style="color: blue;"&gt;="#FF000000"&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Grid&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ShellBase.Content&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ShellBase&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I think (hope) this may be a bug but I will try to confirm this and update my blog if I find out any more.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-4047931089702073412?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=iFyHM-R9MAQ:TB-yeQhbT1Q:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=iFyHM-R9MAQ:TB-yeQhbT1Q:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=iFyHM-R9MAQ:TB-yeQhbT1Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=iFyHM-R9MAQ:TB-yeQhbT1Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=iFyHM-R9MAQ:TB-yeQhbT1Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=iFyHM-R9MAQ:TB-yeQhbT1Q:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=iFyHM-R9MAQ:TB-yeQhbT1Q:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=iFyHM-R9MAQ:TB-yeQhbT1Q:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=iFyHM-R9MAQ:TB-yeQhbT1Q:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/iFyHM-R9MAQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/4047931089702073412/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=4047931089702073412" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/4047931089702073412?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/4047931089702073412?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/06/silverlight-20-beta-2-update-on.html" title="Silverlight 2.0 Beta 2 - Update on creating a user control to be used as a base class" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;AkQBQH89eip7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-2321741717613923187</id><published>2008-06-19T00:17:00.008+01:00</published><updated>2009-01-29T16:59:11.162Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T16:59:11.162Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="Browser" /><title>MessageBox.Show in Silverlight</title><content type="html">&lt;p&gt;Well, it's kind of obvious to anyone that has done any browser based Javascript development, but thought this was worth posting for those of you that do a lot of Windows Development and are wondering how to show a &lt;a href="http://msdn.microsoft.com/en-us/library/aa358525.aspx"&gt;MessageBox&lt;/a&gt; in Silverlight.  For those of you that have tried it:&lt;/p&gt;

&lt;pre&gt;MessageBox.Show("Hello world!");&lt;/pre&gt;
&lt;p&gt;OOPS! Compiler error... that doesn't work, Silverlight does not have a &lt;a href="http://msdn.microsoft.com/en-us/library/aa358525.aspx"&gt;MessageBox class&lt;/a&gt; like WPF / WinForms / Win32. Instead, you can ask the browser to do this for you.  How do you do this you might ask?&lt;/p&gt;

&lt;pre&gt;HtmlWindow.Alert("Hello world!");&lt;/pre&gt;
&lt;p&gt;This is the exact equivalent of the javascript alert function, which would look something like this:&lt;/p&gt;

&lt;pre&gt;alert("Hello world!");&lt;/pre&gt;
&lt;p&gt;So what if you want more control?  Well, you will find the browser does not provide quite as much as desktop apps for this.  In WPF, you can control the message, the title, the icon, the colours, buttons and more!  Alert() will simply display a normal dialog with an OK button and the message, and a browser dependent title.  The other option the browser gives you is to display a message box with "OK" and "Cancel" options and to be able to read the result of what the user chooses.  In WPF you would do:&lt;/p&gt;

&lt;pre&gt;DialogResult result = MessageBox.Show("Shall I proceed?", "Title", MessageBoxButtons.OKCancel);
if (result == MessageBoxResult.OK)
{
  // process the OK
}&lt;/pre&gt;

&lt;p&gt;In Silverlight, the equivalent is:&lt;/p&gt;

&lt;pre&gt;bool result = HtmlPage.Window.Confirm("Shall I proceed?");
if (result)
{
  // process the OK
}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-2321741717613923187?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=nOADfoPF4Eo:Ixaimxq5Y8s:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=nOADfoPF4Eo:Ixaimxq5Y8s:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=nOADfoPF4Eo:Ixaimxq5Y8s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=nOADfoPF4Eo:Ixaimxq5Y8s:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=nOADfoPF4Eo:Ixaimxq5Y8s:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=nOADfoPF4Eo:Ixaimxq5Y8s:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=nOADfoPF4Eo:Ixaimxq5Y8s:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=nOADfoPF4Eo:Ixaimxq5Y8s:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=nOADfoPF4Eo:Ixaimxq5Y8s:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/nOADfoPF4Eo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/2321741717613923187/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=2321741717613923187" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/2321741717613923187?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/2321741717613923187?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/06/messageboxshow-in-silverlight.html" title="MessageBox.Show in Silverlight" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;AkMBRHg6eSp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-378158852524865185</id><published>2008-06-17T23:35:00.008+01:00</published><updated>2009-01-29T17:00:55.611Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T17:00:55.611Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>Silverlight 2.0 Beta 2 - Creating a user control to be used as a base class</title><content type="html">&lt;p&gt;Little tip here that I worked out whilst trying to get the ShellBase class from &lt;a href="http://silverstone.googlecode.com"&gt;Silverstone&lt;/a&gt; working in the XAML editor and Expression blend.&lt;/p&gt;

&lt;p&gt;I started off with an abstract class which derived from UserControl, like follows:&lt;/p&gt;

&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ShellBase&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;UserControl&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;IShell&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;//... some code&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, neither Expression Blend nor Visual Studio's Cider designer likes this, they need to create an instance of the base class for some reason.  You get an error message saying it couldn't create an instance of it.  Removing the abstract constraint solves this (though violates OO, but I don't mind in this instance!).&lt;/p&gt;

&lt;p&gt;Now I have some XAML which looks like this for defining my actual Shell:&lt;/p&gt;

&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ShellBase&lt;/span&gt;&lt;span style="color: red;"&gt; x&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;Class&lt;/span&gt;&lt;span style="color: blue;"&gt;="Silversocial.Client.Views.Shell"&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;="http://schemas.microsoft.com/client/2007"&lt;/span&gt; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;x&lt;/span&gt;&lt;span style="color: blue;"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;="clr-namespace:Silverstone;assembly=Silverstone"&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Grid&lt;/span&gt;&lt;span style="color: red;"&gt; x&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;="LayoutRoot"&lt;/span&gt;&lt;span style="color: red;"&gt; Background&lt;/span&gt;&lt;span style="color: blue;"&gt;="Black"&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Grid&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Silverstone&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ShellBase&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;VS and blend now complain because ShellBase does allow content to be added.  The solution I discovered was fairly simple and was twofold:&lt;/p&gt;

&lt;p&gt;1. Add a property called Content which shadows the UserControl's Content property and redirects to it&lt;/p&gt;

&lt;p&gt;2. Add a ContentProperty attribute to the ShellBase which points to the Content property&lt;/p&gt;

&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;ContentProperty&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"Content"&lt;/span&gt;)]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ShellBase&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;UserControl&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;IShell&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  Redefine the base class's content property to keep the designers happy&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;UIElement&lt;/span&gt; Content&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;base&lt;/span&gt;.Content; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;set&lt;/span&gt; { &lt;span style="color: blue;"&gt;base&lt;/span&gt;.Content = &lt;span style="color: blue;"&gt;value&lt;/span&gt;; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;And that's it!  Designer support enabled!&lt;/p&gt;

&lt;p&gt;Hope this helps...&lt;/p&gt;
&lt;p&gt;Neil&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update - 20/06/2008&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It appears I was wrong about the ContentProperty attribute, it doesn't work.  See &lt;a href="http://neilmosafi.blogspot.com/2008/06/silverlight-20-beta-2-update-on.html"&gt;this post&lt;/a&gt; for more info&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-378158852524865185?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=IgSQ6rcSHgA:ekqyUJ2RoAY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=IgSQ6rcSHgA:ekqyUJ2RoAY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=IgSQ6rcSHgA:ekqyUJ2RoAY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=IgSQ6rcSHgA:ekqyUJ2RoAY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=IgSQ6rcSHgA:ekqyUJ2RoAY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=IgSQ6rcSHgA:ekqyUJ2RoAY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=IgSQ6rcSHgA:ekqyUJ2RoAY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=IgSQ6rcSHgA:ekqyUJ2RoAY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=IgSQ6rcSHgA:ekqyUJ2RoAY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/IgSQ6rcSHgA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/378158852524865185/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=378158852524865185" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/378158852524865185?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/378158852524865185?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/06/silverlight-20-beta-2-creating-user.html" title="Silverlight 2.0 Beta 2 - Creating a user control to be used as a base class" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;C0cBR348cSp7ImA9WxdQFUo.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-7013327980330414347</id><published>2008-06-15T23:59:00.001+01:00</published><updated>2008-06-16T00:04:16.079+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-16T00:04:16.079+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverstone" /><title>Silverstone updated for SL 2.0 Beta 2</title><content type="html">Just a quick note to inform that the &lt;a href="http://silverstone.googlecode.com"&gt;Silverstone&lt;/a&gt; project has been updated for Silverlight 2.0 Beta 2.  Get it &lt;a href="http://code.google.com/p/silverstone/downloads/detail?name=Silverstone.0.2.dll"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-7013327980330414347?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=1ASHn1LQRK0:RUrXHXutGpg:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=1ASHn1LQRK0:RUrXHXutGpg:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=1ASHn1LQRK0:RUrXHXutGpg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=1ASHn1LQRK0:RUrXHXutGpg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=1ASHn1LQRK0:RUrXHXutGpg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=1ASHn1LQRK0:RUrXHXutGpg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=1ASHn1LQRK0:RUrXHXutGpg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=1ASHn1LQRK0:RUrXHXutGpg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=1ASHn1LQRK0:RUrXHXutGpg:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/1ASHn1LQRK0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/7013327980330414347/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=7013327980330414347" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/7013327980330414347?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/7013327980330414347?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/06/silverstone-updated-for-sl-20-beta-2.html" title="Silverstone updated for SL 2.0 Beta 2" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEcER387fSp7ImA9WxRbF0U.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-7266827312675253149</id><published>2008-05-19T00:08:00.009+01:00</published><updated>2008-12-09T00:20:06.105Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:20:06.105Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverstone" /><title>MVC Architecting Silverlight Applications Part 3 - Testing the ViewModel</title><content type="html">In &lt;a href="http://neilmosafi.blogspot.com/2008/05/architecting-silverlight-applications.html"&gt;Part 2&lt;/a&gt; of this series, I built a small class used to model our Login page - LoginViewModel.&lt;br /&gt;&lt;br /&gt;In this post, I will demonstrate how to unit test this class to show that it behaves as expected.  This is pretty essential as we want to be sure the class works properly before handing it over to our designer to build a view for!&lt;br /&gt;&lt;br /&gt;I will be using &lt;a href="http://weblogs.asp.net/nunitaddin/archive/2008/05/01/silverlight-nunit-projects.aspx"&gt;TestDriven.NET's new Silverlight unit testing support&lt;/a&gt; which I blogged about &lt;a href="http://neilmosafi.blogspot.com/2008/05/testdrivennet-adds-nunit-support-for.html"&gt;earlier&lt;/a&gt;.  This is unbelievably simple - just download and install the project template and then create a new Silveright NUnit Project called &lt;em&gt;Silversocial.Client.Modules.Test&lt;/em&gt;&lt;br /&gt;&lt;h4&gt;Building some test doubles&lt;/h4&gt;&lt;br /&gt;Before we can start unit testing our LoginViewModel, we need to fake out the dependencies.  Given that there currently exists no mocking framework for Silverlight ( are you listening &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Ayende&lt;/a&gt;? ;-&gt; ) we will manually build some stubs for our dependencies and then reuse them in our tests.&lt;br /&gt;&lt;br /&gt;It is quite easy to way manually to build reusable stubs for an interface of your choosing.  I simply follow these rules:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use "explicit interface implementations" for all members&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implement properties as normal properties with a backing field (or as automatic properties if you'd prefer)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implement methods by delegating the entire method body to a public event handler with the same signature and name as the method.  Set the event handler to empty delegate to avoid null checks&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implement events by delegating the add/remove to a public event handler with the same signature as the event. Set the event handler to empty delegate to avoid null checks&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Here is the code for the stub for the IAppShell interface.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; Silverstone;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules.Tests.Stubs&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;AppShellStub&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;IAppShell&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; user;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IView&lt;/span&gt; view;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; User&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.user; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IView&lt;/span&gt; View&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.view; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IAppShell&lt;/span&gt;.User&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.user; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;set&lt;/span&gt; { &lt;span style="color: blue;"&gt;this&lt;/span&gt;.user = &lt;span style="color: blue;"&gt;value&lt;/span&gt;; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IShell&lt;/span&gt;.SetView(&lt;span style="color: #2b91af;"&gt;IView&lt;/span&gt; view)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.view = view;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;And now the stub for the ILoginDataProvider, also following the guidelines set above:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; System;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules.Tests.Stubs&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginDataProviderStub&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;ILoginDataProvider&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;&amp;gt; validateUserCompleted = &lt;span style="color: blue;"&gt;delegate&lt;/span&gt; { };&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;User&lt;/span&gt;&amp;gt; ValidateUser = &lt;span style="color: blue;"&gt;delegate&lt;/span&gt; { };&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; RaiseValidateUserCompleted(&lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt; args)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.validateUserCompleted(&lt;span style="color: blue;"&gt;this&lt;/span&gt;, args);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;event&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;&amp;gt; &lt;span style="color: #2b91af;"&gt;ILoginDataProvider&lt;/span&gt;.ValidateUserCompleted&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;add&lt;/span&gt; { &lt;span style="color: blue;"&gt;this&lt;/span&gt;.validateUserCompleted += &lt;span style="color: blue;"&gt;value&lt;/span&gt;; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;remove&lt;/span&gt; { &lt;span style="color: blue;"&gt;this&lt;/span&gt;.validateUserCompleted -= &lt;span style="color: blue;"&gt;value&lt;/span&gt;; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ILoginDataProvider&lt;/span&gt;.ValidateUser(&lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; user)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ValidateUser(user);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;We will create a "ViewStubBase" which implements the IView interface itself.  This will form the base class for all other stubs of the views.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; System;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; Silverstone;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules.Tests.Stubs&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ViewStubBase&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;IView&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt; OnLoad = &lt;span style="color: blue;"&gt;delegate&lt;/span&gt; { };&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt; OnUnload = &lt;span style="color: blue;"&gt;delegate&lt;/span&gt; { };&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IView&lt;/span&gt;.OnLoad()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.OnLoad();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IView&lt;/span&gt;.OnUnload()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.OnLoad();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;And now the stub for the ILoginView interface.  As you can see we just implement the LoginUnsuccessful method and call a public event handler which does nothing by default.  The allows the test to listen to the method being called if it wants to, and can for example validate if it is called or not.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; System;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules.Tests.Stubs&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginViewStub&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;ViewStubBase&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;ILoginView&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt; LoginUnsuccessful = &lt;span style="color: blue;"&gt;delegate&lt;/span&gt; { };&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ILoginView&lt;/span&gt;.LoginUnsuccessful()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.LoginUnsuccessful();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;The other views are just empty classes for now.  The first:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules.Tests.Stubs&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;FriendListStub&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;ViewStubBase&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;IFriendListView&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;And the other...&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules.Tests.Stubs&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;RegisterStub&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;ViewStubBase&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;IRegisterView&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;h4&gt;The test fixture&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Finally it's time to implement the test fixture, just using the standard NUnit syntax for defining the tests and setup method.  The SetUp creates all the stubs, so they can be used by each test.&lt;br /&gt;&lt;br /&gt;Note I am using the "AAA" pattern which was &lt;a href="http://www.ayende.com/Blog/archive/2008/05/16/Rhino-Mocks--Arrange-Act-Assert-Syntax.aspx"&gt;recently coined by Ayende&lt;/a&gt; for RhinoMocks 3.5 - I really like it!  This is the way I have written most of my tests in the past, and it's nice to have a formal name for the stages undergone (especially when it's an alliterism)&lt;br /&gt;&lt;br /&gt;Here are the tests:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; NUnit.Framework;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; Silversocial.Client.Modules.Tests.Stubs;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; Silverstone;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules.Tests&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;TestFixture&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginViewModelTester&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginViewStub&lt;/span&gt; loginViewStub;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;AppShellStub&lt;/span&gt; shellStub;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;FriendListStub&lt;/span&gt; friendListStub;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;RegisterStub&lt;/span&gt; registerStub;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginDataProviderStub&lt;/span&gt; dataProviderStub;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginViewModel&lt;/span&gt; viewModel;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;SetUp&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SetUp()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.shellStub = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;AppShellStub&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.friendListStub = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;FriendListStub&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.registerStub = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;RegisterStub&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginDataProviderStub&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginViewModel&lt;/span&gt;(shellStub, dataProviderStub, friendListStub, registerStub);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.loginViewStub = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginViewStub&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ((&lt;span style="color: #2b91af;"&gt;IViewModel&lt;/span&gt;) &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel).SetView(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.loginViewStub);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_WithoutUsernameAndPassword_CannotExecute()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.IsFalse(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.CanExecute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_WithUsernameAndPassword_CanExecute()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Arrange&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.User.Username = &lt;span style="color: #a31515;"&gt;"abc"&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.User.Password = &lt;span style="color: #a31515;"&gt;"abc"&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.CanExecute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_BeforeCompleted_IsLoggingInIsTrue()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.Execute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.IsLoggingIn);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_AfterCompleted_IsLoggingInIsFalse()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.Execute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.RaiseValidateUserCompleted(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;(&lt;span style="color: blue;"&gt;false&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.IsFalse(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.IsLoggingIn);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_AfterCompleted_RaisesCanExecuteChangedEvent()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Arrange&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; canExecuteChangedCalled = &lt;span style="color: blue;"&gt;false&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.CanExecuteChanged +=&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;delegate&lt;/span&gt; { canExecuteChangedCalled = &lt;span style="color: blue;"&gt;true&lt;/span&gt;; };&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.RaiseValidateUserCompleted(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;(&lt;span style="color: blue;"&gt;false&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(canExecuteChangedCalled);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_WhilstLoggingIn_CannotExecute()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Arrange&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.User.Username = &lt;span style="color: #a31515;"&gt;"abc"&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.User.Password = &lt;span style="color: #a31515;"&gt;"abc"&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.IsLoggingIn = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.IsFalse(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.CanExecute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_Always_CallsValidateUserOnDataProvider_WithCorrectUser()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Arrange&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; userSentToDataProvider = &lt;span style="color: blue;"&gt;null&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.ValidateUser += &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; u =&amp;gt; userSentToDataProvider = u;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.Execute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.User, userSentToDataProvider);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_WithInvalidDetails_CallsLoginUnsuccessfulOnView()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Arrange&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.ValidateUser +=&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; u =&amp;gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.RaiseValidateUserCompleted(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;(&lt;span style="color: blue;"&gt;false&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; loginUnsuccessfulCalledOnView = &lt;span style="color: blue;"&gt;false&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.loginViewStub.LoginUnsuccessful +=&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; () =&amp;gt; loginUnsuccessfulCalledOnView = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.Execute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(loginUnsuccessfulCalledOnView);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_WithValidDetails_SetsFriendListViewOnShell()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Arrange&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.ValidateUser += &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; u =&amp;gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.RaiseValidateUserCompleted(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;(&lt;span style="color: blue;"&gt;true&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.Execute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.friendListStub, &lt;span style="color: blue;"&gt;this&lt;/span&gt;.shellStub.View);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Login_WithValidDetails_SetsUserOnShell()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Arrange&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.ValidateUser +=&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; u =&amp;gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProviderStub.RaiseValidateUserCompleted(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;(&lt;span style="color: blue;"&gt;true&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Login.Execute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.User, &lt;span style="color: blue;"&gt;this&lt;/span&gt;.shellStub.User);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Register_Always_SetsRegisterViewOnShell()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Act&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.viewModel.Register.Execute(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Assert&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.registerStub, &lt;span style="color: blue;"&gt;this&lt;/span&gt;.shellStub.View);&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;And here you can see them running in the Resharper test runner - they all pass!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_BrWlEQlsE3c/SDDA5zyPvmI/AAAAAAAAABM/gZlDL7XMSRg/s1600-h/Silversocial+4.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_BrWlEQlsE3c/SDDA5zyPvmI/AAAAAAAAABM/gZlDL7XMSRg/s400/Silversocial+4.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5201869668998954594" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now I can confidently pass my ViewModel to my designer to build a view against...&lt;br /&gt;&lt;br /&gt;Or can I?  Without a data provider, he's going to have problems creating and testing his view.  This will be the subject of the next post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-7266827312675253149?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=VxXCzOrjvx0:TSZfrXv_kU0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=VxXCzOrjvx0:TSZfrXv_kU0:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=VxXCzOrjvx0:TSZfrXv_kU0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=VxXCzOrjvx0:TSZfrXv_kU0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=VxXCzOrjvx0:TSZfrXv_kU0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=VxXCzOrjvx0:TSZfrXv_kU0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=VxXCzOrjvx0:TSZfrXv_kU0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=VxXCzOrjvx0:TSZfrXv_kU0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=VxXCzOrjvx0:TSZfrXv_kU0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/VxXCzOrjvx0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/7266827312675253149/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=7266827312675253149" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/7266827312675253149?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/7266827312675253149?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/05/architecting-silverlight-applications_19.html" title="MVC Architecting Silverlight Applications Part 3 - Testing the ViewModel" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_BrWlEQlsE3c/SDDA5zyPvmI/AAAAAAAAABM/gZlDL7XMSRg/s72-c/Silversocial+4.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;CEcER3ozfCp7ImA9WxRbF0U.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-3451155329517313856</id><published>2008-05-18T18:07:00.005+01:00</published><updated>2008-12-09T00:20:06.484Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:20:06.484Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverstone" /><title>MVC Architecting Silverlight Applications Part 2 - Building a ViewModel</title><content type="html">In &lt;a href="http://neilmosafi.blogspot.com/2008/04/architecting-silverlight-applications.html"&gt;Part 1&lt;/a&gt; of this series I talked about and described the Model-View-ViewModel (MVVM) pattern.&lt;br /&gt;&lt;br /&gt;In this post I will describe the application I wish to build to demonstrate this pattern to you, and at the same time demonstrate usage of the &lt;a href="http://code.google.com/p/silverstone/"&gt;Silverstone framework&lt;/a&gt;.&lt;br /&gt;&lt;h4&gt;A "social networking" application&lt;/h4&gt;&lt;br /&gt;In picking my sample app I wanted to choose something fairly simple.  I decided on a small social networking app, which would basically allow the following use cases:&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Register&lt;/strong&gt; - A user can enter their email address and choose a password.  The user must confirm their password.  Password must be between 4 and 10 characters.  After registering, the user proceeds to use case 3&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Login&lt;/strong&gt; - An existing user can enter their email address and password to login.  If they enter the wrong details the system should inform them that their details were incorrect.  After logging in, the user proceeds to use case 3&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;View Friends&lt;/strong&gt; - Displays a list of friends for the currently logged in user.&lt;/ol&gt;And that's it!  Despite being fairly minimal (and not that useful without being able to add friends or contact them!) that's all I am going to build for now I think.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Creating a solution&lt;/h4&gt;&lt;br /&gt;We will name this application "Silversocial" (not very imaginative I know, but it's only a demo app!)&lt;br /&gt;&lt;br /&gt;You will require Visual Studio 2008, the Silverlight Tools for Visual Studio, and a copy of &lt;a href="http://silverstone.googlecode.com/files/Silverstone.dll"&gt;Silverstone.dll&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Start off by creating a new project of type Silverlight Application named &lt;em&gt;Silversocial.Client.Views&lt;/em&gt;.  Choose to create a new solution and call it &lt;em&gt;Silversocial&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_BrWlEQlsE3c/SCY-bl-nf2I/AAAAAAAAAA0/dqk9kJ8KC-U/s1600-h/Silversocial+1.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_BrWlEQlsE3c/SCY-bl-nf2I/AAAAAAAAAA0/dqk9kJ8KC-U/s400/Silversocial+1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198911463617953634" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Choose to add a new Web to the solution for hosting the Silverlight content, and call it &lt;em&gt;Silversocial_WebHost&lt;/em&gt; (I choose a web application because I prefer them).  The solution will be created containing a Silverlight project and a Web application project.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_BrWlEQlsE3c/SCY-pl-nf3I/AAAAAAAAAA8/odta9RBEBiA/s1600-h/Silversocial+2.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_BrWlEQlsE3c/SCY-pl-nf3I/AAAAAAAAAA8/odta9RBEBiA/s400/Silversocial+2.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198911704136122226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Out of interest, if you right click on the Web Application project properties, you will see a new tab called "Silverlight links" and you will see that the Silverlight application you just created has been added for you automatically.  All this really means is that when you build the Silverlight application, the compiled .xap file will be copied into the Web application's /ClientBin folder.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_BrWlEQlsE3c/SDBUHjyPvlI/AAAAAAAAABE/dEBmI08AxbM/s1600-h/Silversocial+3.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_BrWlEQlsE3c/SDBUHjyPvlI/AAAAAAAAABE/dEBmI08AxbM/s400/Silversocial+3.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5201750058454728274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The shell&lt;/h4&gt;&lt;br /&gt;The shell in a Silverstone application is the central view component which is responsible for managing the other views in the application.  Hence, the IShell interface contains just one method:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;void SetView(IView view)&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Typically an application will implement the shell as the main UI component containing any navigation and common elements for every page (much like ASP.NET's master page).  The application will create its own derived IShell interface and expose any elements required by the individual pages through that interface.&lt;br /&gt;&lt;br /&gt;So, given the requirements specified earlier, our application's shell only requires an extra property - the currently logged in User.  This would allow the shell's view to display the user and allow the other pages to retrieve it when necessary.&lt;br /&gt;&lt;br /&gt;To begin, we will create another Silverlight class project called Silversocial.Client.Modules to house the rest of our application's interfaces and concrete implementations.  Obviously in a larger application you would consider splitting your code into multiple assemblies grouped by role.  &lt;br /&gt;&lt;br /&gt;First, the User class which stores the username and password:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; System.ComponentModel;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;INotifyPropertyChanged&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; username;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; password;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;PropertyChangedEventHandler&lt;/span&gt; PropertyChanged = (s,p) =&amp;gt; {};&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; Username&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.username; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;set&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.username = &lt;span style="color: blue;"&gt;value&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.PropertyChanged(&lt;span style="color: blue;"&gt;this&lt;/span&gt;, &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;PropertyChangedEventArgs&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"Username"&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; Password&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.password; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;set&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.password = &lt;span style="color: blue;"&gt;value&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.PropertyChanged(&lt;span style="color: blue;"&gt;this&lt;/span&gt;, &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;PropertyChangedEventArgs&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"Password"&lt;/span&gt;));&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;And now the shell interface itself:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; Silverstone;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IAppShell&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;IShell&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; User { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;h4&gt;Creating the first ViewModel&lt;/h4&gt;&lt;br /&gt;For now, we will not worry about building a concrete View.  Instead, we will start with our ViewModel.  The page we will build is the Login page, and we will create a new class called LoginViewModel for it.&lt;br /&gt;&lt;br /&gt;ILoginView will be the interface which our View will have to implement, and has a single method as follows:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; Silverstone;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.ViewModels&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ILoginView&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;IView&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; LoginUnsuccessful();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;The contract states that the LoginUnsuccessful() method will be called by the ViewModel if the login is unsuccessful.&lt;br /&gt;&lt;br /&gt;On the other side of the equation, our ViewModel will require some way of actually validating the user.  In the real world application we will expose a service for doing this, but for now, let's stub it out with the following interface:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; System;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;EventArgs&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; ValidateUserCompletedEventArgs(&lt;span style="color: blue;"&gt;bool&lt;/span&gt; successful)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.Successful = successful;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; Successful { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ILoginDataProvider&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;event&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt;&amp;gt; ValidateUserCompleted;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ValidateUser(&lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; user);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;(Note that this interface is implementing an asynchronous pattern - raising the ValidateUserCompleted event when the method has completed.  This ties in well with the fact that Ajax requests are asynchronous, and that Silverlight's WCF ChannelFactory implementation only supports asynchronous requests.)&lt;br /&gt;&lt;br /&gt;The View Model is shown below.  The main features are:&lt;ul&gt;&lt;li&gt;All dependencies passed through as interfaces to the constructor. This includes other views, the data provider, and the shell.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Property exposed for the User, which the View can bind to.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Property exposed for whether we are in the middle of a login attempt, which the View can bind to.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Exposes a Login command which will attempt to use the data provider to validate the user.  If successful the callback will set the user on the shell and change to the FriendListView.  If unsuccessful the callback will call the LoginUnsuccessful() method on the view.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Exposes a Register command which will simply change views to the RegisterView.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="font-family: Courier; font-size: 10pt; color: black; background: white; overflow:auto;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;using&lt;/span&gt; Silverstone;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; Silversocial.Client.Modules&lt;/p&gt;&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  ViewModel for the login page&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginViewModel&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;ViewModelBase&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ILoginView&lt;/span&gt;&amp;gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Dependencies&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IAppShell&lt;/span&gt; shell;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ILoginDataProvider&lt;/span&gt; dataProvider;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IFriendListView&lt;/span&gt; friendListView; &lt;span style="color: green;"&gt;// This is just an empty view interface for now&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IRegisterView&lt;/span&gt; registerView; &lt;span style="color: green;"&gt;// This is just an empty view interface for now&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Commands&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ICommand&lt;/span&gt; login;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ICommand&lt;/span&gt; register;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Data Fields&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; user = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt;();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; isLoggingIn;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; LoginViewModel(&lt;span style="color: #2b91af;"&gt;IAppShell&lt;/span&gt; shell, &lt;span style="color: #2b91af;"&gt;ILoginDataProvider&lt;/span&gt; dataProvider, &lt;span style="color: #2b91af;"&gt;IFriendListView&lt;/span&gt; gameChooserView, &lt;span style="color: #2b91af;"&gt;IRegisterView&lt;/span&gt; registerView)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.shell = shell;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.registerView = registerView;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.friendListView = gameChooserView;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.dataProvider = dataProvider;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.login = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginCommand&lt;/span&gt;(&lt;span style="color: blue;"&gt;this&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.register = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;RegisterCommand&lt;/span&gt;(&lt;span style="color: blue;"&gt;this&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  Gets the user being logged in&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;User&lt;/span&gt; User&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.user; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  Gets or sets whether the user is currently being logged in&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; IsLoggingIn&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; isLoggingIn; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;set&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; isLoggingIn = &lt;span style="color: blue;"&gt;value&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.RaisePropertyChanged(&lt;span style="color: #a31515;"&gt;"IsLoggingIn"&lt;/span&gt;);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  Gets the command used to login the user&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ICommand&lt;/span&gt; Login&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.login; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  Gets the command used to register a new user&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; &lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ICommand&lt;/span&gt; Register&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;span style="color: blue;"&gt;return&lt;/span&gt; register; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LoginCommand&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;CommandBase&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;LoginViewModel&lt;/span&gt;&amp;gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; LoginCommand(&lt;span style="color: #2b91af;"&gt;LoginViewModel&lt;/span&gt; viewModel) : &lt;span style="color: blue;"&gt;base&lt;/span&gt;(viewModel)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.dataProvider.ValidateUserCompleted += &lt;span style="color: blue;"&gt;this&lt;/span&gt;.HandleValidateUserCompleted;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; CanExecute(&lt;span style="color: blue;"&gt;object&lt;/span&gt; parameter)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Used to inform the command framework that we can only login once the user &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// has entered a username and password and we are not already in the middle of a login&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; !&lt;span style="color: blue;"&gt;string&lt;/span&gt;.IsNullOrEmpty(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.User.Username) &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp; !&lt;span style="color: blue;"&gt;string&lt;/span&gt;.IsNullOrEmpty(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.User.Password) &lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp; !&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.IsLoggingIn;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Execute(&lt;span style="color: blue;"&gt;object&lt;/span&gt; parameter)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Call the Async method on the data provider to validate the user.&amp;nbsp; The ViewModel will &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// handle the response to this method&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.dataProvider.ValidateUser(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.User);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Record that we are currently in the middle of a login attempt&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.IsLoggingIn = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HandleValidateUserCompleted(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af;"&gt;ValidateUserCompletedEventArgs&lt;/span&gt; e)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Record that we have finished attempting to log in&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.IsLoggingIn = &lt;span style="color: blue;"&gt;false&lt;/span&gt;;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (e.Successful)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.shell.User = &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.User;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.shell.SetView(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.friendListView);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.View.LoginUnsuccessful();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Raise the "CanExecuteChanged" method&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.RaiseCanExecuteChanged();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;RegisterCommand&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;CommandBase&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;LoginViewModel&lt;/span&gt;&amp;gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; RegisterCommand(&lt;span style="color: #2b91af;"&gt;LoginViewModel&lt;/span&gt; viewModel) : &lt;span style="color: blue;"&gt;base&lt;/span&gt;(viewModel)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Execute(&lt;span style="color: blue;"&gt;object&lt;/span&gt; parameter)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Simply use the shell to navigate to the register view when this command is executed&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.shell.SetView(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ViewModel.registerView);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;&lt;/div&gt;&lt;h4&gt;The next post&lt;/h4&gt;In the next post I will talk about unit testing the view model, and will start to wire things together so our designer can build a View for all this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-3451155329517313856?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=6_yOv4KejGc:HRrcmSi_W18:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=6_yOv4KejGc:HRrcmSi_W18:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=6_yOv4KejGc:HRrcmSi_W18:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=6_yOv4KejGc:HRrcmSi_W18:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=6_yOv4KejGc:HRrcmSi_W18:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=6_yOv4KejGc:HRrcmSi_W18:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=6_yOv4KejGc:HRrcmSi_W18:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=6_yOv4KejGc:HRrcmSi_W18:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=6_yOv4KejGc:HRrcmSi_W18:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/6_yOv4KejGc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/3451155329517313856/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=3451155329517313856" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/3451155329517313856?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/3451155329517313856?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/05/architecting-silverlight-applications.html" title="MVC Architecting Silverlight Applications Part 2 - Building a ViewModel" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_BrWlEQlsE3c/SCY-bl-nf2I/AAAAAAAAAA0/dqk9kJ8KC-U/s72-c/Silversocial+1.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;A0QCRH0-cSp7ImA9WxVQEkk.&quot;"><id>tag:blogger.com,1999:blog-2557671457352222943.post-1323317218019064390</id><published>2008-05-13T23:18:00.006+01:00</published><updated>2009-01-29T17:16:05.359Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-29T17:16:05.359Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>TestDriven.NET adds NUnit support for running Silverlight tests</title><content type="html">&lt;p&gt;This is great news from Jamie Cansdale - &lt;a href="http://weblogs.asp.net/nunitaddin/archive/2008/05/01/silverlight-nunit-projects.aspx"&gt;Silverlight NUnit Projects&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;He has managed to get a plugin working for NUnit which will run tests compiled for Silverlight directly!&lt;/p&gt;

&lt;p&gt;I was previously using the "in-browser" testing framework provided by &lt;a href="http://www.jeff.wilcox.name/2008/03/31/silverlight2-unit-testing/"&gt;Jeff Wilcox&lt;/a&gt;.  As great as this is, it's always nice to be able to run tests directly from the IDE, and this will finally provide it for Silverlight.&lt;/p&gt;

&lt;p&gt;So... it looks like I'm going to have to update my Silverlight samples (which I am in the middle of writing) to use this new plugin.  These are taking longer than expected but will definitely be published soon - and hopefully before I have to update them again for SL Beta 2!&lt;/p&gt;

&lt;p&gt;Oh - and it even works with the Resharper test runner!&lt;/p&gt;

&lt;p&gt;Good work Jamie!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2557671457352222943-1323317218019064390?l=neilmosafi.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=3eULtFIl5o4:NyfpLJ6B3eI:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=3eULtFIl5o4:NyfpLJ6B3eI:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=3eULtFIl5o4:NyfpLJ6B3eI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=3eULtFIl5o4:NyfpLJ6B3eI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=3eULtFIl5o4:NyfpLJ6B3eI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=3eULtFIl5o4:NyfpLJ6B3eI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=3eULtFIl5o4:NyfpLJ6B3eI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?i=3eULtFIl5o4:NyfpLJ6B3eI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/NeilMosafi?a=3eULtFIl5o4:NyfpLJ6B3eI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/NeilMosafi?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/NeilMosafi/~4/3eULtFIl5o4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://neilmosafi.blogspot.com/feeds/1323317218019064390/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=2557671457352222943&amp;postID=1323317218019064390" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1323317218019064390?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2557671457352222943/posts/default/1323317218019064390?v=2" /><link rel="alternate" type="text/html" href="http://neilmosafi.blogspot.com/2008/05/testdrivennet-adds-nunit-support-for.html" title="TestDriven.NET adds NUnit support for running Silverlight tests" /><author><name>Neil Mosafi</name><uri>http://www.blogger.com/profile/15344599241111572695</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05389396362960678849" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
