<?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:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/" version="2.0">
    <channel>
        <title>Brian Genisio's House of Bilz</title>
        <link>http://houseofbilz.com/Default.aspx</link>
        <description> </description>
        <language>en-US</language>
        <copyright>Brian Genisio's House Of Bilz</copyright>
        <managingEditor>BrianGenisio@Gmail.Com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <image>
            <title>Brian Genisio's House of Bilz</title>
            <url>http://houseofbilz.com/images/RSS2Image.gif</url>
            <link>http://houseofbilz.com/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/genisio" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="genisio" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
            <title>Prism Slides and Demo</title>
            <link>http://houseofbilz.com/archive/2010/03/11/prism-slides-and-demo.aspx</link>
            <description>&lt;p&gt;I recently gave a presentation on Prism at the &lt;a href="http://aadnd.org/"&gt;Ann Arbor .Net Users Group&lt;/a&gt;.  I have made my slides and demo available for download:&lt;/p&gt;  &lt;h3&gt;&lt;a href="http://houseofbilz.net/Prism/Prism.pptx"&gt;Slides&lt;/a&gt;   &lt;a href="http://houseofbilz.net/Prism/PrismExample.zip"&gt;Demo&lt;/a&gt;&lt;/h3&gt;  &lt;p&gt;Some interesting links associated with prism:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://tinyurl.com/Prism2"&gt;Composite Application Guidance&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://tinyurl.com/Prism2-CAL "&gt;Composite Application Library&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codeplex.com/CompositeWPF/"&gt;Codeplex Site&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://tinyurl.com/Prism2-Videos"&gt;Great 4-part video series&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2009/10/27/prism-and-silverlight-screencasts-on-channel-9.aspx"&gt;Another video series&lt;/a&gt; that &lt;a href="http://www.davidgiard.com/"&gt;David Giard&lt;/a&gt; pointed me towards&lt;/li&gt; &lt;/ul&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138478"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138478" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/138478.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2010/03/11/prism-slides-and-demo.aspx</guid>
            <pubDate>Fri, 12 Mar 2010 11:50:37 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/138478.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2010/03/11/prism-slides-and-demo.aspx#feedback</comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/138478.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/138478.aspx</trackback:ping>
        </item>
        <item>
            <title>MVVM Jam &amp;ndash; A Solution</title>
            <link>http://houseofbilz.com/archive/2010/03/02/mvvm-jam-ndash-a-solution.aspx</link>
            <description>&lt;p&gt;Thanks to all who came to the MVVM jam tonight.  In case you wanted to see what a completed solution looks like, you can download it &lt;a href="http://houseofbilz.net/MVVMJam/MVVM-Jam-Complete.zip"&gt;here&lt;/a&gt;.  There are many tweaks that can be made, and it is certainly not the only solution… but hopefully, it helps to understand how the MVVM pattern can be applied.&lt;/p&gt;  &lt;p&gt;Next week (Wednesday, March 9th) , I will be giving a presentation on &lt;a href="http://compositewpf.codeplex.com/"&gt;Prism&lt;/a&gt; for Silverlight and WPF at the &lt;a href="http://aadnd.org/"&gt;Ann Arbor .Net Users’ Group&lt;/a&gt;.  It is an eyes-forward talk about more patterns similar to MVVM.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138289"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138289" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/138289.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2010/03/02/mvvm-jam-ndash-a-solution.aspx</guid>
            <pubDate>Wed, 03 Mar 2010 03:08:08 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/138289.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2010/03/02/mvvm-jam-ndash-a-solution.aspx#feedback</comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/138289.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/138289.aspx</trackback:ping>
        </item>
        <item>
            <title>MVVM Jam -- Prerequisites</title>
            <link>http://houseofbilz.com/archive/2010/02/27/mvvm-jam----prerequisites.aspx</link>
            <description>&lt;p&gt;For those in the Ann Arbor, Michigan area, you might be familiar with the “&lt;a href="http://www.comejamwithus.org/"&gt;Come Jam With Us&lt;/a&gt;” project.  Every week, we get together for an hour and code on a particular topic.  It is usually led by one or two people and the rest of the group codes along in order to learn about the topic at hand.  It is a really great forum for learning new concepts and technologies.&lt;/p&gt;  &lt;p&gt;This week, on Tuesday, March 2nd, I will be hosting an MVVM jam session at 5:30 (&lt;a href="http://www.comejamwithus.org/where-you-can-find-us"&gt;directions&lt;/a&gt;).  I will be taking you through the process of transforming a “Ball of Mud” application to use the MVVM architecture.  We will do this in a test-driven way, so you can see the testability story of MVVM.&lt;/p&gt;  &lt;p&gt;The prerequisites are very simple:&lt;/p&gt;  &lt;p&gt;1. Visual Studio 2008 or 2010 or &lt;a href="http://www.microsoft.com/express/"&gt;Visual Studio Express&lt;/a&gt; (free)&lt;/p&gt;  &lt;p&gt;2. Download the &lt;a href="http://HouseOfBilz.net/MVVMJam/MVVM-Jam.ModelExtracted.zip"&gt;sample project&lt;/a&gt;.  It is a rudimentary Twitter search application written with WPF.&lt;/p&gt;  &lt;p&gt;3. You should have some way of running NUnit tests from Visual Studio.  If you have &lt;a href="http://www.jetbrains.com/resharper/index.html"&gt;ReSharper&lt;/a&gt; or &lt;a href="http://testdriven.net/"&gt;TestDriven.Net&lt;/a&gt; (or any similar plug-in), then you are all set.  ReSharper has a free 30 day trial and TestDriven.Net has a free version for personal use.&lt;/p&gt;  &lt;p&gt;I hope to see you there!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138229"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138229" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/138229.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2010/02/27/mvvm-jam----prerequisites.aspx</guid>
            <pubDate>Sun, 28 Feb 2010 02:45:49 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/138229.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2010/02/27/mvvm-jam----prerequisites.aspx#feedback</comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/138229.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/138229.aspx</trackback:ping>
        </item>
        <item>
            <title>Goodbye XML&amp;hellip; Hello YAML (part 1)</title>
            <link>http://houseofbilz.com/archive/2010/02/21/goodbye-xmlhellip-hello-yaml-part-1.aspx</link>
            <description>&lt;p&gt;This is the first in a many-part series in which I will be writing about using YAML in the .Net space – particularly within C#.  I will cover the whys, the hows, and show some tricks using the dynamic capabilities of C# when using YAML.  I might even explore IronRuby a bit.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h5&gt;Why YAML?&lt;/h5&gt;  &lt;p&gt;I got the chance to sit in on four days of Ruby on Rails (RoR) training from &lt;a href="http://objo.com/"&gt;Joe Obrien&lt;/a&gt; a few weeks ago.  I hadn’t played with RoR in a few months, and this training was amazingly useful.  I always like to see what I can take away from an environment like this for the work I do more regularly.&lt;/p&gt;  &lt;p&gt;In this case, one of the things I took away with me was YAML.  Let me start with some background.&lt;/p&gt;  &lt;p&gt;Over 10 years ago, when XML was touted as a human-readable data format, I had to scoff.  Was XML really human readable?  Well, from a software developer’s perspective, it sure is a lot nicer than binary.  But, from a REAL human’s perspective, XML is just barely more readable than Klingon.  This is mostly due to the verbose nature of XML and the often ranted about “&lt;a href="http://www.google.com/search?q=angle+bracket+tax"&gt;angle bracket tax&lt;/a&gt;”.    &lt;/p&gt;  &lt;p&gt;10 years later, we are still using XML as our primary data transfer/persistence/definition format.  I certainly don’t mind using XML in a world where I (a human) rarely need to read the data.  I am fine with keeping the data in my REST services as XML, for instance.  In that case, my tools abstract it away and I don’t have to read it very often.&lt;/p&gt;  &lt;p&gt;Currently, my colleague &lt;a href="http://srtsolutions.com/blogs/mikewoelmer/"&gt;Mike Woelmer&lt;/a&gt; and I have a client who needs us to develop an engine where the business rules will be entered by a human (not a developer) and will change as the project evolves.  The data/rules will be set in stone once the project is complete.  XML is a bad choice for this, since a non-technical person will be entering the rules.  At the same time, developing a UI for this is too time consuming and out of the scope of the project.  My first thought: a &lt;a href="http://en.wikipedia.org/wiki/Domain_specific_language"&gt;Doman Specific Language&lt;/a&gt; (DSL)!  That would certainly lend well to my requirements.  As much as I liked that idea, I didn’t have time to create a DSL either, especially while spiking.  Then I remembered back to my RoR training.  I remembered a data format called &lt;a href="http://yaml.org/"&gt;YAML&lt;/a&gt; that they used for some of the configuration files.  It was a VERY easy-to-read, hierarchical data format.&lt;/p&gt;  &lt;p&gt;To illustrate the difference between XML and YAML, here is a simple example of some rather easy-to-read XML defining the data for a recipe (unrelated to my current project):&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:9ba9f019-91ea-4a0b-adaf-8e698f42b7b3" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#EBEBEB;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;recipe&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;title&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Macaroni and Cheese&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;title&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;My favorite comfort food&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;author&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Brian Genisio&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;author&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;timeToPrepare&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;30&lt;/span&gt;&lt;span style="color: #000000;"&gt; Minutes&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;timeToPrepare&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ingredients&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ingredient&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Cheese&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;quantity&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;quantity&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;units&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;cups&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;units&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;ingredient&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ingredient&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Macaroni&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;quantity&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;16&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;quantity&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;units&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;oz&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;units&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;ingredient&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;ingredients&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;steps&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;step&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;number&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;number&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Cook the macaroni&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;step&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;step&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;number&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;number&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Melt the cheese&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;step&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;step&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;number&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;number&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
      &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Mix the cooked macaroni with the melted cheese&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;description&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;step&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;steps&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;recipe&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;

&lt;p&gt;Here is the exact same data described with YAML:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:1e7fcb62-fc62-4377-972c-b1a753ae149a" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#EBEBEB;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;Recipe:
  Title:         Macaroni and Cheese
  Description:   My favorite comfort food.
  Author:        Brian Genisio
  TimeToPrepare: 30 Minutes
  Ingredients:
    -
      Name:     Cheese
      Quantity: 3
      Units:    cups
    -
      Name:     Macaroni
      Quantity: 16
      Units:    oz
  Steps:
    -
      Number: 1
      Description: Cook the macaroni
    -
      Number: 2
      Description: Melt the cheese
    -
      Number: 3
      Description: Mix the cooked macaroni with the melted cheese&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;

&lt;p&gt;Although this is a very simple example, I would ask you: Which one would you rather present to a customer when talking about the data and business rules?  Which one would YOU rather look at when developing your software?&lt;/p&gt;

&lt;p&gt;In my next couple of posts, I will discuss some tools available to you in the .Net space and some nifty C# 4.0 techniques for working with the data.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138073"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=138073" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/138073.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2010/02/21/goodbye-xmlhellip-hello-yaml-part-1.aspx</guid>
            <pubDate>Sun, 21 Feb 2010 18:32:38 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/138073.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2010/02/21/goodbye-xmlhellip-hello-yaml-part-1.aspx#feedback</comments>
            <slash:comments>7</slash:comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/138073.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/138073.aspx</trackback:ping>
        </item>
        <item>
            <title>Adventures in MVVM &amp;ndash; CodeMash Schedule Application</title>
            <category>.NET</category>
            <category>Testing</category>
            <category>Silverlight</category>
            <link>http://houseofbilz.com/archive/2010/01/11/adventures-in-mvvm-ndash-codemash-schedule-application.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://geekswithblogs.net/HouseOfBilz/archive/2009/05/22/adventures-in-mvvm-ndash-model-view-viewmodel.aspx"&gt;More Adventures in MVVM&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, I am getting myself ready to head out to Sandusy, Ohio for three days of nerdy fun at &lt;a href="http://Codemash.org"&gt;CodeMash&lt;/a&gt;.  While I am there, I will be giving my “Introduction to the MVVM Pattern”.  In preparation for this talk, I decided to create a new demo application.  This application is a calendar and session list for the conference.  It is not terribly fancy (I wish I had more time (or talent) to skin it better), but it highlights many of the concepts that I will be speaking about in my presentation.&lt;/p&gt;
&lt;p&gt;The app is a Silverlight 3 project utilizing the Telerik Scheduler control.  This particular control is rather rich, and I was excited to get my hands dirty with it. The ViewModel for the scheduler was primarily responsible for translating session data into something the Telerik control could consume.   The app also includes a session list with a filter panel which is derived from the session data.  This is where the majority of the MVVM code can be found.  The ViewModels for the session list are responsible for dynamically creating and merging filter predicates based on the values in the session list. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/HouseOfBilz/WindowsLiveWriter/AdventuresinMVVMCodeMashScheduleApplicat_1351D/CodeMashSessions.Calendar_2.png"&gt;&lt;img width="442" height="287" border="0" src="http://geekswithblogs.net/images/geekswithblogs_net/HouseOfBilz/WindowsLiveWriter/AdventuresinMVVMCodeMashScheduleApplicat_1351D/CodeMashSessions.Calendar_thumb.png" alt="CodeMashSessions.Calendar" title="CodeMashSessions.Calendar" style="border-width: 0px; display: inline;" /&gt;&lt;/a&gt; &lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/HouseOfBilz/WindowsLiveWriter/AdventuresinMVVMCodeMashScheduleApplicat_1351D/CodeMashSessions.Sessions_2.png"&gt;&lt;img width="436" height="283" border="0" src="http://geekswithblogs.net/images/geekswithblogs_net/HouseOfBilz/WindowsLiveWriter/AdventuresinMVVMCodeMashScheduleApplicat_1351D/CodeMashSessions.Sessions_thumb.png" alt="CodeMashSessions.Sessions" title="CodeMashSessions.Sessions" style="border-width: 0px; display: inline;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can play with the application at &lt;a href="http://HouseOfBilz.net/CodeMash"&gt;http://HouseOfBilz.net/CodeMash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;CodeMashSessions Source Code: &lt;a href="http://www.houseofbilz.net/codemash/CodeMashSessions.Source.zip" title="http://www.houseofbilz.net/codemash/CodeMashSessions.Source.zip"&gt;http://www.houseofbilz.net/codemash/CodeMashSessions.Source.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Twitter "Ball of Mud" vs MVVM Source Code: &lt;a href="http://houseofbilz.net/codemash/Twitter-BallOfMud-vs-MVVM.zip"&gt;http://houseofbilz.net/codemash/Twitter-BallOfMud-vs-MVVM.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Slides from "An Introduction to the MVVM Pattern": &lt;a href="http://houseofbilz.net/codemash/MVVM.ppt"&gt;http://houseofbilz.net/codemash/MVVM.ppt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=137441"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=137441" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/137441.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2010/01/11/adventures-in-mvvm-ndash-codemash-schedule-application.aspx</guid>
            <pubDate>Tue, 12 Jan 2010 02:59:13 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/137441.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2010/01/11/adventures-in-mvvm-ndash-codemash-schedule-application.aspx#feedback</comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/137441.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/137441.aspx</trackback:ping>
        </item>
        <item>
            <title>Moving On</title>
            <link>http://houseofbilz.com/archive/2009/12/20/moving-on.aspx</link>
            <description>&lt;p&gt;Four years ago, I moved to Ann Arbor to work with a talented team on what I consider to be an important, high-quality medical application.  In that time, I had many great opportunities and I learned a ton from my colleagues.  My team is filled with some really smart people!  Because of this, I have mixed feelings to announce that I am moving on.  Starting in February, I will be working for &lt;a href="http://srtsolutions.com/blogs/billwagner/"&gt;Bill Wagner&lt;/a&gt; and &lt;a href="http://srtsolutions.com/blogs/diannemarsh/"&gt;Dianne Marsh&lt;/a&gt; and joining the team at &lt;a href="http://srtsolutions.com/"&gt;SRT Solutions&lt;/a&gt;.  It will be quite a change for me -- moving from one of the largest companies in the world to a small, local consulting company.  This job will, however, give me an opportunity to spend more time focusing on the technologies and concepts that most interest me.  I am excited for this change, and I am excited to be working directly with the many amazing members of the SRT team.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=137150"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=137150" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/137150.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2009/12/20/moving-on.aspx</guid>
            <pubDate>Mon, 21 Dec 2009 03:39:43 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/137150.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2009/12/20/moving-on.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/137150.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/137150.aspx</trackback:ping>
        </item>
        <item>
            <title>Adventures in MVVM -- Dependant Properties with INotifyPropertyChanged</title>
            <link>http://houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://geekswithblogs.net/HouseOfBilz/archive/2009/05/22/adventures-in-mvvm-ndash-model-view-viewmodel.aspx"&gt;More Adventures in MVVM&lt;/a&gt; &lt;a href="http://dotnetshoutout.com/Adventures-in-MVVM-Dependant-Properties-with-INotifyPropertyChanged" rev="vote-for"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fhouseofbilz.com%2Farchive%2F2009%2F11%2F14%2Fadventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx" /&gt;&lt;/a&gt; &lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fhouseofbilz.com%2farchive%2f2009%2f11%2f14%2fadventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fhouseofbilz.com%2farchive%2f2009%2f11%2f14%2fadventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I spend a lot of time writing ViewModels, which almost always implements &lt;strong&gt;INotifyPropertyChanged&lt;/strong&gt;.  For those who are not familiar with this interface, it includes a single event: PropertyChanged.  That event contains a payload of the name of the property that changed.  It exists as a standard way to notify observers that a property needs to be re-evaluated.&lt;/p&gt;  &lt;p&gt;Although I use it all the time, I have always believed that &lt;strong&gt;INotifyPropertyChanged&lt;/strong&gt; has some serious shortcomings.  One of those shortcomings deals with dependant properties.  &lt;/p&gt;  &lt;p&gt;Lets say, for for the sake of example, that the ViewModel has two integer properties that the user can enter (&lt;strong&gt;InputA&lt;/strong&gt; and &lt;strong&gt;InputB&lt;/strong&gt;).  There also exists a property named &lt;strong&gt;Calculation&lt;/strong&gt; that is dependent upon &lt;strong&gt;InputA&lt;/strong&gt; and &lt;strong&gt;InputB&lt;/strong&gt;.  Finally, there is a display property named &lt;strong&gt;CalculationText&lt;/strong&gt; which is dependent upon &lt;strong&gt;Calculation&lt;/strong&gt;.  The code for these properties would look like this:&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;private int _inputA;
public int InputA
{
    get { return _inputA; }
    set
    {
        if (_inputA == value) return;

        _inputA = value;
        RaisePropertyChanged("InputA");
        RaisePropertyChanged("Calculation");
        RaisePropertyChanged("CalculationText");
    }
}

private int _inputB;
public int InputB
{
    get { return _inputB; }
    set
    {
        if (_inputB == value) return;

        _inputB = value;
        RaisePropertyChanged("InputB");
        RaisePropertyChanged("Calculation");
        RaisePropertyChanged("CalculationText");
    }
}

public int Calculation
{
    get { return InputA * InputB; }
}

public string CalculationText
{
    get { return "A * B = " + Calculation; }
}&lt;/pre&gt;

&lt;p&gt;There is a problem with this code.  The input properties need to know that they are inputs for &lt;strong&gt;Calculation&lt;/strong&gt; and &lt;strong&gt;CalculationText&lt;/strong&gt; by firing the event for the calculations.  As far as I am concerned, this is the wrong place for this information to exist.  Inputs should not know that they are inputs.  I can say first hand that this quickly breaks down as the ViewModel gets bigger and you start changing behavior.&lt;/p&gt;

&lt;p&gt;The responsibility should be reversed.  Instead of having the input properties knowing about the dependants, the dependent properties should be responsible for knowing the inputs that they rely upon.  This can be done with some simple declarations:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;private int _inputA;
public int InputA
{
    get { return _inputA; }
    set
    {
        if (_inputA == value) return;

        _inputA = value;
        RaisePropertyChanged("InputA");
    }
}

private int _inputB;
public int InputB
{
    get { return _inputB; }
    set
    {
        if (_inputB == value) return;

        _inputB = value;
        RaisePropertyChanged("InputB");
    }
}

[DependsUpon("InputA")]
[DependsUpon("InputB")]
public int Calculation
{
    get { return InputA * InputB; }
}

[DependsUpon("Calculation")]
public string CalculationText
{
    get { return "A * B = " + Calculation; }
}&lt;/pre&gt;

&lt;p&gt;Notice how &lt;strong&gt;Calculation&lt;/strong&gt; declares that it is dependent upon &lt;strong&gt;InputA&lt;/strong&gt; and &lt;strong&gt;InputB&lt;/strong&gt;.  &lt;strong&gt;CalculationText&lt;/strong&gt; also declares a dependency upon &lt;strong&gt;Calculation&lt;/strong&gt;.  The inputs are free of knowing anything about the dependants.&lt;/p&gt;

&lt;p&gt;The implementation of this behavior should be handled in the base class and there are several ways to accomplish it.  There are just a few things you want to think about:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Make sure that when inputs fire a change notification, the dependants are also fired &lt;/li&gt;

  &lt;li&gt;Make sure to handle dependency chaining.  &lt;strong&gt;InputA&lt;/strong&gt; will cause &lt;strong&gt;Calculation&lt;/strong&gt; to fire and &lt;strong&gt;Calculation&lt;/strong&gt; will cause &lt;strong&gt;CalculationText&lt;/strong&gt; to fire &lt;/li&gt;

  &lt;li&gt;If the derived class declares dependencies such that it creates a circular reference, don’t endlessly loop or overflow your stack &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a very simple implementation of this behavior.  It manages the reflection at the time of change.  A better (more efficient) implementation would probably map the dependencies at construction time into a private dictionary, but this is just a quick example of how you might achieve this behavior:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public abstract class ViewModelBase : INotifyPropertyChanged
{
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    protected class DependsUponAttribute : Attribute
    {
        public string DependancyName { get; private set; }
        
        public DependsUponAttribute(string propertyName)
        {
            DependancyName = propertyName;
        }
    }

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handlers = PropertyChanged;
        if (handlers != null)
        {
            foreach(var property in AllNotifiedProperties(propertyName))
                handlers(this, new PropertyChangedEventArgs(property));
        }
    }

    private IEnumerable&amp;lt;string&amp;gt; DependantProperties(string inputName)
    {
        return from property in GetType().GetProperties()
               where property.GetCustomAttributes(typeof(DependsUponAttribute), true).Cast&amp;lt;DependsUponAttribute&amp;gt;()
                     .Any(attribute =&amp;gt; attribute.DependancyName == inputName)
               select property.Name;
    }

    private IEnumerable&amp;lt;string&amp;gt; NotifiedProperties(IEnumerable&amp;lt;string&amp;gt; inputs)
    {
        var dependancies = from input in inputs
                           from dependancy in DependantProperties(input)
                           select dependancy;

        return inputs.Union(dependancies).Distinct();
    }

    private IEnumerable&amp;lt;string&amp;gt; AllNotifiedProperties(string inputName)
    {
        IEnumerable&amp;lt;string&amp;gt; results = new[]{inputName};

        while (NotifiedProperties(results).Count() &amp;gt; results.Count())
            results = NotifiedProperties(results);

        return results;
    }

    public event PropertyChangedEventHandler PropertyChanged;
}&lt;/pre&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=136308"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=136308" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/136308.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx</guid>
            <pubDate>Sun, 15 Nov 2009 01:55:41 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/136308.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/136308.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/136308.aspx</trackback:ping>
        </item>
        <item>
            <title>Adventures in MVVM &amp;ndash; A Rails-Inspired ViewModel</title>
            <link>http://houseofbilz.com/archive/2009/10/20/adventures-in-mvvm-ndash-a-rails-inspired-viewmodel.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://geekswithblogs.net/HouseOfBilz/archive/2009/05/22/adventures-in-mvvm-ndash-model-view-viewmodel.aspx"&gt;More Adventures in MVVM&lt;/a&gt; &lt;a href="http://dotnetshoutout.com/Adventures-in-MVVM-A-Rails-Inspired-ViewModel" rev="vote-for"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fgeekswithblogs.net%2FHouseOfBilz%2Farchive%2F2009%2F10%2F20%2Fadventures-in-mvvm-ndash-a-rails-inspired-viewmodel.aspx" /&gt;&lt;/a&gt; &lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fgeekswithblogs.net%2fHouseOfBilz%2farchive%2f2009%2f10%2f20%2fadventures-in-mvvm-ndash-a-rails-inspired-viewmodel.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fgeekswithblogs.net%2fHouseOfBilz%2farchive%2f2009%2f10%2f20%2fadventures-in-mvvm-ndash-a-rails-inspired-viewmodel.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I have been taking a few weeks off from my personal studies/experiments in the .Net space to learn more about Ruby and Ruby on Rails (RoR).  I have two main goals for this study: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Get to know another platform as an option for future development &lt;/li&gt;    &lt;li&gt;Examine how I can incorporate different concepts into my existing framework &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;em&gt;What follows is intended to document my experimentation with the second bullet:  How might we design a ViewModel if we were in Rails?  My thoughts on this are still forming, and I am still a novice in the RoR arena, so cut me some slack :).&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I am pretty vocal about my thoughts on the MVVM &lt;em&gt;pattern&lt;/em&gt;.  I really like the pattern a lot and I think it solves a lot of problems that I encounter on a daily basis.  Unfortunately, the implementation of the pattern – ViewModels specifically – often get overly complicated.  This is why there are about a dozen major players in this arena.  The plumbing necessary to create a good ViewModel is tedious and error prone.  A good set of abstractions and tools make the job much easier.&lt;/p&gt;  &lt;p&gt;The RoR approach to application development uses a lot of conventions to allow the developer to be as expressive as possible without introducing too much plumbing.  The framework facilitates DRY (Don’t Repeat Yourself) so your controllers declare what they do and the magic under the hood plumbs it all together for you.  How can we translate these ideas to a better implementation of the MVVM pattern?  In this article, I will focus on the ViewModel portion of the MVVM pattern.&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;A classic ViewModel implementation&lt;/h3&gt;  &lt;p&gt;This view is simple.  There is a text box bound to the &lt;strong&gt;Text&lt;/strong&gt; property in the ViewModel and a button bound to the &lt;strong&gt;MakeLowercase&lt;/strong&gt; command (property) in the ViewModel.  The button is enabled/disabled based on the length of the &lt;strong&gt;Text&lt;/strong&gt; property and clicking on the button will cause the text to go to lowercase.&lt;/p&gt;  &lt;pre class="xml" name="code"&gt;&amp;lt;TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Column="0" /&amp;gt;
&amp;lt;Button Content="Make Lower" Commands:Click.Command="{Binding MakeLowercase}" Grid.Column="1" /&amp;gt;&lt;/pre&gt;

&lt;p&gt;Next is the ViewModel in its pure (no abstractions) form:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class MainPageViewModel : INotifyPropertyChanged
{
    public MainPageViewModel()
    {
        MakeLowercase = new DelegateCommand&amp;lt;pobject&amp;gt;(ExecuteMakeLowercase, CanExecuteMakeLowercase);
    }

    private void ExecuteMakeLowercase(object obj)
    {
        Text = Text.ToLower();
    }

    private bool CanExecuteMakeLowercase(object arg)
    {
        return !string.IsNullOrEmpty(Text);
    }

    private string _text;
    public string Text
    {
        get { return _text; }
        set
        {
            _text = value;
            FirePropertyChanged("Text");
            MakeLowercase.RaiseCanExecuteChanged();
        }
    }

    private DelegateCommand&amp;lt;object&amp;gt; _makeLowercase;
    public DelegateCommand&amp;lt;object&amp;gt; MakeLowercase
    {
        get { return _makeLowercase; }
        set
        {
            _makeLowercase = value;
            FirePropertyChanged("MakeLowercase");
        }
    }

    protected void FirePropertyChanged(string propertyName)
    {
        var handlers = PropertyChanged;
        if (handlers != null)
            handlers(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}&lt;/pre&gt;

&lt;h3&gt;Problems with the traditional ViewModel implementation&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Lots of plumbing (Command in the constructor, PropertyChanged in property setters, ExecuteChanged evaluation in the &lt;strong&gt;Text&lt;/strong&gt; setter, etc) &lt;/li&gt;

  &lt;li&gt;Verbose properties (We can’t use auto-properties because of the need to notify of changes &lt;/li&gt;

  &lt;li&gt;Unrelated events (&lt;strong&gt;Text&lt;/strong&gt; property needs to know that &lt;strong&gt;CanExecuteMakeLowercase&lt;/strong&gt; needs to be re-evaluated) &lt;/li&gt;

  &lt;li&gt;INotifyPropertyChanged is error-prone due to string events &lt;/li&gt;

  &lt;li&gt;Lots of redundancies makes maintenance messy &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;What a Rails-Inspired ViewModel might look like&lt;/h3&gt;

&lt;pre class="c-sharp" name="code"&gt;public class MainPageViewModel : ActiveViewModel&amp;lt;MainPageViewModel.Properties&amp;gt;
{
    public enum Properties { Text }

    public void Execute_MakeLowercase()
    {
        Set(Properties.Text, Get&amp;lt;string&amp;gt;(Properties.Text).ToLower());
    }

    [DependentUpon(Properties.Text)]
    public bool CanExecute_MakeLowercase()
    {
        return !string.IsNullOrEmpty(Get&amp;lt;string&amp;gt;(Properties.Text));
    }
}&lt;/pre&gt;

&lt;p&gt;My goal was to reduce the amount of plumbing and redundancies in this code to communicate only what it needs to&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;There is one property named &lt;strong&gt;Text&lt;/strong&gt; &lt;/li&gt;

  &lt;li&gt;The &lt;strong&gt;MakeLowercase&lt;/strong&gt; command will act on the &lt;strong&gt;Text&lt;/strong&gt; property and make it lowercase &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;CanExecuteMakeLowercase&lt;/strong&gt; will return true if &lt;strong&gt;Text&lt;/strong&gt; has meaningful data &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;CanExecuteMakeLowercase&lt;/strong&gt; needs to be re-evaluated with &lt;strong&gt;Text&lt;/strong&gt; changes &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a lot of magic in &lt;strong&gt;ActiveViewModel.  &lt;/strong&gt;I am using convention to define the properties as a list of enums (&lt;strong&gt;Properties&lt;/strong&gt;).  The ActiveViewModel will generate these properties dynamically.  I am also using convention to create commands.  Any method that is prefixed with &lt;strong&gt;Execute_&lt;/strong&gt; will be made into a command property.  Any method prefixed with &lt;strong&gt;CanExecute_&lt;/strong&gt; will be evaluated in the same command.  Further, the &lt;strong&gt;CanExecute_&lt;/strong&gt; method can declare the properties that will cause the commands to re-evaluate, putting the dependency where it belongs – with the method that is dependant upon it!  Testability is really easy: Call the actions and validate the properties (via public Get()).  I didn’t implement it, but actions based on property setters could very easily use the &lt;strong&gt;DependentUpon&lt;/strong&gt; attribute to avoid &lt;strong&gt;INotifyPropertyChanged&lt;/strong&gt; chaining that can get quite ugly.&lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;I think this approach has a lot of potential.  I am posting it in order to move the conversation forward.  When the MVVM dust settles, and we have some best practices flushed out, what do we want our ViewModels to look like?  Even though I consider this class experimental and exploratory (not meant to be used in production), I feel compelled to call out some weaknesses that will (or may) need to be addressed for a more production-ready base class:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;strong&gt;ActiveViewModel&lt;/strong&gt; class will not work in Silverlight.  It relies heavily on custom type descriptors which are not available in Silverlight.  Hopefully, in Silverlight 4.0, we will have some better support for dynamic property generation.  This may be in the form of C# 4.0 (with the DynamicObject.Try[SG]etMember overrides, for instance), property descriptors, or something else (better IronRuby support, perhaps?) &lt;/li&gt;

  &lt;li&gt;There is not a lot of type safety with the properties.  They are stored internally as plain objects.  The &lt;strong&gt;Get&lt;/strong&gt; method lets you get at a type-casted value, but you need to know it when you ask for it.  We might change the property declaration from an enum to a list of name/type pairs and enforce some better type safety in the base class? &lt;/li&gt;

  &lt;li&gt;Because there are not properties, we loose “equals semantics”.  Get/Set is harder to read/follow than simply assigning and reading properties &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, in case you are curious, you can see my implementation (at the time of this post) of the &lt;strong&gt;ActiveViewModel&lt;/strong&gt; from my &lt;a href="http://bazaar.launchpad.net/~briangenisio/mypetproject/Main/annotate/7/ActiveViewModel/ActiveViewModel.cs"&gt;Launchpad project&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=135612"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=135612" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/135612.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2009/10/20/adventures-in-mvvm-ndash-a-rails-inspired-viewmodel.aspx</guid>
            <pubDate>Wed, 21 Oct 2009 01:22:18 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/135612.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2009/10/20/adventures-in-mvvm-ndash-a-rails-inspired-viewmodel.aspx#feedback</comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/135612.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/135612.aspx</trackback:ping>
        </item>
        <item>
            <title>Introducing DynamicWrapper</title>
            <link>http://houseofbilz.com/archive/2009/09/18/introducing-dynamicwrapper.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://dotnetshoutout.com/Introducing-DynamicWrapper" rev="vote-for"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fhouseofbilz.com%2Farchive%2F2009%2F09%2F18%2Fintroducing-dynamicwrapper.aspx" /&gt;&lt;/a&gt; &lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fhouseofbilz.com%2farchive%2f2009%2f09%2f18%2fintroducing-dynamicwrapper.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fhouseofbilz.com%2farchive%2f2009%2f09%2f18%2fintroducing-dynamicwrapper.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dynamicwrapper.codeplex.com/"&gt;DynamicWrapper project on CodePlex&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;Edit: DynamicWrapper does not work in SIlverlight as I first though.  My unit tests passed, but in runtime I get an exception when I try to use the class.  I will be looking at some alternatives.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Over the past few weeks, I have been working on a utility that I have wanted for years: something that allows me to apply an interface to an object that matches the contract but doesn’t actually implement the interface.  In other words, I’ve wanted duck typing in C#.  The code and project can be found on &lt;a href="http://www.codeplex.com/"&gt;CodePlex&lt;/a&gt;.  It is set up so you simply copy one file into your solution and use the extension methods.&lt;/p&gt;  &lt;p&gt;Why did I want this?  Because I write a lot of unit tests and I develop in .Net with C#.  Because I write way too many wrapper classes to make my code testable.  For example, lets say that I have a class that I want to test and it acts upon a framework object:&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public sealed class FrameworkClass
{
    internal FrameworkClass() {}
    
    public int X {get; set;}
    public int Y {get; set;}
    public int Calculate() { return DoSomeStuff(); }
}&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;public class MyClass
{
    public void DoSomethingWithFrameworkData(FrameworkClass value)
    {
        // Do Something
    }
}&lt;/pre&gt;

&lt;p&gt;The problem is that I can’t test &lt;strong&gt;MyClass&lt;/strong&gt; because it is dependent upon &lt;strong&gt;FrameworkClass&lt;/strong&gt; which I can never construct myself (it is sealed with an internal constructor and no interface).  The solution for this is simple but tedious – create a wrapper class that implements an interface and proxy through the wrapper class to the real object.  This approach works, but I can say this: &lt;strong&gt;&lt;em&gt;I am sick of writing wrapper classes!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is why I created this DynamicWrapper utility.  It exposes two extension methods: realObject.As&amp;lt;Interface&amp;gt;() and wrapper.AsReal&amp;lt;ConcreteClass&amp;gt;().  It uses Reflection to emit a dynamically generated wrapper class that implements the interface, and wraps your object for you.  It sounds complicated, but it is extremely simple to use.&lt;/p&gt;

&lt;p&gt;Here is an example. Start by creating an interface that looks like the FrameworkClass:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public interface ICalculatable
{
    int X {get; set;}
    int Y {get; set;}
    int Calculate();
}&lt;/pre&gt;

&lt;p&gt;Modify your class to depend on ICalculatable:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public void DoSomethingWIthFrameworkData(ICalculatable value) {}&lt;/pre&gt;

&lt;p&gt;Now, when you pass the framework class into the MyClass, you can wrap it with the interface:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;myObject.DoSomethingWithFrameworkData(frameworkObject.As&amp;lt;ICalculatable&amp;gt;());&lt;/pre&gt;

&lt;p&gt;If you need the framework object to pass back to the framework, it is really simple:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;wrapper.AsReal&amp;lt;FrameworkClass&amp;gt;()&lt;/pre&gt;

&lt;p&gt;That’s all there is to it!  The utility is very simple.  It just gets me out of the business of writing (and maintaining) wrapper classes. I am now free to get back to real development.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*On a slightly related note, I will be focusing my learning efforts towards Ruby in the coming months.*&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134926"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134926" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/134926.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2009/09/18/introducing-dynamicwrapper.aspx</guid>
            <pubDate>Sat, 19 Sep 2009 04:44:16 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/134926.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2009/09/18/introducing-dynamicwrapper.aspx#feedback</comments>
            <slash:comments>9</slash:comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/134926.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/134926.aspx</trackback:ping>
        </item>
        <item>
            <title>Adventures in MVVM &amp;ndash; Binding Commands to ANY Event</title>
            <link>http://houseofbilz.com/archive/2009/08/27/adventures-in-mvvm-ndash-binding-commands-to-any-event.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://geekswithblogs.net/HouseOfBilz/archive/2009/05/22/adventures-in-mvvm-ndash-model-view-viewmodel.aspx"&gt;More Adventures in MVVM&lt;/a&gt; &lt;a href="http://dotnetshoutout.com/Adventures-in-MVVM-Binding-Commands-to-ANY-Event" rev="vote-for"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fgeekswithblogs.net%2FHouseOfBilz%2Farchive%2F2009%2F08%2F27%2Fadventures-in-mvvm-ndash-binding-commands-to-any-event.aspx" /&gt;&lt;/a&gt; &lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fgeekswithblogs.net%2fHouseOfBilz%2farchive%2f2009%2f08%2f27%2fadventures-in-mvvm-ndash-binding-commands-to-any-event.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fgeekswithblogs.net%2fHouseOfBilz%2farchive%2f2009%2f08%2f27%2fadventures-in-mvvm-ndash-binding-commands-to-any-event.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;One of the biggest points of friction for me when implementing the MVVM pattern happens when I need to bind commands to events.  When using &lt;a href="http://compositewpf.codeplex.com/"&gt;Prism&lt;/a&gt;, I get the Button.Click command binding out of the box, but every other event needs to be wired up individually.  Doing this requires a LOT of boilerplate code that is very easy to get wrong.  In my &lt;a href="http://houseofbilz.com/archive/2009/08/21/adventures-in-mvvm-ndash-generalized-command-behavior-attachments.aspx"&gt;last post, I published some code to alleviate that pain&lt;/a&gt;.  Still, it requires you to write a new behavior and attachment for every event that you want to bind an event to.&lt;/p&gt;  &lt;p&gt;For a while now, I have toyed with the idea of just binding commands to events directly.  I ran into a lot of bumps in the road.  For instance, every event handler has a different event argument type.  This requires all of the handlers to be dynamic.  I also couldn’t create an inline command binding – I will surely want to bind more than one event per control – so I need to create a collection of bindings.  Creating arrays of structures created its own troubles – binding only works with FrameworkElements within the visual tree.  This required me to write my own crude binding within my generic behavior.&lt;/p&gt;  &lt;p&gt;What follows is very loosely based off of the &lt;a href="http://www.codeproject.com/KB/WPF/Cinch.aspx"&gt;Chinch MVVM framework&lt;/a&gt;.  I tested this code in Silverlight and WPF and it works really well!&lt;/p&gt;  &lt;p&gt;Assume I have a ViewModel that looks like this:&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public class MainPageViewModel : INotifyPropertyChanged
{
    ...
    public ICommand MouseLeaveCommand { get; private set; }
    public ICommand MouseEnterCommand { get; private set; }
    public ICommand ClickCommand { get; private set; }
    ...
}&lt;/pre&gt;

&lt;p&gt;I can then bind the commands to events on a control (Button, for instance):&lt;/p&gt;

&lt;pre class="xml" name="code"&gt;&amp;lt;Button Content="Click Me"&amp;gt;
    &amp;lt;Behaviors:Events.Commands&amp;gt;
        &amp;lt;Behaviors:EventCommandCollection&amp;gt;
            &amp;lt;Behaviors:EventCommand CommandName="MouseEnterCommand" EventName="MouseEnter" /&amp;gt;
            &amp;lt;Behaviors:EventCommand CommandName="MouseLeaveCommand" EventName="MouseLeave" /&amp;gt;
            &amp;lt;Behaviors:EventCommand CommandName="ClickCommand" EventName="Click" /&amp;gt;
        &amp;lt;/Behaviors:EventCommandCollection&amp;gt;
    &amp;lt;/Behaviors:Events.Commands&amp;gt;
&amp;lt;/Button&amp;gt;&lt;/pre&gt;

&lt;p&gt;I no longer need to write any extra code whenever I want to attach commands to my events!  There are a few caveats to this code:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The XAML requires the EventCommandCollection to be declared in the XAML.  I struggled to figure out how to eliminate this but gave up.  Someone smarter than me might be able to tell me what I am doing wrong. &lt;/li&gt;

  &lt;li&gt;This code does not consider command properties.  Every command assumes a null parameter.  If you need parameters (like data context), then you’ll have to do something differently (either use the old-school mechanism or extend this code to handle some special event types). &lt;/li&gt;

  &lt;li&gt;You don’t bind directly to the command.  Instead, you declare the name of the command (Notice CommandName is not bound).  The behavior binds for you using a primitive mechanism. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the command behavior that does all the work:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class Events
{
    private static readonly DependencyProperty EventBehaviorsProperty =
        DependencyProperty.RegisterAttached(
        "EventBehaviors",
        typeof(EventBehaviorCollection),
        typeof(Control),
        null);

    private static readonly DependencyProperty InternalDataContextProperty =
        DependencyProperty.RegisterAttached(
        "InternalDataContext",
        typeof(Object),
        typeof(Control),
        new PropertyMetadata(null, DataContextChanged));

    private static void DataContextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var target = dependencyObject as Control;
        if (target == null) return;

        foreach (var behavior in GetOrCreateBehavior(target))
            behavior.Bind();
    }

    public static readonly DependencyProperty CommandsProperty =
        DependencyProperty.RegisterAttached(
        "Commands",
        typeof(EventCommandCollection),
        typeof(Events),
        new PropertyMetadata(null, CommandsChanged));

    public static EventCommandCollection GetCommands(DependencyObject dependencyObject)
    {
        return dependencyObject.GetValue(CommandsProperty) as EventCommandCollection;
    }

    public static void SetCommands(DependencyObject dependencyObject, EventCommandCollection eventCommands)
    {
        dependencyObject.SetValue(CommandsProperty, eventCommands);
    }

    private static void CommandsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var target = dependencyObject as Control;
        if (target == null) return;

        var behaviors = GetOrCreateBehavior(target);
        foreach (var eventCommand in e.NewValue as EventCommandCollection)
        {
            var behavior = new EventBehavior(target);
            behavior.Bind(eventCommand);
            behaviors.Add(behavior);
        }

    }

    private static EventBehaviorCollection GetOrCreateBehavior(FrameworkElement target)
    {
        var behavior = target.GetValue(EventBehaviorsProperty) as EventBehaviorCollection;
        if (behavior == null)
        {
            behavior = new EventBehaviorCollection();
            target.SetValue(EventBehaviorsProperty, behavior);
            target.SetBinding(InternalDataContextProperty, new Binding());
        }

        return behavior;
    }
}

public class EventCommand
{
    public string CommandName { get; set; }
    public string EventName { get; set; }
}

public class EventCommandCollection : List&amp;lt;EventCommand&amp;gt;
{
}

public class EventBehavior : CommandBehaviorBase&amp;lt;Control&amp;gt;
{
    private EventCommand _bindingInfo;

    public EventBehavior(Control control)
        : base(control)
    {

    }

    public void Bind(EventCommand bindingInfo)
    {
        ValidateBindingInfo(bindingInfo);

        _bindingInfo = bindingInfo;

        Bind();
    }

    private void ValidateBindingInfo(EventCommand bindingInfo)
    {
        if(bindingInfo == null) throw new ArgumentException("bindingInfo");
        if (string.IsNullOrEmpty(bindingInfo.CommandName)) throw new ArgumentException("bindingInfo.CommandName");
        if (string.IsNullOrEmpty(bindingInfo.EventName)) throw new ArgumentException("bindingInfo.EventName");
    }

    public void Bind()
    {
        ValidateBindingInfo(_bindingInfo);
        HookPropertyChanged();
        HookEvent();
        SetCommand();
    }

    public void HookPropertyChanged()
    {
        var dataContext = TargetObject.DataContext as INotifyPropertyChanged;
        if (dataContext == null) return;

        dataContext.PropertyChanged -= DataContextPropertyChanged;
        dataContext.PropertyChanged += DataContextPropertyChanged;
    }

    private void DataContextPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == _bindingInfo.CommandName)
            SetCommand();
    }

    private void SetCommand()
    {
        var dataContext = TargetObject.DataContext;
        if (dataContext == null) return;

        var propertyInfo = dataContext.GetType().GetProperty(_bindingInfo.CommandName);
        if (propertyInfo == null) throw new ArgumentException("commandName");

        Command = propertyInfo.GetValue(dataContext, null) as ICommand;
    }

    private void HookEvent()
    {
        var eventInfo = TargetObject.GetType().GetEvent(
            _bindingInfo.EventName, BindingFlags.Public | BindingFlags.Instance);
        if (eventInfo == null) throw new ArgumentException("eventName");

        eventInfo.RemoveEventHandler(TargetObject, GetEventMethod(eventInfo));
        eventInfo.AddEventHandler(TargetObject, GetEventMethod(eventInfo));
    }

    private Delegate _method;
    private Delegate GetEventMethod(EventInfo eventInfo)
    {
        if (eventInfo == null) throw new ArgumentNullException("eventInfo");
        if (eventInfo.EventHandlerType == null) throw new ArgumentException("EventHandlerType is null");

        if (_method == null)
        {
            _method = Delegate.CreateDelegate(
                eventInfo.EventHandlerType, this,
                GetType().GetMethod("OnEventRaised",
                BindingFlags.NonPublic | BindingFlags.Instance));
        }

        return _method;
    }

    private void OnEventRaised(object sender, EventArgs e)
    {
        ExecuteCommand();
    }
}

public class EventBehaviorCollection : List&amp;lt;EventBehavior&amp;gt;
{ }&lt;/pre&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134357"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134357" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://houseofbilz.com/aggbug/134357.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brian Genisio's House Of Bilz</dc:creator>
            <guid>http://houseofbilz.com/archive/2009/08/27/adventures-in-mvvm-ndash-binding-commands-to-any-event.aspx</guid>
            <pubDate>Fri, 28 Aug 2009 01:27:12 GMT</pubDate>
            <wfw:comment>http://houseofbilz.com/comments/134357.aspx</wfw:comment>
            <comments>http://houseofbilz.com/archive/2009/08/27/adventures-in-mvvm-ndash-binding-commands-to-any-event.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://houseofbilz.com/comments/commentRss/134357.aspx</wfw:commentRss>
            <trackback:ping>http://houseofbilz.com/services/trackbacks/134357.aspx</trackback:ping>
        </item>
    </channel>
</rss>
