<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>My Public Interface</title>
	
	<link>http://blog.roboblob.com</link>
	<description>and ideas for its refactoring...</description>
	<lastBuildDate>Sun, 08 Jan 2012 16:21:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/roboblob" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="roboblob" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Why I think Windows Phone is superior phone OS?</title>
		<link>http://blog.roboblob.com/2012/01/08/why-i-think-windows-phone-is-superior-phone-os/</link>
		<comments>http://blog.roboblob.com/2012/01/08/why-i-think-windows-phone-is-superior-phone-os/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 11:29:01 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Windows Phone]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Phone]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=494</guid>
		<description><![CDATA[Let me try to summarize the things i personally love about my new Windows Phone...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<h2>Windows Phone? How did that happen?</h2>
<p>Well over the last couple of months i was experimenting with mobile devices a lot because i was kind of tired of the Desktop and the whole HTML5 madness (yes i don&#8217;t like Java Script that much and i certainly don&#8217;t think its the-way-of-the-future, but that&#8217;s subject for another post).</p>
<p>Out of desperation at first i tried Android and got me a <a href="http://www.gsmarena.com/lg_optimus_one_p500-3516.php" target="_blank">LG Optimus One</a> phone. And I must admit that i liked it very much.</p>
<p>Yes, battery lifetime was problem at start, but installing <a href="http://www.cyanogenmod.com/" target="_blank">CyanogenMod</a> custom ROM completely solved that. I even spent some time programming an Android game but that failed miserably because my productivity was close to zero considering all the new things i needed to learn (Java, Open GL).</p>
<p>And all that time <a href="http://papiri.rs/" target="_blank">one good friend</a> was constantly telling me how great his Windows Phone was. I was very skeptical about that since I previously owned Windows Mobile 6.5 phone  and it was complete failure. I even recall at some time in the past promising to my self that i will never buy Windows powered phone again!</p>
<p>But after hearing all the good things about new Microsoft phone OS I eventually decided to give it a try and got me a <a href="http://www.gsmarena.com/samsung_focus-3453.php" target="_blank">Samsung Focus</a> with Windows Phone Mango installed.</p>
<h3>Boy was i pleasantly surprised.</h3>
<p>And lets be honest here: its not that i did not like Android.  Its good and mature mobile OS.<br />
Its (kind of) Open Source and its has significant market share &#8211; not without good reason.</p>
<p>But using Windows Phone after Android was a really pleasent and refreshing experience. And there is no way I&#8217;m going back.</p>
<p><em><span style="text-decoration: underline;">Disclaimer:</span></em><em> before I continue i want to make few things clear: i don&#8217;t work for Microsoft, and i never did and probably never will. Everything i say on this blog is my personal opinion and not of my neighbors or my dog.</em></p>
<h2>So now let me try to summarize the things i</h2>
<h2>personally love about my new Windows Phone:</h2>
<p><strong> </strong></p>
<ul>
<li><strong>Superb UI </strong>- The whole phone User Interface is absolutely AMAZING!  Its very simple and intuitive.<br />
Yet at the same time it manages to stay slick and beautiful with subtle animations and transitions that do not annoy user but enhance the overall UI experience and make it fun and pleasant.<br />
UI team did a great job &#8211; without any compromises. This is huge win for the platform.</li>
</ul>
<ul>
<li><strong>Live Tiles</strong> &#8211; When we speak of the User Experience I must mention the excellent Live Tiles concept.<br />
Live Tiles are actually just animated squares on your home screen  that represent applications or shortcuts for documents, contacts, URLs or any other static/dynamic piece of information that you can pin and arrange on your mobile &#8216;desktop&#8217;.<br />
They are called Live for a good reason &#8211; they often change their content to show additional information &#8211; like number of emails in inbox for email application Live Tile, current temperature for weather app Live Tile etc.<br />
I like this because it works great for the limited screen space of the phone &#8211; each of the tiles can show more info by flipping to display live content as it becomes available/relevant.</li>
</ul>
<ul>
<li><strong>The phone </strong><a href="http://c2.com/cgi/wiki?ItJustWorks" target="_blank"><strong>Just Works</strong></a> &#8211; From the practical everyday usage perspective the OS feels very natural and in 99% of cases works exactly as you think it will.<br />
I have to admit that i never expected this from Microsoft but the whole Windows Phone is so well planed and designed that its never in the way when you are using it. One good example is how built-in music player works with non-standard headphones.<br />
I tried plugging in the headphones from my old Android phone (it’s a different manufacturer) and I was able to control music playback by pressing the hardware button on the headphones, one press for play/pause, double press to skip current track. Yes I know this is minor and expected thing, but  remember i found this out just by trying and expecting that it should work, and it &#8216;just worked&#8217;  even with non-supported headphones.<br />
And when you use the phone you often catch yourself thinking &#8216;Wow this works just as I expected it to work&#8217;. After few moments like that and I was already bought.</li>
</ul>
<ul>
<li><strong>General Email experience</strong> is great! In my opinion its superior when compared to the built in email clients on IPhone or  Android. And I don’t mean just MS Exchange email.<br />
I&#8217;m a long time Google Mail user and i don&#8217;t use Exchange Server at all. So i was little worried how this will work with MS phone &#8211; but without any reason.Gmail works flawlessly out of the box without ANY additional  apps or customizations. I  just added my Google account and it worked. Even the push notifications worked without a single glitch. It also synced my Google Email Contacts and Google Calendar  in expected way, no fuss.</li>
</ul>
<ul>
<li><strong>Built in keyboard is great!</strong> Unlike Android you cannot replace keyboard with 3rd party replacement, but there is really no reason for you to do so any way.<br />
Default keyboard flawlessly supports multiple languages &#8211; I&#8217;m using English and Czech settings and i can enter all the Czech special characters very easily (they appear by long pressing the keys &#8211; as expected).<br />
Actually I&#8217;m deliberately writing this post on the phone using that same keyboard just to prove the point (therefore don’t mind my spelling, please).<br />
<strong>Copy and paste</strong> works very nice and another thing i like is the <strong>caret repositioning</strong> &#8211; just by long pressing the screen and then moving the caret around &#8211; i would love to see this working so nice on Android.</li>
</ul>
<ul>
<li><strong>Multitasking</strong> experience is very nice at least in the Mango Windows Phone version that i have.<br />
Actually there is no real multitasking (if you exclude the occasional background data sync) because only one app is active at the moment. Others are &#8216;<a href="http://msdn.microsoft.com/en-us/library/ff817008(v=vs.92).aspx" target="_blank">tombstoned</a>&#8216; until you activate them.<br />
But there is very nice illusion of multitasking that does the job pretty well.<br />
By long pressing the Back hardware button you get on the screen very cool visual &#8216;Task Manager&#8217; where you can see list of your app screens which you can scroll through and choose which app you want to activate now.<br />
Simply brilliant.<br />
On the other hand Android has true multitasking but list of running apps is hidden in phone settings and not so slick at all.</li>
</ul>
<ul>
<li><strong>Phone and SMS functionality</strong> &#8211; Simple, quick and feature rich yet not in your way when you want to do quick call or SMS somebody. And I could hardly say that for Android or IPhone. Very impressive.</li>
</ul>
<ul>
<li><strong>TextToSpeech and SpeechToText</strong> &#8211; Windows Phone has pretty decent voice recognition and when you use wireless or wired headsets you can set it up so that it reads you your SMS messages and you can reply to them over voice command and then dictate your answer. Have a look at this <a href="http://www.zdnet.com/blog/hardware/windows-phone-75-mango-killer-feature-voice-to-text/14072" target="_blank">Windows Phone voice commanding demo</a> if you want to know more. Yes i know its not <a href="http://www.apple.com/iphone/features/siri.html" target="_blank">Siri </a>and it can be much better but even as it is now is quite usable if you are native English speaker.</li>
</ul>
<ul>
<li><strong>Marketplace</strong> &#8211; Even though there are less apps then for other platforms, there are enough of them and number is growing so time will fix that. But generally speaking Marketplace is already mature and useful.</li>
</ul>
<ul>
<li><strong>Social Networks integration</strong> is flawless. Again without any third party tools.<br />
Facebook, Twitter, LinkedIn you name it. Its all integrated into People hub on the phone, so you can merge Facebook account with your SIM card phone contact to use it as his/hers account picture etc.</li>
</ul>
<ul>
<li>do i need to mention that <strong>phone integrates nicely with desktop MS Office?</strong> OneNote, Word, Excel it works as good as it can get on a mobile device. I don&#8217;t use it too much except for OneNote but i think its huge win for corporate users.</li>
</ul>
<ul>
<li><strong>Built in Music Player and Radio app are great</strong> and i enjoy using them for they simplicity and stability. Not a single crash. Try that on android device and good luck trying!</li>
</ul>
<ul>
<li>One big advantage of Windows Phone for<strong> .NET</strong> software developers especially for <strong>Silverlight</strong> folks is that programming Windows Phone is very familiar experience.  Visual Studio has very good support for phone development and Emulator for Windows Phone is in my personal opinion much better and faster then Android one. (Off course one could say I am biased since I&#8217;m .NET developer but speed is something that is easily measurable).<br />
If you have .NET background you can start app development or XNA game development in no time.<br />
And the Marketplace is not overcrowded. Anyone mentioned word <strong>Opportunity</strong>?</li>
</ul>
<ul>
<li>Another small thing that can be a lifesaver is the <strong>phone boot time</strong>.<br />
My Samsung Focus boots in 20 seconds and its immediately ready to make phone calls or to write SMS.<br />
My Android device was not even close to that and even when it was booted it remained to be slow for some time, probably until Micro SD card is initialized and until all the services are up and running.<br />
Sometimes when you need to make an urgent call this can be really important feature.</li>
</ul>
<ul>
<li>Every Windows Phone has built in<strong> </strong><a href="https://www.windowsphone.com/en-US/find" target="_blank"><strong>Find My Phone</strong></a> feature that allows you (if you enable it) to see on the map where is your phone and to start the Ringing on the phone, Lock it or Erase it (off course it needs to be connected on the network for this to work).<br />
This is useful if you lose your phone, or if it gets stolen. I&#8217;m not sure about IPhone but I know that on Android you need to install third party apps for this so this is another nice benefit of this platform.</li>
</ul>
<ul>
<li><strong>Battery</strong><strong> Saver</strong> &#8211; if enabled phone automatically switches to power saving mode when battery is low (stops background sync for example)  and your phone calls and SMS functionality continues to work until there is juice in the battery. I really like this because after all this is a phone device so my calls are more important then my Facebook updates <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<ul>
<li><strong>Lock Screen</strong> on Windows Phone is beautiful. It is following the general minimalistic approach but still manages to show all the relevant information &#8211; calendar items, missed calls, messages, emails etc. If you are playing some music there are small controls there.<br />
All in all very nice without unnecessary bells and whistles.</li>
</ul>
<p>I could continue like this for some times because there are many other nice things that deserve mention.</p>
<h4>But at the same time this is young phone platform so there are also some problems to be addressed.</h4>
<p>The biggest issue I currently see for Windows Phone is that its not open enough for developers. Many OS features are exclusively used only by OS apps and by Vendors apps and everyday developers don’t have APIs to access them. Much has been written on the subject so I wont repeat it here, so read the post <a href="http://www.orktane.com/post/2011/02/11/From-a-Developers-Perspective-10-ways-to-improve-Windows-Phone-7.aspx" target="_blank">10 ways to improve Windows Phone 7</a> if you are interested or <a href="http://www.orktane.com/post/2010/09/26/WP7-Extensibility-Rant.aspx" target="_blank">WP7 Extensibility Rant</a> from same author.</p>
<p>Typical example is that in 3rd party apps you cannot subscribe to some user invoked actions, for example <a href="http://stackoverflow.com/questions/8562005/how-to-subscribe-to-get-sharelinktask-notifications-in-windows-phone-mango" target="_blank">there is no way for user to send url to non system application</a>.</p>
<p>I dont see anyone benefiting from this kinds of limitations.</p>
<p>I really hope that Windows Phone team will address these problems and give developers more power.</p>
<p>There is <a href="http://wpdev.uservoice.com/forums/110705-app-platform" target="_blank">WPDev User Voice Feedback site</a> where all the requests from the developer community are listed &#8211; so there is hope this will change soon.</p>
<p>Another thing I don’t like is that for some settings there is no quick way of access.<br />
For example WiFi or Flight Mode. In order to manipulate them you need to go to System Settings and choose menu item  and then switch them on or off. Instead of this hassle I would like to have quick toggle button somewhere on the phone desktop.</p>
<p>Again this is something that would be solved if developers could have access to those settings to programmatically manipulate them.</p>
<p>I guess Microsoft do not want to open the Pandora&#8217;s Box by giving  too much power to 3rd party apps, but I think they over did it in this case.</p>
<p>Right balance between opennes and system security on Windows Phone needs yet to be determined.</p>
<p>I would also love to see support for more languages for Text To Speech and Voice Recognition. Im not sure abut Microsoft plans but this would be a killer feature since i think voice is the way to go when it comes to the future of mobile platforms.</p>
<h4>Wow this was longer post that I originally intended it to be!</h4>
<p>I hope I was able to explain why I personally choose Windows Phone over other modern phone platforms.</p>
<p>Then again, this is all my personal experience and your mileage may vary.</p>
<p>It all depends on what you expect from your phone:</p>
<ul>
<li>If you want to pay for Brand, then simply buy IPhone.</li>
<li>If you want phone that does everything you want and that is completely customizable yes often fails because its complex and bloated with unstable apps &#8211; get Android.</li>
<li>if you just wont cool phone that dont stand in your way but does all things you really could need from mobile device &#8211; i recommend Windows Phone</li>
</ul>
<p>I don’t really expect my phone to be Swiss army knife capable of EVERYTHING but failing to do anything efficiently.</p>
<p>I like minimalistic approach and simplicity so probably this is why I like Windows Phone so much.</p>
<p>But the war of the platforms is still on so don’t be surprised if tomorrow I choose another <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Those were my 2 cents on the subject, let me know what&#8217;s your experience and what is your best mobile OS out there, and most importantly: WHY?</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F&amp;title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F&amp;title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F&amp;title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F&amp;headline=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F&amp;title=Why+I+think+Windows+Phone+is+superior+phone+OS%3F+&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2012%2F01%2F08%2Fwhy-i-think-windows-phone-is-superior-phone-os%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/0EJqtIAvzKc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2012/01/08/why-i-think-windows-phone-is-superior-phone-os/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lighthouse – Silverlight Unit Test Runner Project released</title>
		<link>http://blog.roboblob.com/2011/03/22/lighthouse_silverlight_unit_test_runner_project_released/</link>
		<comments>http://blog.roboblob.com/2011/03/22/lighthouse_silverlight_unit_test_runner_project_released/#comments</comments>
		<pubDate>Mon, 21 Mar 2011 23:27:45 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[Lighthouse]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[UnitTest]]></category>
		<category><![CDATA[UnitTesting]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=479</guid>
		<description><![CDATA[Unit Testing in Silverlight? But you need Web Browser to do that! No you do not! Ok maybe you do. But not in a direct way. I will clarify that later. Lets first go back in time to the root of the story: Since the initial release of Silverlight i was really annoyed by the [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<h2>Unit Testing in Silverlight? But you need Web Browser to do that!</h2>
<p>No you do not! Ok maybe you do. But not in a direct way. I will clarify that later. Lets first go back in time to the root of the story:</p>
<p>Since the initial release of Silverlight i was really annoyed by the fact that Unit Testing had very slim support.</p>
<p>Even later <a href="http://archive.msdn.microsoft.com/silverlightut" target="_blank">when Silverlight Unit Testing Framework</a> was introduced by Microsoft things became little better but still it was far from good.</p>
<p>You could create Unit Tests, but you had to start your Visual Studio in order to run them &#8211; eventually looking at the results of tests in your favorite Web Browser.</p>
<p>That ruled out one of the most important facets of <strong>T</strong>est <strong>D</strong>riven <strong>D</strong>evelopment &#8211; running your Unit Test on Continuous Integration server, so that you can easily see when any of your Unit Tests are broken &#8211; in other words treating your Unit Tests equally as all your code, like you should.</p>
<p>Not to mention that there was no way to run Unit Tests from Reshaper! (oh boy don&#8217;t even let me get started on that one).</p>
<h2>Can feeling of anger be a motivation for good deeds?</h2>
<p>Very likely. I started by investigating what open source projects were available to fill these Silverlight TDD gaps.</p>
<p>And i did found few of them. But they were either too complex or simply did not work properly and failed to run tests from one reason or the other.</p>
<p>This is how i decided to create project <strong>Lighthouse</strong> &#8211; probably in same way how many other open source projects are born: <strong>to scratch an itch</strong> of single developer, for the benefit of the community <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>What is it for? What&#8217;s the Roadmap?</h2>
<p><a href="http://lighthouse.codeplex.com/" target="_blank">Lighthouse</a> is envisioned as project that will host multiple tools that will allow Silverlight developers to do Test Driven Development much easier then before.<br />
First tool in this project <a href="http://lighthouse.codeplex.com/releases/view/62936" target="_blank">Silverlight Command Line Unit Test Runner</a> has just been released on Codeplex website.</p>
<p>Lighthouse Command Line Unit Test Runner is console application that runs given <a href="http://archive.msdn.microsoft.com/silverlightut" target="_blank">Silverlight Unit Testing Framework</a> Unit Tests and collects their results and saves them in known ﻿<a href="http://www.nunit.org/wiki/doku.php?id=dev:specs:xml_formats&amp;s[]=xml" target="_blank">NUnit XML Unit Tests results file format</a> on your hard-drive.</p>
<h2>What can i expect?</h2>
<p>The rule of the thumb goes like this:</p>
<p><strong>YOUR SILVERLIGHT UNIT TESTS SHOULD BEHAVE EXACTLY THE SAME WHEN YOU RUN THEM WITH LIGHTHOUSE AS IF YOU ARE RUNNING THEM FROM VISUAL STUDIO OR WEB BROWSER.</strong></p>
<p>In other words: If they failed in browser, they will fail when you run them via Lighthouse in completely same way (same timing, same exception etc) &#8211; and vice versa.</p>
<p>You can use Lighthouse to run tests in XAP packaged application or you can use it to run tests directly specifying your Silverlight DLL&#8217;s &#8211; it is very flexible.</p>
<p>Currently Lighthouse saves results in NUnit XML Unit Tests results file format so that means<strong> you can use it to run your Unit Tests in ANY Continuous Integration server</strong> that supports this format &#8211; <a href="http://sourceforge.net/projects/ccnet/" target="_blank">CCNet</a>, <a href="http://www.jetbrains.com/teamcity/" target="_blank">Team City</a> you name it.</p>
<p>In future we will maybe add more output XML formats, but for start this should suffice.</p>
<p>Lighthouse Silverlight Command Line Unit Tests runner supports variety of command line switches so you can tweak it to work how you need it.</p>
<p>You can specify Tag Filter to run only certain test cases.</p>
<p>You can specify timeouts, output log file, output directory etc.</p>
<p>Make sure you visit the <a href="http://lighthouse.codeplex.com/wikipage?title=Lighthouse_Command_Line_Runner_Parameters_Documentation" target="_self">Lighthouse Command Line Test Runner Documentation</a> page to get familiar with all the options.</p>
<p>In the future we are planning to develop Resharper plugin to run Silverlight Unit Tests, but you will here more on that when its ready.</p>
<h2>And how does all this work?</h2>
<p>Its much simpler to explain then it was to make it work:</p>
<p>In its essence, Lighthouse analyzes your XAP/Assemblies and modifies them in a way so that it can control the Unit Test execution. It then fires up a web browser instance in the background and start this modified Silverlight application and collects the results of all Unit Tests. Results are saved in XML file and everyone go home and live happily ever after.</p>
<h2>What now?</h2>
<p>Until future releases I&#8217;m asking all interested Silverlight developers to use Lighthouse and <a href="http://lighthouse.codeplex.com/workitem/list/basic" target="_blank">send us feedback</a> or even join the <a href="http://lighthouse.codeplex.com/team/view" target="_blank">Lighthouse team</a> to make it better.</p>
<p>For the end check out this short video where Lighthouse Command Line Runner executes Silverlight Unit Tests from <a href="http://sterling.codeplex.com/" target="_blank">Sterling</a> project:</p>
<p>http://www.youtube.com/watch?v=MhBarClpvp8</p>
<p>Stay tuned&#8230;</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F&amp;title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F&amp;title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F&amp;title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F&amp;headline=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F&amp;title=Lighthouse+-+Silverlight+Unit+Test+Runner+Project+released&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F03%2F22%2Flighthouse_silverlight_unit_test_runner_project_released%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/y8EnHaWG3WI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2011/03/22/lighthouse_silverlight_unit_test_runner_project_released/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Microsoft Silverlight 4 Certification, is it worth the ride?</title>
		<link>http://blog.roboblob.com/2011/02/24/microsoft-silverlight-4-certification-is-it-worth-the-ride/</link>
		<comments>http://blog.roboblob.com/2011/02/24/microsoft-silverlight-4-certification-is-it-worth-the-ride/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 22:31:19 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[Certification]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Exam]]></category>
		<category><![CDATA[Microsoft]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=463</guid>
		<description><![CDATA[Now some good news folks: I received the confirmation that I successfully passed the Silverlight 4 Microsoft Certification. I was too busy to immediately brag about it and write a show-off post so I will here just quickly share my thoughts on how all this went before my brain moves these impressions to non-accessible-memory-banks-prepared-for-deletion. First of [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<div id="attachment_459" class="wp-caption alignleft" style="width: 286px"><a href="http://blog.roboblob.com/wp-content/uploads/2009/12/MCTSrgb_1401.jpg"><br />
<img class="size-full wp-image-459 " title="Roboblob's Silverlight 4 Microsoft Certificate" src="http://blog.roboblob.com/wp-content/uploads/2009/12/MCTSrgb_1401.jpg" alt="Roboblob's Silverlight 4 Microsoft Certificate" width="276" height="80" /></a><p class="wp-caption-text">Silverlight 4 Microsoft Certificate</p></div>
<p>Now some good news folks: I received the confirmation that I successfully passed the <a title="Silverlight 4 Microsoft Certification" href="http://www.microsoft.com/learning/en/us/exam.aspx?ID=70-506" target="_blank">Silverlight 4 Microsoft Certification</a>.</p>
<p>I was too busy to immediately brag about it and write a show-off post so I will here just quickly share my thoughts on how all this went before my brain moves these impressions to non-accessible-memory-banks-prepared-for-deletion.</p>
<p>First of all I must admit that I was pretty sceptical about the whole certification thing. I&#8217;m not big fan of certifications in general and I find it a bit overrated &#8211; who cares about fancy printouts people are framing on their walls. You either know how to do your job or you don&#8217;t and some poster with Microsoft stamp on it wont change that in any way.</p>
<p>But at that time (it was 3 months ago) Silverlight 4 Exam was beta test (you could take it for free) and in that period of time I was switching my corporate job to become a full time Silverlight developer so this seemed like perfect opportunity to test my knowledge &#8211; and I applied.</p>
<p>Honestly I did not had enough time to prepare for the test &#8211; even though I was planning to do so. Simply could not find the time or strength to study and eventually I had to go for a test without any especial preparations &#8211; all I had was my hands-on experience in writing Silverlight code and few books I have read on the subject along the way.</p>
<p>Naturally I expected lots of theory mumbo-jumbo in the test so I was sure I will fail-fast <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>But to my surprise the test was mainly pragmatic with questions from real-world Silverlight programming practice so it turned out I did pretty good after all.</p>
<p>It was interesting that some parts of the test required knowledge of MVVM pattern &#8211; just as if they asked me what to put there <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>All in all test turned out to be more serious and realistic than I expected so this is +1 for old Microsoft.</p>
<p>In case any one of you want to take the test and don&#8217;t know how to prepare I have two things I could recommend:</p>
<ol>
<li>read THE book: <a title="Silverlight 4 In Action on Amazon.com" href="http://www.amazon.com/Silverlight-4-Action-Pete-Brown/dp/1935182374" target="_blank">Pete Brown&#8217;s Silverlight 4 In Action</a> &#8211; Its the best Silverlight book I have read so far and covers most of the knowledge needed for the exam.</li>
<li>Mark Monster also participated in the Beta Silverlight 4 testing and <a title="Mark Monster blog post on Silverlight 4 exam preparations" href="http://mark.mymonster.nl/2010/10/25/exam-preparationsilverlight-4-development70-506part-1/" target="_blank">blogged</a> about how he was preparing for it so this is also worth reading.</li>
</ol>
<p>All in all this was fun ride, and now I&#8217;m looking forward to Silverlight 5 Certification announcements <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F&amp;title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F&amp;title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F&amp;title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F&amp;headline=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F&amp;title=Microsoft+Silverlight+4+Certification%2C+is+it+worth+the+ride%3F&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2011%2F02%2F24%2Fmicrosoft-silverlight-4-certification-is-it-worth-the-ride%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/CCB4Y4p0HgM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2011/02/24/microsoft-silverlight-4-certification-is-it-worth-the-ride/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Introducing the Prism Navigation Framework for Silverlight MVVM Applications</title>
		<link>http://blog.roboblob.com/2010/10/24/introducing-prism-navigation-framework-for-silverlight-mvvm-applications/</link>
		<comments>http://blog.roboblob.com/2010/10/24/introducing-prism-navigation-framework-for-silverlight-mvvm-applications/#comments</comments>
		<pubDate>Sun, 24 Oct 2010 16:03:56 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Prism Navigation Framework]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[inavigationframework]]></category>
		<category><![CDATA[navigation]]></category>
		<category><![CDATA[Prism]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=427</guid>
		<description><![CDATA[After receiving a lot of positive feedback and requests for source code for my previous post on Prism navigation i decided to release the code i had as open source project.
This is how Prism Navigation Framework project was born...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<h1>Another framework? But why?</h1>
<p>After receiving a lot of positive feedback and requests for source code for <a title="Combining Silverlight Navigation Framework and Prism to create MVVM Applications – Introduction" href="http://blog.roboblob.com/2010/10/15/combining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction/" target="_blank">my previous post on Prism navigation</a> i decided to release the code i had as open source project.</p>
<p>This is how <a title="Prism Navigation Framework project homepage" href="http://prismnavigation.codeplex.com/" target="_blank">Prism Navigation Framework</a> project was born.</p>
<p>My intention was to create simple-to-use but powerful-and-feature-full Navigation Framework for building Silverlight MVVM applications with <a title="Microsoft Patterns and Practices Team - Prism " href="http://compositewpf.codeplex.com/" target="_blank">Prism</a>.</p>
<p>This is the first introductory post (from series of planned similar posts) that will try to explain what this Navigation Framework for Prism can do to make your life as developer easier.</p>
<p>If you are too anxious to read the whole article you can just open the <a title="Sample Silverlight Navigation Application Application" href="http://demos.roboblob.com/Silverlight4/PrismNavigationFramework/Beta1Demo/" target="_blank">Sample Silverlight Navigation Application Application</a> (for the Beta 1 version of the Framework) and try out some of the features and then read on if you find it to be interesting (in the demo you can see loading Views and their ViewModels to Prism Regions, visual transitions when loading Views, Browser URL and History integration &#8211; deep linking, deferred module loading, passing parameters to views etc).</p>
<p>If you are interested in the source of the Prism Navigation Framework and the Sample Application shown here you can download it on the <a title="Prism Navigation Framework downloads" href="http://prismnavigation.codeplex.com/releases/" target="_blank">Downloads section on the project site</a>.</p>
<p><span style="color: #ff0000;">Note:</span> Its important to say here that in this post I will not try to explain in detail how <a title="Microsoft Patterns and Practices Team Prism" href="http://compositewpf.codeplex.com/" target="_blank">Microsoft Patterns and Practices Team Prism</a> works &#8211; you must already be familiar with it, and if you never used it to develop Silverlight or WPF MVVM applications, i recommend you to try it out, also make sure to check <a title="Prism Documentation" href="http://compositewpf.codeplex.com/wikipage?title=Getting%20Started&amp;referringTitle=Home" target="_blank">Prism excellent documentation</a> if you need to refresh your memory.</p>
<h1>Basic Concepts</h1>
<p><span style="text-decoration: underline;">Since <strong>Prism Navigation Framework</strong> is based on the Prism guidance, naturally it is leaning on and reusing all of Prism main concepts:</span></p>
<ul>
<li><strong>Modules &#8211; </strong>packages of application functionality (packaged as .dll or .xap) &#8211; they can be loaded immediately on application start or on demand (so called deferred module loading) &#8211; this framework completely supports loading of modules implicitly or explicitly.</li>
<li><strong>Views </strong>and their <strong>ViewModels </strong>that are packaged in those Modules (each View has its ViewModel set as value of its <a title="DataContext on MSDN" href="http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.datacontext(VS.95).aspx" target="_blank">DataContext</a> property) &#8211; this framework allows you to register Views and their ViewModels and then easily load them in many ways, initialize them with parameters etc.</li>
<li><strong>Regions </strong>- are actually Controls that are used as placeholders on the Views where you can load content &#8211; other Views of the application &#8211; this framework supports Regions and extends them in practical way &#8211; read more below.</li>
</ul>
<h1>One Region To Rule Them All</h1>
<p>If you ever built Prism applications you know that by convention each Prism application has one Main View &#8211; called the &#8216;<strong>ShellView</strong>&#8216;.</p>
<p>Shell View is created on the application start and loaded to represent the main screen of the application.</p>
<p>This main View has multiple Regions &#8211; this is where you can load your Views.</p>
<p><span style="text-decoration: underline;"><strong>Prism Navigation Framework</strong> takes Prism&#8217;s concept of Regions a little further and defines two types of regions:</span></p>
<ol>
<li><strong>Single Main Region</strong> &#8211; there is only one Main Region in the Application and its usually large region in the center of the Shell View. This Region is meant to be placeholder where we will load other Views &#8211; <strong>Pages </strong>of the Application with the main content. Only one View can be shown in Main Region at one time. This region is represented by dropping instance of <strong><a title="PrismNavigationMainFrame" href="http://prismnavigation.codeplex.com/SourceControl/changeset/view/58210#1299188" target="_blank">PrismNavigationMainFrame</a> </strong>control in your ShellView and setting its RegionName.</li>
<li><strong>Multiple Secondary Regions</strong> &#8211; represented by <strong><a title="PrismNavigationSecondaryFrame Control" href="http://">PrismNavigationSecondaryFrame</a> </strong>control - you can place as many of them as you like in the Shell View and load any of application Views into any of those Secondary Regions &#8211; Secondary Region can (unlike the Main Region) show multiple Views at the same time (widgets, control etc).</li>
</ol>
<p>Here is how you would add the single Main Region to your Shell View:</p>
<pre class="brush: xml; title: ; notranslate">
                    &lt;Controls:PrismNavigationMainFrame cal:RegionManager.RegionName=&quot;MainRegion&quot; /&gt;
</pre>
<p>And here is how you can add multiple Secondary Regions:</p>
<pre class="brush: xml; title: ; notranslate">
                    &lt;Controls:PrismNavigationSecondaryFrame cal:RegionManager.RegionName=&quot;WidgetsRegion&quot; /&gt;

                    &lt;Controls:PrismNavigationSecondaryFrame cal:RegionManager.RegionName=&quot;OpenedDocumentsRegion&quot; /&gt;
</pre>
<h1>Loading Views</h1>
<p>We have seen how we can define Main and Secondary Regions so lets see what are our options for loading our Views into those Regions:</p>
<ol>
<li><span style="text-decoration: underline;">First and most useful way to load View into Main region is by typing meaningful URLs in the Browser</span>. Our Framework supports <a title="Convention over configuration" href="http://en.wikipedia.org/wiki/Convention_over_configuration" target="_blank">convention over configuration</a> so some defaults work out of the box, for example if you have View control called <strong>DetailsView </strong>in Module called <strong>ProductsModule</strong>, then to load this DetailsView into the Main Region of the application just point your browser to this URL:   http://yourapplication.com/index.html#/Products/Details/ (Off course you can pass parameters through the url like this: http://yourapplication.com/index.html#/Products/Details/ProductId/1234  or http://yourapplication.com/index.html#/Products/Details/)</li>
<li><span style="text-decoration: underline;">you can also use standard Silverlight HyperlinkButton control and its <strong>NavigateUri </strong>property</span> to specify URL of the View you want to load (for example &#8220;/Products/Details/Id/1&#8243;) and its <strong>TargetName </strong>property to specify to which Region you want View to be loaded</li>
<li>and <span style="text-decoration: underline;">from your code in ViewModel use the framework&#8217;s <strong><a title="IPrismViewLoadingService " href="http://prismnavigation.codeplex.com/SourceControl/changeset/view/58210#1299183" target="_blank">IPrismViewLoadingService</a> </strong>and load Views to any Region in multiple ways</span>: by specifying the <strong>View type</strong>, or <strong>View interface</strong> <strong>type</strong> or just a <strong>string name of the View</strong> &#8211; choice is on you (more on that later). Its important to mention here that when view is loaded via URL &#8211; Prism Navigation Framework automatically checks from the URL what is the name of its Module and loads the module if its not already loaded before loading the View, but more on that later.</li>
</ol>
<h1>Modules And How They Relate To Their Views And ViewModels</h1>
<p>Now that we covered how to load Views, <span style="text-decoration: underline;">lets see how the Views and ViewModels are defined, created, registered and initialized in your MVVM application done with Prism Navigation Framework:</span></p>
<p>Views and ViewModels are in Prism applications packaged in <strong>Modules </strong>- each module is Silverlight Library (packaged in .dll) or Silverlight Application (packaged in .XAP) that supports some application functionality.</p>
<p>View is usually a UserControl that is just a visual representation of the functionality and its bound to its ViewModel for the data and application logic.</p>
<p>Each module in Prism has to implement <strong><a title="Prism Module documentation" href="http://msdn.microsoft.com/en-us/library/ff921157(v=PandP.20).aspx" target="_blank">IModule</a></strong> interface and it contains <strong>InitModule </strong>method that is called by the Prism when the Module is loaded.</p>
<p>This is where you need to register your Views and ViewModels so that Prism Navigation Framework can help you instantiate them and load them into Regions.</p>
<p>So here is how your typical Module initialization would look like:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class InitModule : IModule
    {
        private readonly IViewRegistrationService _viewRegistrationService;

        public InitModule(IViewRegistrationService viewRegistrationService)
        {
            _viewRegistrationService = viewRegistrationService;
        }

        public void Initialize()
        {
            this._viewRegistrationService.RegisterViewsAndTheirViewModels();
        }
    }
</pre>
<p>This is possible because each <strong>ViewModel </strong>needs to inherit the generic type ViewModel&lt;IView&gt; and therefore carries the type (or interface) its View.</p>
<p>This way <strong>RegisterViewsAndTheirViewModels </strong>method can automagically scan the calling Assembly and look for the types that inherit ViewModel&lt;TView&gt; and registers them for you.</p>
<p>Here is how typical ViewModel definition looks like if you tie your ViewModel to the View interface type:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class IndexViewModel : ViewModel&lt;IIndexView&gt;
    {

    }
</pre>
<p>But off course you can also tie your ViewModel directly to the View type if you want (but i don&#8217;t recommend that you do this, tying ViewModel to View interface is much cleaner):</p>
<pre class="brush: csharp; title: ; notranslate">
    public class IndexViewModel : ViewModel&lt;IndexView&gt;
    {

    }
</pre>
<p>Naturally, nothing stops you from manually registering your Views and ViewModels in your Module initialization like this:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class InitModule : IModule
    {
        private readonly IViewRegistrationService _viewRegistrationService;

        public InitModule(IViewRegistrationService viewRegistrationService)
        {
            _viewRegistrationService = viewRegistrationService;
        }

        public void Initialize()
        {
            this._viewRegistrationService.RegisterViewAndViewModel&lt;IUserDetailsView, UserDetailsViewModel&gt;();
        }
    }
</pre>
<p>As long as you use any of these methods of View-ViewModel registrations &#8211; your navigation will work.</p>
<h1>View Initialization</h1>
<p>So now that we know how to register our Views and ViewModels lets see how ViewModel initialization looks like.</p>
<p>Since base class ViewModel implements <strong><a title="IAcceptInitializationData " href="http://prismnavigation.codeplex.com/SourceControl/changeset/view/58210#1299219" target="_blank">IAcceptInitializationData</a> </strong>interface it is ready to accept initialization data like this:</p>
<pre class="brush: csharp; title: ; notranslate">
    public interface IAcceptInitializationData
    {
        void Initialize(ViewInitializationData initializationData);
    }
</pre>
<p>So whenever some View needs to be shown, behind the scenes its ViewModel will be created, and its Initialize method will be invoked with initialization data (that includes parameters from URLs or directly passed if its done via code) and afterwards this ViewModel will be set as DataContext of the View and then View will be shown in desired prism Region by our Navigation Framework.</p>
<p>Lets take a look at the <strong>ViewInitializationData </strong>class that is passed to the ViewModel:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class ViewInitializationData
    {
        public string Url { get; set; }

        public string RegionName { get; set; }

        public Dictionary&lt;string,string&gt; Parameters = new Dictionary&lt;string, string&gt;();
    }
</pre>
<p>As you see its enough data for the ViewModel to start functioning &#8211; it knows where its loaded &#8211; RegionName, how (if via URL then corresponding Url property is filled), and it gets its parameters via Parameters dictionary.<br />
Parameters are parsed from the URL automatically by the framework so you dont have to worry about it.</p>
<h1>Can I Show Views From Code in ViewModel?</h1>
<p>If you are showing the View from the code, you can pass to it new instance of ViewInitializationData type where you can set your parameters etc.</p>
<p>Also its worth mentioning that if you show some View from code into the Main Region and pass parameters to it, then Browser URL will be updated to show the Url of the View showing the Module name, View name and parameters if any.</p>
<p>For example if you loaded <strong>DetalsView </strong>from <strong>ProductsModule </strong>with parameters ProductId = 1234 browser URL would change to something like this: http://yourapplication.com/index.html#/Products/Details/ProductId/1234).</p>
<h1>Plumbing</h1>
<p>As you can see the Prism Navigation Framework can do a lot of plumbing for you, so that you can focus on the implementation of the application functionality (don&#8217;t we all want to do that?).</p>
<p>In order to achieve all this framework is extending the Prism so it needs to call some initialization code in the <a title="bootstrapper documentation" href="http://msdn.microsoft.com/en-us/library/dd490820.aspx" target="_blank">Bootstrapper</a> class.</p>
<p>To avoid forcing users to manually call that code in every application there is special class <strong><a title="PrismNavigationFrameworkUnityBootstrapper" href="http://prismnavigation.codeplex.com/SourceControl/changeset/view/58210#1299193" target="_blank">PrismNavigationFrameworkUnityBootstrapper</a> </strong>that you can use instead of the regular <strong>UnityBootstrapper</strong> that will do all this initialization for you (for now MEF is not supported by this framework but maybe we will include it later).</p>
<p>So in your application bootstrapper that inherits <strong>PrismNavigationFrameworkUnityBootstrapper </strong>you don&#8217;t need to do anything other than what you would usually do, just create your Shell and register Modules etc, something like this maybe:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class Bootstrapper : PrismNavigationFrameworkUnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            this.Container.Resolve&lt;IViewRegistrationService&gt;().RegisterViewAndViewModel&lt;ShellView, ShellViewModel&gt;();
            return Container.Resolve&lt;IViewCreationService&gt;().CreateView&lt;ShellView&gt;() as DependencyObject;
        }

        protected override void InitializeShell()
        {
            base.InitializeShell();

            Application.Current.RootVisual = (UIElement)this.Shell;
        }

        protected override Microsoft.Practices.Composite.Modularity.IModuleCatalog CreateModuleCatalog()
        {
            return
                Microsoft.Practices.Composite.Modularity.ModuleCatalog.CreateFromXaml(new Uri(
                    &quot;PrismNavigation.App;component/ModuleCatalog.xaml&quot;, UriKind.Relative));
        }
    }
</pre>
<h1>Wrap Up</h1>
<p>This is just an introductory post and here you could see only part of what you can expect from this Framework.</p>
<p>I wont go into further details for now, so expect in the future more posts covering every feature of the Prism Navigation Framework in more details.</p>
<p>In the meantime check out the <a title="Prism Application Framework Sample Application" href="http://demos.roboblob.com/Silverlight4/PrismNavigationFramework/Beta1Demo/" target="_blank">Prism Application Framework Sample Application</a> just to get a feel of what it can do, or browse the <a title="Latest Source Code" href="http://prismnavigation.codeplex.com/SourceControl/BrowseLatest" target="_blank">latest Source Code</a> or <a title="source code downloads" href="http://prismnavigation.codeplex.com/releases/" target="_blank">download it</a> and use freely for building your next big Prism Silverlight MVVM application.</p>
<p>Your <a title="feedback form" href="http://blog.roboblob.com/contact/" target="_blank">feedback</a> (both positive and negative) and <a title="participate" href="http://prismnavigation.codeplex.com/team/view" target="_blank">participation in the development of the project</a> is very welcome!</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F&amp;title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F&amp;title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F&amp;title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F&amp;headline=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F&amp;title=Introducing+the+Prism+Navigation+Framework+for+Silverlight+MVVM+Applications&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F24%2Fintroducing-prism-navigation-framework-for-silverlight-mvvm-applications%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/fpqa7iIfVjU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2010/10/24/introducing-prism-navigation-framework-for-silverlight-mvvm-applications/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Combining Silverlight Navigation Framework and Prism to create MVVM Applications – Introduction</title>
		<link>http://blog.roboblob.com/2010/10/15/combining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction/</link>
		<comments>http://blog.roboblob.com/2010/10/15/combining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction/#comments</comments>
		<pubDate>Fri, 15 Oct 2010 14:32:01 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Prism Navigation Framework]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[frame]]></category>
		<category><![CDATA[inavigationframework]]></category>
		<category><![CDATA[navigation]]></category>
		<category><![CDATA[Prism]]></category>
		<category><![CDATA[View]]></category>
		<category><![CDATA[ViewModel]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=405</guid>
		<description><![CDATA[This is introductory post for a series of posts where i will try to tackle the holy grail of MVVM applications - Navigation.

To do this I will be using Prism from Microsoft's Patterns and Practices team (Silverlight version - latest drop) combined with Silverlight Navigation Framework and i will build small navigation framework on top of that...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>This is introductory post for a series of posts where i will try to tackle the holy grail of MVVM applications &#8211; Navigation.</p>
<p>To do this I will be using <a title="Prism" href="http://compositewpf.codeplex.com/" target="_blank">Prism</a> from Microsoft&#8217;s Patterns and Practices team (Silverlight version &#8211; latest drop) combined with <a title="Silverlight Navigation Framework" href="http://msdn.microsoft.com/en-us/library/cc838245%28VS.95%29.aspx" target="_blank">Silverlight Navigation Framework</a> and i will build small navigation framework on top of that.</p>
<p>If you are too busy to read this post and just want to see the result take a look at the current state of the <a title="Demo MVVM Prism Navigation application" href="http://demos.roboblob.com/Silverlight4/MVVM/PrismNavigation/index.html" target="_blank">sample Silverlight Prism Navigation application</a> where you can see most of the important features of this small navigation framework (PrismExtensions.dll that contains all the framework code is 35.5 KB in size).</p>
<p>And for those of you with stronger nerves here is the real story:</p>
<p>Lately i have been playing with my old friend <a title="Prism" href="http://compositewpf.codeplex.com/" target="_blank">Prism</a> and re-discovering how good it is for building MVVM Silverlight and WPF applications.</p>
<p>Out of the box you get a lot of things (and only few months ago i was trying to build all of this from scratch &#8211; you can see that from my earlier <a title="Silverlight MVVM posts" href="http://blog.roboblob.com/category/mvvm/" target="_blank">MVVM blog posts</a>).</p>
<p>One of the things i like the most in Prism is the modularity concept and support for loading application modules dynamically from local/remote servers &#8211; on users/application request.</p>
<p>This allows developers to cut the application in modules with isolated functionality and on start load only mandatory parts and then load other modules only if users really needs/request them.</p>
<p>What really surprised me is that nobody has so far managed to combine Prism with <a title="Silverlight Navigation Framework" href="http://msdn.microsoft.com/en-us/library/cc838245%28VS.95%29.aspx" target="_blank">Silverlight&#8217;s excellent Navigation Framework </a>in a successful way so that is usable for real-life MVVM applications (at least i could not find any good examples on the web).</p>
<p>Prism has a concept of Regions and allows easy loading of Views into them but this is where it ends &#8211; there are no higher level concepts of navigation &#8211; this is why i decided to build some kind of Navigation framework on top of Prism &#8211; to fill that gap.</p>
<p>This is where the very important concept of <a title="Deep Linking" href="http://en.wikipedia.org/wiki/Deep_linking" target="_blank">Deep Linking</a> comes into the story. I cannot imagine any serious Silverlight application without allowing users to bookmark pages in the browser, and to use the Back and Forward browser button to navigate though the UI, to manually &#8216;hack&#8217; the URLs to load different data etc&#8230;</p>
<p>So this is something where Silverlight Navigation Framework can help us. It has built in support for all major browsers for browser history, it notifies the application about the browser URL change, there is HyperlinkButton control that has NavigateUri property where you can specify the application URL that will be loaded when user clicks on it (without full page reload off course &#8211; because only the fragment of the URL after # sign is changed) etc.</p>
<p>The only problem is that there is no easy way to combine Prism and Silverlight Navigation Framework.</p>
<p>Yes we can implement <a title="INavigationContentLoader" href="http://msdn.microsoft.com/en-us/library/system.windows.navigation.inavigationcontentloader%28VS.95%29.aspx" target="_blank">INavigationContentLoader</a> and plug it into the <a title="Silverlight Frame control" href="http://msdn.microsoft.com/en-us/library/system.windows.controls.frame%28v=VS.95%29.aspx" target="_blank">Frame</a> control but still we don&#8217;t have full control over the page/view loading process, we need additional Frame for each Region where we want to show Views etc.</p>
<p>So i decided to do a little research on how to simplify things and to create a small framework for Prism that will use Silverlight Navigation Framework to load Views into Prism Regions and enable Deep Linking, passing parameters to views, to allow integration with Prism modularity and allow deferred module loading etc &#8211; in other words all the features that one would expect to have in modern RIA Silverlight application.</p>
<p><span style="text-decoration: underline;">Here are some features that i already support or will in near future:</span></p>
<ul>
<li>it must be a simple (for the end user-developer) but full blown Navigation Framework for Prism Silverlight MVVM applications</li>
<li>it will support this main MVVM scenario: application will have one Main View (so called &#8216;Shell&#8217;) that will be loaded on start of the application and this will be the main &#8216;screen&#8217; of the application that will have multiple regions where we can load Views. Only one region will be considered as Main Region and it will be &#8216;tied&#8217; to the URL typed in the browser. Other regions will not update browsers URL or be affected by changes in the URL but application will be able to load Views into other regions &#8211; for example Widgets etc (i decided not to support Regions inside Views loaded into Regions on Main Region as this greatly simplifies the implementation and i don&#8217;t see a real usage scenario anyway -  instead of using Sub-Regions you can always use child Views inside of your View for that).</li>
<li>support for passing the parameters to the Views via browsers URL &#8211; every update in the URL of the browser will load appropriate view in  Main Region (and pass parameters from URL to the Views ViewModel) and on  the other hand, if some View is loaded to Main Region from code, this  will reflect on the browser URL (including the parameters passed to  View).</li>
<li>when View is loaded into region it will be connected to its ViewModel (set as its DataContext) &#8211; this is done automagically by the framework, user just needs to define the mapping between Views and View Models in the Module initialization &#8211; more details on that in later posts.</li>
<li>support for manually loading Views from ViewModels via code (not only via URLs) using the same framework &#8211; via some service like IPrismViewLoadingService</li>
<li>framework should include support for Prism deferred loading of application Modules &#8211; there should be easy way to load Prism Modules that are marked as OnDemand and they should be loaded either manually &#8211; from code or automagically &#8211; when user navigates to URL that should show View that is in module marked as &#8216;OnDemand&#8217;</li>
<li>there should be a way to define User Friendly URL&#8217;s &#8211; aliases for specific Views and Modules but some smart defaults should work out of the box by default like: &#8220;/Products/Detail/1234&#8243;  or &#8220;/ProductsModule/Details/1234&#8243; etc &#8211; user should just type the URL in browser and Framework must load the Module if needed and then show the View (bound to its initialized ViewModel)</li>
<li>full support for navigation between Views using HyperlinkButton controls &#8211; for loading Views to Main Region and to other Regions</li>
<li>framework should be &#8216;opinionated&#8217; regarding the way how it initializes and binds Views and their ViewModels &#8211; in our case it will be View-ViewModel-Marriage approach: there is separate service that initializes ViewModel and set it as DataContext of the View.</li>
<li>it should be simple to use for the end user-developer &#8211; smart defaults should work without any user configuration yet customization should be possible for advanced scenarios</li>
<li>whole solution should be based on services that implement defined interfaces &#8211; so that they can be easily changed with different implementations that user could plug via IOC &#8211; for example to easily change the parameters format from &#8216;parameterA/value1/parameterB/value2&#8242; into &#8216;?parameterA=value1&amp;parameterB/value2&#8242; etc.</li>
</ul>
<p>So this features should be enough to get us started but we can change this along the way if we see that its appropriate &#8211; if you have some suggestions &#8211; <a title="Contact form" href="http://blog.roboblob.com/contact/" target="_blank">do let me know</a>!</p>
<p>As you can see from the <a title="Silverlight Prism MVVM Navigation sample application" href="http://demos.roboblob.com/Silverlight4/MVVM/PrismNavigation/index.html" target="_blank">Sample Application</a> I already have implemented most of these features and I will be finishing along the way as i write more posts in the future &#8211; what you can see in the demo right now is: Browser URL history integration (Deep Linking and Back/Forward buttons support), Loading Views with their corresponding ViewModels to Main Region and to secondary Regions, passing parameters to Views, asynchronous deferred loading of Modules/Views etc.</p>
<p>If some you know of some other Prism Navigation Framework that already has most of these features please let me know so i can stop doing this and enjoy real life <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Otherwise see ya soon in the next part of this article series where i will explain all about this framework and share some code with usage scenarios.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F&amp;title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F&amp;title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F&amp;title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F&amp;headline=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F&amp;title=Combining+Silverlight+Navigation+Framework+and+Prism+to+create+MVVM+Applications+%E2%80%93+Introduction&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F10%2F15%2Fcombining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/jDRji6mujjk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2010/10/15/combining-silverlight-navigation-framework-and-prism-to-create-mvvm-applications-introduction/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Custom Silverlight TextBox control that immediately updates DataBound Text property in TwoWay binding</title>
		<link>http://blog.roboblob.com/2010/07/16/custom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding/</link>
		<comments>http://blog.roboblob.com/2010/07/16/custom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 14:55:20 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[CustomControl]]></category>
		<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[Control]]></category>
		<category><![CDATA[DataBinding]]></category>
		<category><![CDATA[TextBlock]]></category>
		<category><![CDATA[TextBox]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=385</guid>
		<description><![CDATA[Standard Silverlight TextBox control is very useful but has one strange behavior: if you use TwoWay data binding and bind some property to controls Text property, when users type text into the control, this change is not propagated to the bound property until the control loses its focus. This can be very annoying if you [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Standard Silverlight TextBox control is very useful but has one strange behavior: if you use TwoWay data binding and bind some property to controls Text property, when users type text into the control, this change is not propagated to the bound property until the control loses its focus.</p>
<p>This can be very annoying if you have MVVM application and you have some kind of real-time filter that needs to update some data as-you-type.</p>
<p>Problem is that TextBox control does not call <a href="http://msdn.microsoft.com/en-us/library/system.windows.data.bindingexpression.updatesource%28VS.95%29.aspx" target="_blank">BindingExpression.UpdateSource</a> when its Text property is changed so we have to do that manually in order to fix this issue.</p>
<p>To fix this once and for all I have created simple custom control ImmediateTextBox that inherits the standard TextBox and just calls BindingExpression.UpdateSource for TextBox.TextProperty whenever text is changed.</p>
<p>Here is all the code that is in our custom control:</p>
<pre class="brush: csharp; title: ; notranslate">
using System.Windows.Controls;

namespace ImmediateDataBindingTextBox
{
    public class ImmediateTextBox : TextBox
    {
        public ImmediateTextBox()
        {
            this.Loaded += ImmediateTextBox_Loaded;
        }

        void ImmediateTextBox_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            this.TextChanged += ImmediateTextBox_TextChanged;
        }

        void ImmediateTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            var tb = sender as TextBox;
            if (tb != null)
            {
                var be = tb.GetBindingExpression(TextBox.TextProperty);
                if (be != null)
                {
                 be.UpdateSource();
                }
            }
        }
    }
}
</pre>
<p>And here is the <a title="sample silverlight application for ImmediateTextBox" href="http://demos.roboblob.com/Silverlight4/mvvm/ImmediateTextBox/" target="_blank">demo application</a> that shows this in action.<br />
In sample app you have standard TextBox and our custom ImmediateTextBox that are both bound to some property in ViewModel using TwoWay binding.</p>
<p>Below is TextBlock also bound to same property to show the current value of the property.</p>
<p>If you type text into standard TextBox the text in TextBlock will not be updated until TextBox loses its focus  and if you type text into our custom control you will see the changes propagated to the underlying property immediately.</p>
<p>If you want to use this control you can download <a title="sample solution Visual Studio 2010" href="http://demos.roboblob.com/Silverlight4/mvvm/ImmediateTextBox/ImmediateDataBindingTextBoxSolution.zip" target="_self">sample  Visual Studio 2010 Solution</a></p>
<p>Hope someone can find this useful when doing MVVM style applications where you cannot just reach for the code in code-behind to fix problems like this <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F&amp;title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F&amp;title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F&amp;title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F&amp;headline=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F&amp;title=Custom+Silverlight+TextBox+control+that+immediately+updates+DataBound+Text+property+in+TwoWay+binding&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F07%2F16%2Fcustom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/2NEPifhi3_M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2010/07/16/custom-silverlight-textbox-control-that-immediately-updates-databound-text-property-in-twoway-binding/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Silverlight MergedDictionaries – using styles and resources from Class Libraries</title>
		<link>http://blog.roboblob.com/2010/06/09/silverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries/</link>
		<comments>http://blog.roboblob.com/2010/06/09/silverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 12:54:11 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[resources]]></category>
		<category><![CDATA[styles]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=346</guid>
		<description><![CDATA[If you were developing larger Silverlight/WPF applications and trying to keep things like styles, control templates and other resources organized it can become really hard. Prior to Silverlight 3 it was hell to be honest You had to scatter resources all around your application, on control level and put global ones in App.xaml and soon [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>If you were developing larger Silverlight/WPF applications and trying to keep things like styles, control templates and other resources organized it can become really hard.<br />
Prior to Silverlight 3 it was hell to be honest <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>You had to scatter resources all around your application, on control level and put global ones in App.xaml and soon it would all grow beyond control.</p>
<p>But then nice people from Microsoft introduced lovely little feature called <a href="http://msdn.microsoft.com/en-us/library/system.windows.resourcedictionary.mergeddictionaries(VS.95).aspx">MergedDictionaries</a> that allows you to combine the resources from different places in your application.</p>
<p>The beauty of this simple technique is that you can use resources from different files that can even reside in different Class Libraries in your project and just &#8216;reference&#8217; them in the application level (App.xaml) and they will immediately become available to all the controls in your application.</p>
<p>Not to mention the moment of reuse: you can group your application resources into assemblies, for example one can hold the Styles, another can contain Control Templates, third can have text resources etc and then you can just reference them in any project and easily (re)use them.</p>
<p>So lets see how to actually accomplish this.<br />
Luckily its very simple. We just need to add few lines to our App.xaml file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;Application xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
             x:Class=&quot;ResourceDictionariesInLib.App&quot;&gt;
    &lt;Application.Resources&gt;
        &lt;ResourceDictionary&gt;
            &lt;ResourceDictionary.MergedDictionaries&gt;
                &lt;ResourceDictionary Source=&quot;/ResourceDictionariesInLib.BasicStyles;component/StylesForShapes.xaml&quot; /&gt;
                &lt;ResourceDictionary Source=&quot;/ResourceDictionariesInLib.FontStyles;component/StylesForFonts.xaml&quot; /&gt;
                &lt;ResourceDictionary Source=&quot;LocalStyles/BasicStyles.xaml&quot; /&gt;
            &lt;/ResourceDictionary.MergedDictionaries&gt;
        &lt;/ResourceDictionary&gt;
  &lt;/Application.Resources&gt;
&lt;/Application&gt;
</pre>
<p>As you see here I&#8217;m using resources from two different Silverlight Class Libraries and one is from local subfolder called &#8220;LocalStyles&#8221;.<br />
The format is clear, for resources in DLLs you use:<br />
Source=&#8221;/AssemblyName;<strong>component</strong>/FileName.xaml&#8221;<br />
The &#8220;component&#8221; part is just a keyword that tells the parser that resource is in referenced DLL.</p>
<p>One important catch here is if you are merging resources from DLLs than you need to actually add references to those Class Libraries that hold your resources so in this case i had to Add Reference to two DLLs: ResourceDictionariesInLib.BasicStyles.dll and ResourceDictionariesInLib.FontStyles.dll.</p>
<p>Format for the resource file in the application is self-explanatory.</p>
<p>In order to create a xaml file in some Class Library to hold resources just choose Add-&gt;New Item and then select SilverlightResourceDictionary from the list.</p>
<p>Also its important to state here that you can put MergedDictionaries at every level, meaning that you can put them to App.xaml and then those merged resources will be available to every element of your application, but also you can place MergedDictionaries in the CustomControl (in CustomControl.Resources) and then this resources will be available only to this control.</p>
<p>So lets see how those MergedDictionaries of resources can be used.</p>
<p>In the StylesForShapes.xaml file i have some background gradient brushes:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;ResourceDictionary
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;&gt;

    &lt;LinearGradientBrush x:Key=&quot;EllipseFillBrush&quot; EndPoint=&quot;1,0.5&quot; StartPoint=&quot;0,0.5&quot;&gt;
        &lt;GradientStop Color=&quot;Black&quot; Offset=&quot;0&quot; /&gt;
        &lt;GradientStop Color=&quot;#FFD41313&quot; Offset=&quot;1&quot; /&gt;
    &lt;/LinearGradientBrush&gt;

  &lt;LinearGradientBrush x:Key=&quot;RectangleFillBrush&quot; EndPoint=&quot;1,0.5&quot; StartPoint=&quot;0,0.5&quot;&gt;
    &lt;GradientStop Color=&quot;Black&quot; Offset=&quot;0&quot; /&gt;
    &lt;GradientStop Color=&quot;#FF3AD859&quot; Offset=&quot;1&quot; /&gt;
  &lt;/LinearGradientBrush&gt;

&lt;/ResourceDictionary&gt;
</pre>
<p>So since i referenced StylesForShapes.xaml file in MergedDictionaries in my App.xaml file i can use styles from that file in any Silverlight control in the whole application.</p>
<pre class="brush: xml; title: ; notranslate">
    &lt;Grid x:Name=&quot;LayoutRoot&quot; Background=&quot;White&quot; Height=&quot;348&quot; Width=&quot;489&quot;&gt;
        &lt;Ellipse Fill=&quot;{StaticResource EllipseFillBrush}&quot; /&gt;
        &lt;Rectangle Fill=&quot;{StaticResource RectangleFillBrush}&quot; /&gt;
    &lt;/Grid&gt;
</pre>
<p>You can do the same for any other property like FontSize or FontFamilly.</p>
<p>Just extract property value to a resource and then reuse it in your app.</p>
<p>Another very nice thing about MergedDictionaries is that they are supported by Visual Studio 2010 and Blend 3/4 so if you have DLLs with resources and you merge them in App.xaml then when you are extracting new resources you can specify those resource files in DLL&#8217;s as the place where that newly extracted resource will be created.</p>
<p>Here is the example:<br />
In Visual Studio create UserControl and put an Ellipse element on it and set its Fill property to be some nice GradientBrush and then click on the <strong>black diamond</strong> <strong>symbol </strong>to the right of the Fill property and in the pop-up menu choose option <strong>Extract value to Resource</strong>:</p>
<p><a href="http://blog.roboblob.com/wp-content/uploads/2010/06/ExtractToResource.jpg"></a><a href="http://blog.roboblob.com/wp-content/uploads/2010/06/ExtractToResource.jpg"><br />
</a><a href="http://blog.roboblob.com/wp-content/uploads/2010/06/ExtractToResource.jpg"><img class="aligncenter size-full wp-image-354" title="ExtractToResource" src="http://blog.roboblob.com/wp-content/uploads/2010/06/ExtractToResource.jpg" alt="" width="468" height="349" /></a></p>
<p>After clicking on the <strong>Extract Value to Resource</strong> menu item you will need to choose where to save the newly created resource and you can here choose any of the resource xaml files in your Class Libraries like this:</p>
<p><a href="http://blog.roboblob.com/wp-content/uploads/2010/06/ChooseResourceFile.jpg"><img class="aligncenter size-full wp-image-357" title="ChooseResourceFile" src="http://blog.roboblob.com/wp-content/uploads/2010/06/ChooseResourceFile.jpg" alt="" width="380" height="174" /></a></p>
<p>So here is how a sample page that uses MergedDictionaries to set styles and fonts on its controls looks like:<br />
<a title="Silverlight MergedDictionaries demo" href="http://demos.roboblob.com/Silverlight4/MergedDictionaries/" target="_blank"><br />
</a><a href="http://demos.roboblob.com/Silverlight4/MergedDictionaries/"></a><a href="http://demos.roboblob.com/Silverlight4/MergedDictionaries/"><img class="aligncenter size-full wp-image-367" title="MergedDictionariesSample" src="http://blog.roboblob.com/wp-content/uploads/2010/06/MergedDictionariesSample.jpg" alt="" width="600" height="344" /></a></p>
<p>And <a href="http://demos.roboblob.com/Silverlight4/MergedDictionaries/ResourceDictionariesInLibrarySolution.zip">here is the Visual Studio 2010 demo solution</a>.</p>
<p>Have fun! <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F&amp;title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F&amp;title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F&amp;title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F&amp;headline=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F&amp;title=Silverlight+MergedDictionaries+-+using+styles+and+resources+from+Class+Libraries&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F06%2F09%2Fsilverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/E01UjOWjhGo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2010/06/09/silverlight-mergeddictionaries-using-styles-and-resources-from-class-libraries/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Unit Testing Modal Dialogs in MVVM and Silverlight 4</title>
		<link>http://blog.roboblob.com/2010/04/21/unit-testing-modal-dialogs-in-mvvm-and-silverlight-4/</link>
		<comments>http://blog.roboblob.com/2010/04/21/unit-testing-modal-dialogs-in-mvvm-and-silverlight-4/#comments</comments>
		<pubDate>Wed, 21 Apr 2010 07:58:53 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[ChildWindow]]></category>
		<category><![CDATA[Dialog]]></category>
		<category><![CDATA[ModalDialog]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[UnitTest]]></category>
		<category><![CDATA[UnitTesting]]></category>
		<category><![CDATA[ViewModel]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=319</guid>
		<description><![CDATA[As feedback to my recent post on Modal Dialogs in MVVM and Silverlight 4 I have received comments that the solution is not easy to Unit Test so i decided to create small blog posts on this subject just to show how simple and clean it is to do this...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>As feedback to <a href="http://blog.roboblob.com/2010/01/19/modal-dialogs-with-mvvm-and-silverlight-4/" target="_blank">my recent post on Modal Dialogs in MVVM and Silverlight 4</a> I have received comments that the solution is not easy to Unit Test so i decided to create small blog posts on this subject just to show how simple and clean it is to do this.</p>
<p>So for those who are too lazy to read <a href="http://blog.roboblob.com/2010/01/19/modal-dialogs-with-mvvm-and-silverlight-4/" target="_blank">my original modal dialog post</a> here is a quick reminder:</p>
<ul>
<li>I presented a simple solution how to abstract modal dialogs and  message boxes in Silverlight 4 and call them from your ViewModel and act  according to the results returned from those modal dialogs.</li>
<li>I used Silverlight&#8217;s ChildWindow control because it was perfect fit for  that job.</li>
<li>Important thing is to say that ChildWindow control was used as  implementation (with its ViewModel off course) but was hidden by  abstractions (like IModalWindow and IModalWindowService) so it can  easily be changed by some other implementation and unit tested, mocked  out etc.</li>
</ul>
<p>So in this post i will use the same simple <a href="http://demos.roboblob.com/demos/Silverlight4/MVVM/MvvmModalDialogsUnitTesting/" target="_blank">Demo Application</a> for the previous modal dialogs post but I will add few Unit Tests using <a href="http://code.msdn.microsoft.com/silverlightut" target="_blank">Silverlight Unit Testing Framework</a> and <a href="http://www.ayende.com/projects/rhino-mocks/downloads.aspx" target="_blank">Silverlight verstion of RhinoMocks</a>.</p>
<p>Our <a href="http://demos.roboblob.com/demos/Silverlight4/MVVM/MvvmModalDialogsUnitTesting/" target="_blank">Sample app</a> is very simple and just shows a view with list of some User entities.</p>
<p>Each of users can be edited by clicking on EDIT button next to them &#8211; this shows a modal dialog with User editor, we can change details and save them by clicking on OK or CANCEL.</p>
<p>Also there is option to delete each User by clicking on the DEL button &#8211; Message Box is shown with OK/Cancel buttons &#8211; these are very common scenarios for every LOB application so that&#8217;s why i picked them.</p>
<p>I must admit that i improved my framework since the previous post &#8211; I changed the signature of the IModalDialogService a little because now in my framework i have a IViewInitializationService that wires up ViewModels with Views so all this is used in this posts just to show it off <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   (more on the IViewInitializationService and the new way how i wire up ViewModels and View in one of the next posts).</p>
<p>So first let&#8217;s see the changes made to the IModalDialogView that is the abstraction of the actual modal dialog to be shown:</p>
<pre class="brush: csharp; title: ; notranslate">
  public interface IModalWindowView : IView
  {
    bool? DialogResult { get; set; }
    event EventHandler Closed;
    void Show();
    void Close();
  }
</pre>
<p>So the real ChildWindow that will be our dialog only needs to be marked as implementor of IModalWindowView interface with no additional code needed since this interface contains only methods and properties that ChildWindow already implements:</p>
<pre class="brush: csharp; title: ; notranslate">
    public partial class EditUserModalDialogView : IModalWindowView
    {
        public EditUserModalDialogView()
        {
            InitializeComponent();
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }
    }
</pre>
<p>Also you could see that our IModalDialogView implements our old friend &#8211; IView:</p>
<pre class="brush: csharp; title: ; notranslate">
    public interface IView
    {
        object FindName(string name);
        object DataContext { get; set; }
        string Name { get; set; }
        event RoutedEventHandler Loaded;
    }
</pre>
<p>Again nothing to implement here &#8211; no code to add &#8211; because ChildWindow already implements all this since its inheriting the ContentContol that has all this.</p>
<p>So now lets see the MainPageViewModel for our MainPageView that will actually show the modal dialogs and message boxes:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class MainPageViewModel : ViewModel
    {
        private readonly IModalDialogService modalDialogService;
        private readonly IMessageBoxService messageBoxService;
        private ObservableCollection&lt;User&gt; users = new ObservableCollection&lt;User&gt;();

        public MainPageViewModel(IModalDialogService modalDialogService, IMessageBoxService messageBoxService)
        {
          this.modalDialogService = modalDialogService;
          this.messageBoxService = messageBoxService;

          this.Users = new ObservableCollection&lt;User&gt;();

          for (int i = 1; i &lt; 6; i++ )
          {
            this.Users.Add(new User {Username = string.Format(&quot;Admin User {0}&quot;,
                new Random((int)DateTime.Now.Ticks).Next(10,100)), IsAdmin = true});
            Thread.Sleep(100);
          }

          this.ShowUserCommand =
              new DelegateCommand&lt;User&gt;(userInstanceToEdit =&gt;
                                      {
                                       this.modalDialogService.ShowDialog&lt;EditUserModalDialogViewModel&gt;
                                             (
                                             userInstanceToEdit,
                                             (dialog, returnedViewModelInstance) =&gt;
                                             {
                                                if (dialog.DialogResult.HasValue &amp;&amp; dialog.DialogResult.Value)
                                                {
                                                var oldItem = this.Users.FirstOrDefault( u =&gt; u.Id == userInstanceToEdit.Id);
                                                var oldPos = this.Users.IndexOf(oldItem);
                                                if (oldPos &gt; -1)
                                                {
                                                    this.Users.RemoveAt(oldPos);
                                                    this.Users.Insert(oldPos, returnedViewModelInstance.User);
                                                }
                                                }
                                            });
                                       });

          this.DeleteUserCommand = new DelegateCommand&lt;User&gt;
              (p =&gt;
                                    {
                                        var result = this.messageBoxService.Show(string.Format(
                                            &quot;Are you sure you want to delete user {0} ???&quot;, p.Username),
                                            &quot;Please Confirm&quot;, GenericMessageBoxButton.OkCancel);
                                        if (result == GenericMessageBoxResult.Ok)
                                        {
                                        this.Users.Remove(p);
                                        }});

        }

        public ObservableCollection&lt;User&gt; Users
        {
            get { return users; }
            set { users = value;
            this.OnPropertyChanged(&quot;Users&quot;);
            }
        }

        private ICommand showUserCommand;
        public ICommand ShowUserCommand
        {
            get { return showUserCommand; }
            set { showUserCommand = value;
                this.OnPropertyChanged(&quot;ShowUserCommand&quot;);
            }
        }

      private ICommand deleteUserCommand;
      public ICommand DeleteUserCommand
      {
        get { return deleteUserCommand; }
        set { deleteUserCommand = value;
        this.OnPropertyChanged(&quot;DeleteUserCommand&quot;);
        }
      }
    }
</pre>
<p>As you see ViewModel is simple class and it just has a list of Users to be shown by its View and important things to notice here are two commands for editing and deleting single user.</p>
<p><strong> ShowUserCommand </strong>shows modal dialog for editing single user, and <strong>DeleteUserCommand </strong>just shows MessageBox for confirmation of deletion with OK and Cancel buttons.</p>
<p>So now comes the fun part, lets write unit tests for those commands:</p>
<p>First UnitTest checks that our ShowUserCommand shows the modal dialog for editing the user (using the IModalDialogService). We put expectation on our IModalDialogService mock and invoke our command on ViewModel and verify all expectations afterwards.</p>
<p>Here is the code:</p>
<pre class="brush: csharp; title: ; notranslate">
        [TestMethod]
        public void ShowUserCommand_WhenCalledWithSpecificUser_ShowsModalDialogByPassingThatUserAsInitParam()
        {
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            modalDialogService.Expect(
                p =&gt; p.ShowDialog&lt;EditUserModalDialogViewModel&gt;(null, null))
                .Constraints(
                Is.Same(userToSend),
                Is.TypeOf(typeof(Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;)))
                .Repeat.Once();

            viewModel.ShowUserCommand.Execute(userToSend);

            modalDialogService.VerifyAllExpectations();
        }
</pre>
<p>We first get our ViewModel with Rhino-mocked instances of IModalDialogService and IMessageBoxService and some test Users by calling this methods:</p>
<pre class="brush: csharp; title: ; notranslate">
        private static ObservableCollection&lt;User&gt; GenerateSampleUsers()
        {
            return new ObservableCollection&lt;User&gt;()
                                  {
                                      new User() {Username = &quot;user 1&quot;},
                                      new User() {Username = &quot;user 2&quot;},
                                      new User() {Username = &quot;user 3&quot;}
                                  };
        }

        private MainPageViewModel GetInitializedAndMockedViewModel()
        {
            this.modalDialogService = MockRepository.GenerateMock&lt;IModalDialogService&gt;();
            this.messageBoxService = MockRepository.GenerateMock&lt;IMessageBoxService&gt;();
            return new MainPageViewModel(this.modalDialogService, this.messageBoxService);
        }
</pre>
<p>So that was easy or what?</p>
<p>Lets go to next Unit Test. Lets check that when we call ShowUserCommand with instance of User that when it shows dialog and dialog returns true as its DialogResult &#8211; that we replace the original User in ViewModel&#8217;s list of Users with the one we got from the modal dialog:</p>
<pre class="brush: csharp; title: ; notranslate">
        [TestMethod]
        public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsTrue_ShouldReplaceTheOriginalUserInstanceWithOneReturnedFromModel()
        {
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            var dialog = MockRepository.GenerateMock&lt;IModalWindowView&gt;();
            dialog.Expect(p =&gt; p.DialogResult).Return(true);

            var mockViewModel = MockRepository.GenerateStub&lt;EditUserModalDialogViewModel&gt;();
            mockViewModel.User = new User() {Username = &quot;mocked&quot;};

            modalDialogService.Expect(
                p =&gt; p.ShowDialog&lt;EditUserModalDialogViewModel&gt;(null, null))
                .Constraints(
                    Is.Same(userToSend),
                    Is.TypeOf(typeof (Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;)))
                .Repeat.Once().WhenCalled(
                    m =&gt;
                        {
                            var action = (m.Arguments[1] as Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;);
                            if (action != null)
                            {
                                action.Invoke(dialog, mockViewModel);
                            }
                        });

            viewModel.ShowUserCommand.Execute(userToSend);

            Assert.AreEqual(&quot;mocked&quot;, viewModel.Users[1].Username);
        }
</pre>
<p>And here is the unit test that checks the DeleteUserCommand so that it actually deletes the user from the ViewModel&#8217;s list of users if OK button was clicked on the shown message box:</p>
<pre class="brush: csharp; title: ; notranslate">
        [TestMethod]
        public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsOk_ShouldDeleteThatUser()
        {
            // arrange
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            this.messageBoxService.Expect(p =&gt; p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
                Is.Anything(), Is.Anything(),
                Is.Anything()).Return(GenericMessageBoxResult.Ok);

            // act
            viewModel.DeleteUserCommand.Execute(userToSend);

            // assert user is not there anymore
            Assert.IsFalse(viewModel.Users.Any( u =&gt; u.Username == userToSend.Username));
        }
</pre>
<p>So it turned out that its quite simple to test Modal Dialogs as long as you have the proper abstractions in place <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
You can <a href="http://demos.roboblob.com/demos/Silverlight4/MVVM/MvvmModalDialogsUnitTesting/tests.aspx" target="_blank">open this page to see all the unit tests running in browser</a>.</p>
<p>Those tests are actually running on the code from the sample demo app!</p>
<p>And as you see all the Unit Tests are green, and the world is safe again <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Here is the code for all the tests, that is &#8211; all 9 of them:</p>
<pre class="brush: csharp; title: ; notranslate">
namespace UnitTestingModalDialogs.Tests
{
    [TestClass]
    public class MainPageViewModelTests
    {
        private IModalDialogService modalDialogService;
        private IMessageBoxService messageBoxService;

        private static ObservableCollection&lt;User&gt; GenerateSampleUsers()
        {
            return new ObservableCollection&lt;User&gt;()
                                  {
                                      new User() {Username = &quot;user 1&quot;},
                                      new User() {Username = &quot;user 2&quot;},
                                      new User() {Username = &quot;user 3&quot;}
                                  };
        }

        private MainPageViewModel GetInitializedAndMockedViewModel()
        {
            this.modalDialogService = MockRepository.GenerateMock&lt;IModalDialogService&gt;();
            this.messageBoxService = MockRepository.GenerateMock&lt;IMessageBoxService&gt;();
            return new MainPageViewModel(this.modalDialogService, this.messageBoxService);
        }

        [TestMethod]
        public void ShowUserCommand_WhenCalledWithSpecificUser_ShowsModalDialogByPassingThatUserAsInitParam()
        {
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            modalDialogService.Expect(
                p =&gt; p.ShowDialog&lt;EditUserModalDialogViewModel&gt;(null, null))
                .Constraints(
                Is.Same(userToSend),
                Is.TypeOf(typeof(Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;)))
                .Repeat.Once();

            viewModel.ShowUserCommand.Execute(userToSend);

            modalDialogService.VerifyAllExpectations();
        }

        [TestMethod]
        public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsTrue_ShouldReplaceTheOriginalUserInstanceWithOneReturnedFromModel()
        {
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            var dialog = MockRepository.GenerateMock&lt;IModalWindowView&gt;();
            dialog.Expect(p =&gt; p.DialogResult).Return(true);

            var mockViewModel = MockRepository.GenerateStub&lt;EditUserModalDialogViewModel&gt;();
            mockViewModel.User = new User() {Username = &quot;mocked&quot;};

            modalDialogService.Expect(
                p =&gt; p.ShowDialog&lt;EditUserModalDialogViewModel&gt;(null, null))
                .Constraints(
                    Is.Same(userToSend),
                    Is.TypeOf(typeof (Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;)))
                .Repeat.Once().WhenCalled(
                    m =&gt;
                        {
                            var action = (m.Arguments[1] as Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;);
                            if (action != null)
                            {
                                action.Invoke(dialog, mockViewModel);
                            }
                        });

            viewModel.ShowUserCommand.Execute(userToSend);

            Assert.AreEqual(&quot;mocked&quot;, viewModel.Users[1].Username);
        }

        [TestMethod]
        public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsFalse_ShouldNotReplaceTheItemInViewModelWithOneReceivedFromDialog()
        {
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            var dialog = MockRepository.GenerateMock&lt;IModalWindowView&gt;();
            dialog.Expect(p =&gt; p.DialogResult).Return(false);

            var mockViewModel = MockRepository.GenerateStub&lt;EditUserModalDialogViewModel&gt;();
            mockViewModel.User = new User() { Username = &quot;mocked&quot; };

            modalDialogService.Expect(
                p =&gt; p.ShowDialog&lt;EditUserModalDialogViewModel&gt;(null, null))
                .Constraints(
                    Is.Same(userToSend),
                    Is.TypeOf(typeof(Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;)))
                .Repeat.Once().WhenCalled(
                    m =&gt;
                    {
                        var action = (m.Arguments[1] as Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;);
                        if (action != null)
                        {
                            action.Invoke(dialog, mockViewModel);
                        }
                    });

            viewModel.ShowUserCommand.Execute(userToSend);

            Assert.AreNotEqual(&quot;mocked&quot;, viewModel.Users[1].Username);
        }

        [TestMethod]
        public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsNull_ShouldNotReplaceTheItemInViewModelWithOneReceivedFromDialog()
        {
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            var dialog = MockRepository.GenerateMock&lt;IModalWindowView&gt;();
            dialog.Expect(p =&gt; p.DialogResult).Return(null);

            var mockViewModel = MockRepository.GenerateStub&lt;EditUserModalDialogViewModel&gt;();
            mockViewModel.User = new User() { Username = &quot;mocked&quot; };

            modalDialogService.Expect(
                p =&gt; p.ShowDialog&lt;EditUserModalDialogViewModel&gt;(null, null))
                .Constraints(
                    Is.Same(userToSend),
                    Is.TypeOf(typeof(Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;)))
                .Repeat.Once().WhenCalled(
                    m =&gt;
                    {
                        var action = (m.Arguments[1] as Action&lt;IModalWindowView, EditUserModalDialogViewModel&gt;);
                        if (action != null)
                        {
                            action.Invoke(dialog, mockViewModel);
                        }
                    });

            viewModel.ShowUserCommand.Execute(userToSend);

            Assert.AreNotEqual(&quot;mocked&quot;, viewModel.Users[1].Username);
        }

        [TestMethod]
        public void DeleteUserCommand_WhenCalledWithSpecificUser_ShouldCallMessageBoxServiceWithSomeTextThatContainsThatUsersUsername()
        {

            // arrange
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            this.messageBoxService.Expect(p =&gt; p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
                Is.Matching&lt;string&gt;(txt =&gt; txt.Contains(userToSend.Username)), Is.Anything(),
                Is.Equal(GenericMessageBoxButton.OkCancel)).Return(GenericMessageBoxResult.Ok);

            // act
            viewModel.DeleteUserCommand.Execute(userToSend);

            // assert
            this.messageBoxService.VerifyAllExpectations();
        }

        [TestMethod]
        public void DeleteUserCommand_WhenCalledWithSpecificUser_ShouldCallMessageBoxServiceWithOkCancelParamForButtons()
        {

            // arrange
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            this.messageBoxService.Expect(p =&gt; p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
                Is.Anything(), Is.Anything(),
                Is.Equal(GenericMessageBoxButton.OkCancel)).Return(GenericMessageBoxResult.Ok);

            // act
            viewModel.DeleteUserCommand.Execute(userToSend);

            // assert
            this.messageBoxService.VerifyAllExpectations();
        }

        [TestMethod]
        public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsOk_ShouldDeleteThatUser()
        {
            // arrange
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            this.messageBoxService.Expect(p =&gt; p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
                Is.Anything(), Is.Anything(),
                Is.Anything()).Return(GenericMessageBoxResult.Ok);

            // act
            viewModel.DeleteUserCommand.Execute(userToSend);

            // assert user is not there anymore
            Assert.IsFalse(viewModel.Users.Any( u =&gt; u.Username == userToSend.Username));
        }

        [TestMethod]
        public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsCancel_ShouldNOTDeleteThatUser()
        {
            // arrange
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            this.messageBoxService.Expect(p =&gt; p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
                Is.Anything(), Is.Anything(),
                Is.Anything()).Return(GenericMessageBoxResult.Cancel);

            // act
            viewModel.DeleteUserCommand.Execute(userToSend);

            // assert user is not there anymore
            Assert.IsTrue(viewModel.Users.Any(u =&gt; u.Username == userToSend.Username));
        }

        [TestMethod]
        public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsCancel_ShouldNOTDeleteAnyUser()
        {
            // arrange
            var viewModel = GetInitializedAndMockedViewModel();

            viewModel.Users = GenerateSampleUsers();

            var userToSend = viewModel.Users[1];

            this.messageBoxService.Expect(p =&gt; p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
                Is.Anything(), Is.Anything(),
                Is.Anything()).Return(GenericMessageBoxResult.Cancel);

            var usersCountBefore = viewModel.Users.Count;
            // act
            viewModel.DeleteUserCommand.Execute(userToSend);

            // assert user is not there anymore
            Assert.AreEqual(usersCountBefore, viewModel.Users.Count);
        }

    }
}
</pre>
<p>If you want to investigate further <a href="http://demos.roboblob.com/Silverlight4/MVVM//MvvmModalDialogsUnitTesting/UnitTestingModalDialogsSolution.zip" target="_self">download the Visual Studio 2010 solution </a>and play with it &#8211; feel free to use the code as you wish and remember to have fun!</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F&amp;headline=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testing+Modal+Dialogs+in+MVVM+and+Silverlight+4&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F21%2Funit-testing-modal-dialogs-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/PUqOA3PUnPs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2010/04/21/unit-testing-modal-dialogs-in-mvvm-and-silverlight-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Silverlight 4 is over and out so ‘the dude abides’</title>
		<link>http://blog.roboblob.com/2010/04/17/silverlight-4-is-over-and-out-and-so-the-dude-abides/</link>
		<comments>http://blog.roboblob.com/2010/04/17/silverlight-4-is-over-and-out-and-so-the-dude-abides/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 14:08:53 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=311</guid>
		<description><![CDATA[Finally Visual Studio 2010 is out and so is the Silverlight 4. I got few complaints that my MVVM demo applications are not working properly for people that have the new Silverlight 4 runtime installed so i updated all the examples so they run properly. Also all solutions files with code are recompiled and checked [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Finally Visual Studio 2010 is out and so is the Silverlight 4.</p>
<p>I got few complaints that my <a title="mvvm in silverlight 4 blog posts" href="http://blog.roboblob.com/category/mvvm/" target="_blank">MVVM demo applications</a> are not working properly for people that have the new Silverlight 4 runtime installed so i updated all the examples so they run properly.</p>
<p>Also all solutions files with code are recompiled and checked in final version of VS 2010 so this should run fine now.</p>
<p>Expect soon more MVVM goodness on this blog, and until then &#8211; just enjoy the spring!  <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F&amp;title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F&amp;title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F&amp;title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F&amp;headline=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F&amp;title=Silverlight+4+is+over+and+out+so+%27the+dude+abides%27&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F17%2Fsilverlight-4-is-over-and-out-and-so-the-dude-abides%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/awv1dlfcLlo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2010/04/17/silverlight-4-is-over-and-out-and-so-the-dude-abides/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit Testable WCF Web Services in MVVM and Silverlight 4</title>
		<link>http://blog.roboblob.com/2010/04/11/unit-testable-wcf-web-services-in-mvvm-and-silverlight-4/</link>
		<comments>http://blog.roboblob.com/2010/04/11/unit-testable-wcf-web-services-in-mvvm-and-silverlight-4/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 21:00:19 +0000</pubDate>
		<dc:creator>roboblob</dc:creator>
				<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[DataBinding]]></category>
		<category><![CDATA[Mocking]]></category>
		<category><![CDATA[Mocks]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[ViewModel]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://blog.roboblob.com/?p=255</guid>
		<description><![CDATA[In all my previous MVVM in Silverlight 4 posts i was avoiding to address one painful aspect of the Silverlight: calling WCF Web Services. And it was not without reason. Lets face it, consuming WCF Web Services from your Silverlight application can be pretty hard. I mean hard to do it in a clean way [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F&amp;source=roboblob&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>In all my previous <a title="mvvm in silverlight 4 blog posts" href="http://blog.roboblob.com/tag/mvvm/" target="_blank">MVVM in Silverlight 4 posts</a> i was avoiding to address one painful aspect of the Silverlight: calling WCF Web Services.</p>
<p>And it was not without reason. Lets face it, consuming WCF Web Services from your Silverlight  application can be pretty hard.</p>
<p>I mean hard to do it in a clean way off course.</p>
<p>Yes we all know how to create a Silverlight enabled WCF Web Service from Visual Studio but things become messy from that point.</p>
<p>First question is how to invoke methods of the web service?</p>
<p>Should we use Add Web Service Reference from the Visual Studio and and get the service proxy generated for us by the IDE?</p>
<p>If you go down that route, its easy to start and you will be invoking web service methods asynchronously in no time, but you will pay the price for that simplicity later, that is for sure.</p>
<p>Next problem is how to Unit Test those web service calls &#8211; its impossible to abstract the generated proxy in a clean way.</p>
<p>Then if you change your Web Service signature, you have to rebuild your Proxy. This can be troublesome especially if more than one person is working on the same project (can be avoided using build scripts to rebuild proxy automatically during compilation but still i don&#8217;t like that).</p>
<p>Also invoking web service methods asynchronously is tedious work in terms of writing the same code over and over again.</p>
<p>You have to subscribe to the OnCompleted event, and then invoke the actual asynchronous method, and then when your OnComplete handler is invoked, you can process the results of the web service method.</p>
<p>Not to mention the lifetime of the generated proxy, and handling exceptions that could be thrown in the service etc.</p>
<p>So as we see Visual Studio (or command line) proxy generating helps us in many ways but also brings new problems that are hard to solve.</p>
<p>I figured that there has to be a better way to solve this everyday problem so while working on my personal MVVM framework (yes, everyone is building one these days) i was setting these goals regarding the Web Service calls from my MVVM applications:</p>
<ol>
<li>simplify as much as possible asynchronous invocation of Web Service methods (avoid writing boring boilerplate code for each call)</li>
<li>get rid of the Add Service Reference approach completely if possible</li>
<li>make the Web Services unit testable (hide them behind some interface so we can mock them in our unit tests)</li>
<li>simplify exception handling</li>
<li>fault tolerance (if web service client is faulted by exception it should be automatically recreated)</li>
</ol>
<p>If this list of features looks interesting to you then you will soon see that all this is possible in a simple way by using ChannelFactory&lt;T&gt; and creating the Web Service client channel for the web service manually.</p>
<p>So lets start:  In our example we will be using a fake WeatherForecast web service that will have just one method GetForecast and it will accept DateTime as parameter and return a simple class DailyForecast as a result that will have some fake data just to have something to work with.</p>
<p>First of all we need to create a service contract interface for WeatherForecastWebService and since we must allow the Silverlight client to call this web service asynchronously we will add conditional compilation code regions in the interface with additional asynchronous signatures for the GetForecast method (BeginGetForecast and EndGetForecast) like this:</p>
<pre class="brush: csharp; title: ; notranslate">
namespace Abstractions
{
    [ServiceContract]
    public interface IWeatherForecastService
    {

#if SILVERLIGHT
        [OperationContract(AsyncPattern=true)]
        IAsyncResult BeginGetForecast(DateTime day, AsyncCallback callback, object state);
        DailyForecast EndGetForecast(IAsyncResult result);
#else

        [OperationContract]
        DailyForecast GetForecast(DateTime day);
#endif
    }
}
</pre>
<p>and here is the DailyForecast Data Transfer Object (DTO) class that we will receive from the web service:</p>
<pre class="brush: csharp; title: ; notranslate">
namespace Abstractions
{
    [DataContract]
    public class DailyForecast
    {
        [DataMember]
        public DateTime Date { get; set; }

        [DataMember]
        public string Description { get; set; }
    }
}
</pre>
<p>Note the DataContract and DataMember attributes, they must be provided in order to receive the class on the client properly.</p>
<p>Since we are to consume the web service on the Silverlight client we must make available all the classes to the client side.</p>
<p>Here is how we are going to accomplish this: We must define service contract interface and all the classes that the service will return both on server and on the Silverlight client.  We will do that by creating a <strong>Abstractions.Web</strong> class library project that will hold the service contract interface IWeatherForecastService all the needed Data Transfer Object classes (in this example its just DailyForecast class), and then we will also create <strong>Abstractions.Silverlight </strong>- Silverlight class library project where we will add the same classes (DTO&#8217;s and service contract interface) as links &#8211; by going to to right click menu on the project and choose Add -&gt; Existing Item and add all needed files and click on Add As Link button instead of Add button.</p>
<p>here is how this setup looks in my Visual Studio instance:  <a href="http://blog.roboblob.com/wp-content/uploads/2010/04/AbstractionsProjectsVisualStudio.jpg"><img class="aligncenter size-medium wp-image-260" title="AbstractionsProjectsVisualStudio" src="http://blog.roboblob.com/wp-content/uploads/2010/04/AbstractionsProjectsVisualStudio-300x272.jpg" alt="" width="300" height="272" /></a> So now that we have same set of shared classes on client and on the server we can proceed with creating a web service helper class that will allow us to invoke asynchronous methods in a simple way without having to do lot of boilerplate code.  As we said we want to be able to mock that helper in our Unit Tests we need to have an interface for it so lets define that first:</p>
<pre class="brush: csharp; title: ; notranslate">
namespace Framework.Abstractions.Silverlight.WebServices
{
    public interface IWebServiceClientFactory&lt;TWebService&gt; :  IDisposable
    {
        TWebService WebServiceInstance
        {
            get;
        }

        void Invoke&lt;TParam, TResult&gt;(TParam param, object state,
                                     Func&lt;TParam, AsyncCallback, object, IAsyncResult&gt; beginOp,
                                     Func&lt;IAsyncResult, TResult&gt; endOp,
                                     Action&lt;AsyncWebServiceCallResult&lt;TResult&gt;&gt; onComplete);

    }
}
</pre>
<p>As you can see we are defining the WebServiceClientFactory of TWebService that will expose a web service client instance WebServiceInstance if we want to call it directly but more important will be the generic <strong>Invoke </strong>method for generic asynchronous calls that will allow to call any method on any web service in a simple way just by specifying the parameter, then the begin and end method we want to calla and a method that should be called with the received results when web service call is finished.</p>
<p>Our helper class will also implement IDisposable so we can cleanup properly.</p>
<p>Let us investigate the Invoke method. From its signature we see that it is a generic function and that it has two type parameters, <strong>TParam </strong>that is the type of the parameter sent to our web service when we invoke the web method, and <strong>TResult </strong>that is the type of the result we expect from the method.</p>
<p>Then there is a object state that we want to send to the web service method (we can pass NULL there if we don&#8217;t need it).</p>
<p>And then comes the fun part: Parameter <strong>beginOp </strong>is a BEGIN* method that will be invoked, and parameter <strong>endOp </strong>is the END* method that will be invoked for the web service call. In our case we will supply here BeginGetForecast and EndGetForecast methods using the WebServiceInstance property of the same factory class. But its important to note here that if our web service would have other methods that support asynchronous invoking with these BEGIN* and END* signatures, we could call them in same way, just passing another pair of Begin* and End* methods.</p>
<p>Last parameters is an Action&gt; that will be called when the web method call is finished. This action will receive the instance of custom generic class AsyncWebServiceCallResult whose type parameter is the DailyForecast &#8211; result we would normally expect from the web method.  So here is the definition of generic AsyncWebServiceCallResult class:</p>
<pre class="brush: csharp; title: ; notranslate">
namespace Framework.Abstractions.Silverlight.WebServices
{
    public class AsyncWebServiceCallResult&lt;TResult&gt;
    {
        public TResult Result { get; set; }
        public bool WasSuccessfull { get; set;}
        public Exception Exception { get; set; }
    }
}
</pre>
<p>So this class is just a wrapper around the TResult we would usually receive from the web service method call and it adds just two more properties: boolean <strong>WasSuccessfull </strong>and <strong>Exception</strong>.  If web method call is executed without problems WasSuccessfull is set to true and Exception is null, and on the other hand if there is some exception thrown during the invocation of the web service method call Exception will hold the Exception thrown and WasSuccessfull will be set to false.</p>
<p>So lets see how we would use this Web Service factory to call our WeatherForecastService:</p>
<pre class="brush: csharp; title: ; notranslate">
var weatherServiceFactory = SimpleServiceLocator.Instance.Retrieve&lt;IWebServiceClientFactory&lt;IWeatherForecastService&gt;&gt;();
weatherServiceFactory.Invoke(date, null,
                                          weatherServiceFactory.WebServiceInstance.BeginGetForecast,
                                          weatherServiceFactory.WebServiceInstance.EndGetForecast,
                                          this.OnResultReceived);
</pre>
<p>And the method that will be called when results is received would look like this:</p>
<pre class="brush: csharp; title: ; notranslate">
        private void OnResultReceived(AsyncWebServiceCallResult&lt;DailyForecast&gt; asyncResult)
        {
            if (asyncResult.WasSuccessfull)
            {
                this.StatusMessage = &quot;New forecast received ok.&quot;;
                this.ForecastThatWasReceived = asyncResult.Result;

            }
            else
            {
                this.ForecastThatWasReceived = null;
                this.StatusMessage = &quot;Error result received: Error description: &quot; + asyncResult.Exception.Message;
            }
        }
</pre>
<p>And you can use this generic helper class to create wrapper around ANY web service exposed to your Silverlight application.</p>
<p>You just instantiate this class giving it the contract interface of the desired web service and URL of the web service.</p>
<p>WebServiceClientFactory will do all the plumbing for you and create ChannelFactory and web service client and expose it in WebServiceInstance property.</p>
<p>Then you can use Invoke method of the class to call ANY web service method with single line of code (you need on complete action to receive the result but you cannot avoid that &#8211; its asynchronous call after all).</p>
<p>Usable?  <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>So now that you have seen how we would use the interface of our web service factory, lets see how its really implemented:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Windows;
using Framework.Abstractions.Silverlight.WebServices;
using System.Linq.Expressions;

namespace Framework.Implementors.Silverlight.WebServices
{
    public class WebServiceClientFactory&lt;TWebService&gt; : IWebServiceClientFactory&lt;TWebService&gt; where  TWebService : class
    {
        private CustomBinding binding;
        private readonly string endpointAddress;
        private ChannelFactory&lt;TWebService&gt; channelFactory;

        public WebServiceClientFactory(CustomBinding binding, string endpointAddress)
        {
            this.binding = binding;
            this.endpointAddress = endpointAddress;
        }

        public WebServiceClientFactory(string endpointAddress)
        {
            this.endpointAddress = endpointAddress;
        }

        public TWebService WebServiceInstance
        {
            get
            {
                if (this.channelFactory == null || this.channel == null)
                {
                    this.InitializeWeatherServiceClient();
                }

                return this.channel;
            }

            private set
            {
                this.channel = value;
            }
        }
        private TWebService channel;

        private void InitializeWeatherServiceClient()
        {
            Debug.WriteLine(&quot;Initializing factory and channel in &quot; + this.GetType().Name);
            if (this.binding == null)
            {
                var elements = new List&lt;BindingElement&gt;();
                elements.Add(new BinaryMessageEncodingBindingElement());
                elements.Add(new HttpTransportBindingElement());
                this.binding = new CustomBinding(elements);
            }

            channelFactory = new ChannelFactory&lt;TWebService&gt;(this.binding, new EndpointAddress(endpointAddress));
            channel = this.GetNewChannelFromCurrentFactory();
        }

        public void Invoke&lt;TParam, TResult&gt;(TParam param, object state, Func&lt;TParam, AsyncCallback, object, IAsyncResult&gt; beginOp, Func&lt;IAsyncResult, TResult&gt; endOp, Action&lt;AsyncWebServiceCallResult&lt;TResult&gt;&gt; onComplete)
        {
            beginOp(param, (ar) =&gt;
                {
                    var asyncResult = new AsyncWebServiceCallResult&lt;TResult&gt;();
                    try
                    {
                        asyncResult.Result = endOp(ar);
                        asyncResult.WasSuccessfull = true;
                    }
                    catch (Exception e)
                    {
                        asyncResult.WasSuccessfull = false;
                        asyncResult.Exception = e;
                    }

                    if (Deployment.Current.Dispatcher.CheckAccess())
                    {
                        onComplete(asyncResult);
                    }
                    else
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =&gt; onComplete(asyncResult));
                    }

                }, state );
        }

        private TWebService GetNewChannelFromCurrentFactory()
        {

            var newChannel = channelFactory.CreateChannel();

            var channelAsCommunicationObject = (newChannel as ICommunicationObject);
            if (channelAsCommunicationObject != null)
            {
                channelAsCommunicationObject.Faulted += ChannelFaulted;
            }

            return newChannel;
        }

        void ChannelFaulted(object sender, EventArgs e)
        {
            Debug.WriteLine(&quot;Service channel faulted in &quot; + this.GetType().Name);
            var communicationObject = (this.channel as ICommunicationObject);
            if (communicationObject != null)
            {
                communicationObject.Abort();

                this.channel = this.GetNewChannelFromCurrentFactory();
            }
        }

        ~WebServiceClientFactory()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
        }

        protected void Dispose(bool disposing)
        {
            if (disposing)
            {
                // dispose managed stuff
                Debug.WriteLine(&quot;Disposing managed resources in &quot; + this.GetType().Name);
                var communicationObject = (this.channel as ICommunicationObject);
                if (communicationObject != null)
                {
                    communicationObject.Faulted -= this.ChannelFaulted;

                    try
                    {
                        communicationObject.Close();
                    }
                    catch (Exception)
                    {
                        try
                        {
                            communicationObject.Abort();
                        }
                        catch
                        {
                        }
                    }
                }
            }

            // here we would dispose unmanaged stuff
        }

    }
}
</pre>
<p>Class has multiple constructors so you can choose how to set it up. The simplest usage is just to specify the string URL of the web service. Here is how i setup my IOC in the bootstrapper of my Silverlight application:</p>
<pre class="brush: csharp; title: ; notranslate">
SimpleServiceLocator.Instance.RegisterAsSingleton&lt;IWebServiceClientFactory&lt;IWeatherForecastService&gt;&gt;
(new WebServiceClientFactory&lt;IWeatherForecastService&gt;(&quot;http://localhost:1000/WeatherForecastService.svc&quot;));
</pre>
<p>When constucted like this factory class uses standard Binding that would be created for you if you would add the Web Service Reference from visual studio and it will use that Binding and that given URL as endpoint to create a generic ChannelFactory of the web service type provided in  type param</p>
<p>&lt;TWebService&gt; and then it will create a communication channel to communicate with web service of given type on the given URL.</p>
<p>Here is the code that is doing this part:</p>
<pre class="brush: csharp; title: ; notranslate">
        private void InitializeWeatherServiceClient()
        {
            Debug.WriteLine(&quot;Initializing factory and channel in &quot; + this.GetType().Name);
            if (this.binding == null)
            {
                var elements = new List&lt;BindingElement&gt;();
                elements.Add(new BinaryMessageEncodingBindingElement());
                elements.Add(new HttpTransportBindingElement());
                this.binding = new CustomBinding(elements);
            }

            channelFactory = new ChannelFactory&lt;TWebService&gt;(this.binding, new EndpointAddress(endpointAddress));
            channel = this.GetNewChannelFromCurrentFactory();
        }
</pre>
<p>There is a another constructor that accepts Binding if you want to provide your own.<br />
Next interesting part of the class is the Invoke method:</p>
<pre class="brush: csharp; title: ; notranslate">
        public void Invoke&lt;TParam, TResult&gt;(TParam param, object state, Func&lt;TParam, AsyncCallback, object, IAsyncResult&gt; beginOp, Func&lt;IAsyncResult, TResult&gt; endOp, Action&lt;AsyncWebServiceCallResult&lt;TResult&gt;&gt; onComplete)
        {
            beginOp(param, (ar) =&gt;
                {
                    var asyncResult = new AsyncWebServiceCallResult&lt;TResult&gt;();
                    try
                    {
                        asyncResult.Result = endOp(ar);
                        asyncResult.WasSuccessfull = true;
                    }
                    catch (Exception e)
                    {
                        asyncResult.WasSuccessfull = false;
                        asyncResult.Exception = e;
                    }

                    if (Deployment.Current.Dispatcher.CheckAccess())
                    {
                        onComplete(asyncResult);
                    }
                    else
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =&gt; onComplete(asyncResult));
                    }

                }, state );
        }
</pre>
<p>As you can see no big deal there, we just invoke the BEGIN* operation with lambda method as complete handler where we wrap the call to END* operation in Try..Catch so we can recover from any exception.<br />
If there was an exception we set WasSuccessfull to false and Exception property.<br />
If all went ok we populate the Result property with the result of the web method call and then we invoke the onComplete action that was supplied by the user of the class.<br />
But we make sure that we invoke it on the UI thread just as a convenience for the user so he does not need to do it by himself.</p>
<p>One more important thing is that if our web service channel gets faulted by some communication error we will catch that event and recreate the channel:</p>
<pre class="brush: csharp; title: ; notranslate">
        void ChannelFaulted(object sender, EventArgs e)
        {
            Debug.WriteLine(&quot;Service channel faulted in &quot; + this.GetType().Name);
            var communicationObject = (this.channel as ICommunicationObject);
            if (communicationObject != null)
            {
                communicationObject.Abort();

                this.channel = this.GetNewChannelFromCurrentFactory();
            }
        }
</pre>
<p>Previously, we subscribed that method to the OnFaulted event on the channel.</p>
<p>Other parts of the class are not too much interesting so you can dig yourself if you want.</p>
<p>So lets see how we would use the class in our view model.<br />
Here is the listing of the ForecastViewModel that will allow us to invoke the WeatherForecast web service:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using Abstractions;
using Framework.Abstractions.Silverlight.Intefaces;
using Framework.Abstractions.Silverlight.WebServices;
using Framework.Implementors.Silverlight.Comanding;
using Framework.Implementors.Silverlight.MVVM;

namespace ViewModels
{
    public class ForecastViewModel : ViewModel
    {
        private readonly IWebServiceClientFactory&lt;IWeatherForecastService&gt; weatherServiceFactory;

        public ForecastViewModel(IWebServiceClientFactory&lt;IWeatherForecastService&gt; weatherServiceFactory)
        {
            this.weatherServiceFactory = weatherServiceFactory;

            this.GetForecastCommand =
                new DelegateCommand&lt;DateTime&gt;(
                    date =&gt;
                    {
                        this.StatusMessage = string.Format(&quot;Invoking web service with parameter {0}&quot;, date.ToString());
                        this.weatherServiceFactory.Invoke(
date,
null,
this.weatherServiceFactory.WebServiceInstance.BeginGetForecast,

this.weatherServiceFactory.WebServiceInstance.EndGetForecast,

this.OnResultReceived);

                    });

        }

        private void OnResultReceived(AsyncWebServiceCallResult&lt;DailyForecast&gt; asyncResult)
        {
            if (asyncResult.WasSuccessfull)
            {
                this.StatusMessage = &quot;New forecast received ok.&quot;;
                this.ForecastThatWasReceived = asyncResult.Result;

            }
            else
            {
                this.ForecastThatWasReceived = null;
                this.StatusMessage = &quot;Error result received: Error description: &quot; + asyncResult.Exception.Message;
            }
        }

        private IDelegateCommand getForecastCommand;

        public IDelegateCommand GetForecastCommand
        {
            get { return getForecastCommand; }
            set { getForecastCommand = value;
                this.OnPropertyChanged(&quot;GetForecastCommand&quot;);
            }
        }

        private DailyForecast forecastThatWasReceived;

        public DailyForecast ForecastThatWasReceived
        {
            get { return forecastThatWasReceived; }
            set { forecastThatWasReceived = value;
            this.OnPropertyChanged(&quot;ForecastThatWasReceived&quot;);
            }
        }

        public DateTime ValidForecastDate
        {
            get
            {
                return DateTime.Now;
            }
        }

        public DateTime BadForecastDate
        {
            get
            {
                return DateTime.MinValue;
            }
        }

        private string statusMessage;
        public string StatusMessage
        {
            get { return statusMessage; }
            set { statusMessage = value;
            this.OnPropertyChanged(&quot;StatusMessage&quot;);
            }
        }
    }
}
</pre>
<p>As you can see from the ForecastViewModel we have a command that&#8217;s invoking the web service called GetForecastCommand and we have a action method OnResultReceived that receives the result.</p>
<p>If the web service call fails we set the ForecastThatWasReceived to null and we set the StatusMessage to the Message of the Exception we received from server.</p>
<p>So here is our simple ForecastView:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;UserControl x:Class=&quot;Views.ForecastView&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable=&quot;d&quot;
    d:DesignHeight=&quot;300&quot; d:DesignWidth=&quot;400&quot; MinHeight=&quot;400&quot; MinWidth=&quot;400&quot;&gt;

    &lt;Grid x:Name=&quot;LayoutRoot&quot; Background=&quot;Red&quot;&gt;

        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition&gt;&lt;/RowDefinition&gt;
            &lt;RowDefinition&gt;&lt;/RowDefinition&gt;
            &lt;RowDefinition&gt;&lt;/RowDefinition&gt;
        &lt;/Grid.RowDefinitions&gt;
        &lt;StackPanel Orientation=&quot;Vertical&quot; Grid.Row=&quot;0&quot;&gt;
            &lt;Button Content=&quot;Invoke valid web service call&quot; Command=&quot;{Binding GetForecastCommand}&quot; CommandParameter=&quot;{Binding ValidForecastDate}&quot; HorizontalAlignment=&quot;Center&quot; VerticalAlignment=&quot;Center&quot; Margin=&quot;10&quot; /&gt;

            &lt;Button Content=&quot;Invoke web service call that throws exception on server&quot; Command=&quot;{Binding GetForecastCommand}&quot; CommandParameter=&quot;{Binding BadForecastDate}&quot; HorizontalAlignment=&quot;Center&quot; VerticalAlignment=&quot;Center&quot; Margin=&quot;10&quot; /&gt;

        &lt;/StackPanel&gt;

        &lt;Grid Grid.Row=&quot;1&quot;&gt;
            &lt;StackPanel Orientation=&quot;Vertical&quot;&gt;
                &lt;TextBlock Text=&quot;{Binding ForecastThatWasReceived.Date, StringFormat='Date: {0}', FallbackValue=' ?'}&quot; /&gt;
                &lt;TextBlock Text=&quot;{Binding ForecastThatWasReceived.Description, StringFormat='Description: {0}', FallbackValue=' ?'}&quot; /&gt;

            &lt;/StackPanel&gt;
        &lt;/Grid&gt;

        &lt;Grid Grid.Row=&quot;2&quot;&gt;
            &lt;TextBlock Text=&quot;{Binding StatusMessage}&quot; TextWrapping=&quot;Wrap&quot; /&gt;

        &lt;/Grid&gt;

    &lt;/Grid&gt;
&lt;/UserControl&gt;
</pre>
<p>As you can see we have two buttons, each wired up to the same GetForecastCommand but with different parameters.<br />
One is sending the current date to the server and other is using the BadForecastDate databound from ViewModel which is set to DateTime.Min. When web service receives any other date then DateTime.Min it returns valid instance of DailyForecast class and if it receives DateTime.Min it throws some bogus exception.<br />
This is how we will test our WebServiceFactory class to see if it can handle the exceptions thrown on server side or not.</p>
<p>you can test the <a title="Unit Testable Web Service in MVVM and Silverlight 4 demo application" href="http://demos.roboblob.com/demos/Silverlight4/MVVM/TestableWebServices/" target="_blank">live sample application here</a>.</p>
<p>So here is screenshot of the app (in case you dont have the <a href="http://www.silverlight.net/getstarted/" target="_self">Silverlight 4 runtime</a> installed) when we invoke the web service with current date:</p>
<p><a href="http://blog.roboblob.com/wp-content/uploads/2010/04/WebServiceCallOk.jpg"><img class="aligncenter size-medium wp-image-268" title="WebServiceCallOk" src="http://blog.roboblob.com/wp-content/uploads/2010/04/WebServiceCallOk-300x248.jpg" alt="" width="300" height="248" /></a></p>
<p>As you can see when we click on first button we receive the valid forecast and when we click the second one, we will receive the error but it will be catched and wrapped in our AsyncWebServiceCallResult class and our UI won&#8217;t hang and we will be able to recover from that error and immediately invoke the web service call again with different parameters.</p>
<p>Here is the same app when we invoke the web service method with invalid (min) date so it throws exception:</p>
<p><a href="http://blog.roboblob.com/wp-content/uploads/2010/04/WebServiceCallBad.jpg"><img class="aligncenter size-medium wp-image-269" title="WebServiceCallBad" src="http://blog.roboblob.com/wp-content/uploads/2010/04/WebServiceCallBad-300x248.jpg" alt="" width="300" height="248" /></a></p>
<p>So this should help us handle the web service with greater ease right ?  <img src='http://blog.roboblob.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>But wait! We are not finished yet! Those of you that were paying attention noticed i promised a unit testable web services.</p>
<p>So lets do that also.</p>
<p>We will add another SIlverlight application to our sample code and set it up with Silverlight Unit Testing Framework.</p>
<p>Also we will reference all the needed projects &#8211; ViewModels, Abstractions.Silverlight, Framework.Abstractions and Framework.Implementors.</p>
<p>Also we need to make a fake WebServiceClientFactory and IWeatherService implementations so we can use them in our tests instead of the real implementations.</p>
<p>So lets do that first. here is the FakeWebServiceClientFactory:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using Abstractions;
using Framework.Abstractions.Silverlight.WebServices;

namespace Silverlight.Tests
{
    public class FakeWebServiceClientFactory : IWebServiceClientFactory&lt;IWeatherForecastService&gt;
    {
        public FakeWebServiceClientFactory()
        {
            this.WebServiceInstance = new FakeWeatherService();
        }

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public IWeatherForecastService WebServiceInstance { get; private set; }

        public object LastParameterSentToInvoke;

        public object NextResultToReturn;

        public void Invoke&lt;TParam, TResult&gt;(TParam param, object state, Func&lt;TParam, AsyncCallback, object, IAsyncResult&gt; beginOp, Func&lt;IAsyncResult, TResult&gt; endOp, Action&lt;AsyncWebServiceCallResult&lt;TResult&gt;&gt; onComplete)
        {
            this.LastParameterSentToInvoke = param;

            var nextResult = NextResultToReturn as AsyncWebServiceCallResult&lt;TResult&gt;;

            if (nextResult != null)
            {
                onComplete(nextResult);
            }
            else
            {
                onComplete(new AsyncWebServiceCallResult&lt;TResult&gt;
                               {Exception = new Exception(&quot;Some exception&quot;), WasSuccessfull = false});
            }
        }
    }
}
</pre>
<p>As you can see it does not do much, its just a manually written mock class we can use in our test instead of the real web service client factory.<br />
It allows us to check what was sent to the Invoke method as parameter and it allows us to set what will be sent to the OnComplete handler when client code invokes some web service call.</p>
<p>Also we need a stub for the IWeatherForecastService so here it is:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using Abstractions;

namespace Silverlight.Tests
{
    public class FakeWeatherService : IWeatherForecastService
    {
        public IAsyncResult BeginGetForecast(DateTime day, AsyncCallback callback, object state)
        {
            throw new NotImplementedException();
        }

        public DailyForecast EndGetForecast(IAsyncResult result)
        {
            throw new NotImplementedException();
        }
    }
}
</pre>
<p>Again its very simple its just a Stub class that allows us to instantiate and use it without really calling it.<br />
So now we can write few tests for our ForecastViewModel:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using Abstractions;
using Framework.Abstractions.Silverlight.WebServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ViewModels;

namespace Silverlight.Tests
{
    [TestClass]
    public class ForecastViewModelTests
    {
        [TestMethod]
        public void GetForecastCommand_WhenExecutedWithParam_InvokesCallOnWebServiceClientFactoryInstance()
        {
            var fakeFactory = new FakeWebServiceClientFactory();
            var viewModel = new ForecastViewModel(fakeFactory);

            var date = DateTime.Now;

            viewModel.GetForecastCommand.Execute(date);

            Assert.AreEqual(date, fakeFactory.LastParameterSentToInvoke);
        }

        [TestMethod]
        public void GetForecastCommand_WhenExecutedWithMinDateANdWebserviceReturnsUnsuccessfullResult_SetsTheForecastThatWasReceivedToNull()
        {
            var fakeFactory = new FakeWebServiceClientFactory();
            var viewModel = new ForecastViewModel(fakeFactory);
            viewModel.ForecastThatWasReceived = new DailyForecast() {Description = &quot;just dummy so we can test if it was set to null.&quot;};

            fakeFactory.NextResultToReturn = new AsyncWebServiceCallResult&lt;DailyForecast&gt;() {WasSuccessfull = false, Exception = new Exception(&quot;Bad error.&quot;)};
            viewModel.GetForecastCommand.Execute(DateTime.MinValue);

            Assert.IsNull(viewModel.ForecastThatWasReceived);
        }

        [TestMethod]
        public void GetForecastCommand_WhenExecutedWithMinDateANdWebserviceReturnsUnsuccessfullResult_SetsTheStatusMessageToErrorFromReturnedException()
        {
            var fakeFactory = new FakeWebServiceClientFactory();
            var viewModel = new ForecastViewModel(fakeFactory);
            viewModel.ForecastThatWasReceived = new DailyForecast() { Description = &quot;just dummy so we can test if it was set to null.&quot; };

            fakeFactory.NextResultToReturn = new AsyncWebServiceCallResult&lt;DailyForecast&gt;() { WasSuccessfull = false, Exception = new Exception(&quot;Bad error.&quot;) };
            viewModel.GetForecastCommand.Execute(DateTime.MinValue);

            Assert.IsTrue(viewModel.StatusMessage.Contains(&quot;Bad error.&quot;));
        }

        [TestMethod]
        public void GetForecastCommand_WhenExecutedWithOkDateANdWebserviceReturnsSuccessfullResult_SetsTheStatusMessageToOkMessage()
        {
            var fakeFactory = new FakeWebServiceClientFactory();
            var viewModel = new ForecastViewModel(fakeFactory);
            viewModel.ForecastThatWasReceived = null;

            fakeFactory.NextResultToReturn = new AsyncWebServiceCallResult&lt;DailyForecast&gt;() { WasSuccessfull = true};
            viewModel.GetForecastCommand.Execute(DateTime.Now);

            Assert.IsTrue(viewModel.StatusMessage.Contains(&quot;New forecast received ok.&quot;));
        }

    }
}
</pre>
<p>And when we run them, as you can see from the screenshot below, they are all <span style="color: #008000;">GREEN!</span></p>
<p><span style="color: #008000;"><a href="http://blog.roboblob.com/wp-content/uploads/2010/04/AllTestsAreGreenAndTheWorldIsSafeAgain.jpg"><img class="aligncenter size-medium wp-image-271" title="AllTestsAreGreenAndTheWorldIsSafeAgain" src="http://blog.roboblob.com/wp-content/uploads/2010/04/AllTestsAreGreenAndTheWorldIsSafeAgain-300x178.jpg" alt="" width="300" height="178" /></a></span></p>
<p><span style="color: #008000;"><span style="color: #000000;">So there you go, we have completed in this lengthy posts most of the tasks we set in the beginning. Off course there are many places for improvement but the basis of a simple way to invoke WCF web services from Silverlight and MVVM and Unit Testability are there.</span></span></p>
<p><span style="color: #008000;"><span style="color: #000000;">If you have some comments and improvements to the solutions presented here i would be happy to hear them out.</span></span></p>
<p><span style="color: #008000;"><span style="color: #000000;">You can <a title="Unit Testable Web Service in MVVM and Silverlight 4 Solution Visual Studio 2010" href="http://demos.roboblob.com/demos/Silverlight4/MVVM/TestableWebServices/TestableWebServicesInMVVMSilverlight4Solution.zip" target="_self">download Visual Studio 2010 Solution</a> with the code from this post if you want to run it locally.<br />
</span></span></p>
<p><span style="color: #008000;"><span style="color: #000000;">Until then, happy testing!<br />
</span></span></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F&amp;headline=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4&amp;u=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F&amp;title=Unit+Testable+WCF+Web+Services+in+MVVM+and+Silverlight+4&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fblog.roboblob.com%2F2010%2F04%2F11%2Funit-testable-wcf-web-services-in-mvvm-and-silverlight-4%2F" ><img class="lightsocial_img" src="http://blog.roboblob.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><img src="http://feeds.feedburner.com/~r/roboblob/~4/sUdzJ46DJpo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.roboblob.com/2010/04/11/unit-testable-wcf-web-services-in-mvvm-and-silverlight-4/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

