<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>The Problem Solver : WPF</title><link>http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx</link><description>Tags: WPF</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Rehosting the Workflow Designer in WF4</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/12/23/rehosting-the-workflow-designer-in-wf4.aspx</link><pubDate>Wed, 23 Dec 2009 16:46:22 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1747392</guid><dc:creator>Maurice</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1747392</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/12/23/rehosting-the-workflow-designer-in-wf4.aspx#comments</comments><description>&lt;p&gt;&lt;font color="#ff0000"&gt;Note: This blog post is written using the .NET framework 4.0 Beta 2&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;With Windows Workflow Foundation 3 it was possible to rehost the workflow designer in your own application. But possible is about all there was to say about it as it was pretty hard to do anything beyond the basics.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;With Windows Workflow Foundation 4 live has become much better on the rehosting front &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt; In fact it is possible to create the fully functional and useful workflow editor below in about 200 lines of code. Now that is more like it!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.metablogapi/7433.image_5F00_6A43D4F6.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.metablogapi/4606.image_5F00_thumb_5F00_04E04B43.png" width="511" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h2&gt;&amp;#160;&lt;/h2&gt;  &lt;h2&gt;The WorkflowDesigner&lt;/h2&gt;  &lt;p&gt;The WorkflowDesigner is the main class to work with. This exposes the actual design surface through the View property and the linked property sheet through the PropertyInspectorView property. Both these properties point to ready to use WPF UIElement’s so, as long as the host used WPF, adding them to a form is easy. And loading or saving a workflow is easy to, all it takes is a Load() and Save() function pointing to a XAML file. The code that does this part is below:&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;_workflowDesigner = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WorkflowDesigner();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;_workflowDesigner.Load(_fileName);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var view = _workflowDesigner.View;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;Grid.SetColumn(view, 1);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;Grid.SetRow(view, 1);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;LayoutGrid.Children.Add(view);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var propInspector = _workflowDesigner.PropertyInspectorView;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;Grid.SetColumn(propInspector, 2);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;Grid.SetRow(propInspector, 1);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;LayoutGrid.Children.Add(propInspector);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;DesignerMetadata&lt;/h2&gt;

&lt;p&gt;One thing that is needed is to register the workflow activity designer metadata. It is just a single call but leaving it out means all activities are just a small collapsed shape and won’t expand.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; DesignerMetadata().Register();&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Displaying the toolbox with activities&lt;/h2&gt;

&lt;p&gt;The toolbox on the left if another standard WPF control called the ToolboxControl. Again easy to add to any WPF form. Add to it ToolboxItemWrapper with the activity type to add and you are good to go. Dragging controls onto the design surface just works, no extra work required. In the code below I just scan through all types in a few assemblies and if they are valid activities I add them to the toolbox. Again nice and easy.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var toolbox = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ToolboxControl();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var cat = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ToolboxCategory(&lt;span style="color:#006080;"&gt;&amp;quot;Standard Activities&amp;quot;&lt;/span&gt;);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var assemblies = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Assembly&amp;gt;();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;assemblies.Add(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(Send).Assembly);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;assemblies.Add(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(Delay).Assembly);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;assemblies.Add(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(ReceiveAndSendReplyFactory).Assembly);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var query = from asm &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; assemblies&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            from type &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; asm.GetTypes()&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;where&lt;/span&gt; type.IsPublic &amp;amp;&amp;amp;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            !type.IsNested &amp;amp;&amp;amp;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            !type.IsAbstract &amp;amp;&amp;amp;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            !type.ContainsGenericParameters &amp;amp;&amp;amp;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            (&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(Activity).IsAssignableFrom(type) ||&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(IActivityTemplateFactory).IsAssignableFrom(type))&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            orderby type.Name&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            select &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ToolboxItemWrapper(type);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;query.ToList().ForEach(ti =&amp;gt; cat.Add(ti));&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;toolbox.Categories.Add(cat);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;Grid.SetColumn(toolbox, 0);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;Grid.SetRow(toolbox, 1);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;LayoutGrid.Children.Add(toolbox);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;The current selection&lt;/h2&gt;

&lt;p&gt;At the top of the form I display the currently selected activity and its parents. The WorkflowDesigner has an Items collection with a bunch of useful objects in there. One of these is a Selection object. We could periodically check this Selection but its even easier to subscribe to chances using the Subscribe() function and passing in a handler that is called whenever the selection changes. Setting up the subscription is another one-liner.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;_workflowDesigner.Context.Items.Subscribe&amp;lt;Selection&amp;gt;(SelectionChanged);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The handler itself isn’t very complex either.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; SelectionChanged(Selection selection)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;{&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    var modelItem = selection.PrimarySelection;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    var sb = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StringBuilder();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; (modelItem != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        var displayName = modelItem.Properties[&lt;span style="color:#006080;"&gt;&amp;quot;DisplayName&amp;quot;&lt;/span&gt;];&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (displayName != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (sb.Length &amp;gt; 0)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;                sb.Insert(0, &lt;span style="color:#006080;"&gt;&amp;quot; - &amp;quot;&lt;/span&gt;);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            sb.Insert(0, displayName.ComputedValue);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        modelItem = modelItem.Parent;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    CurrentActivityName.Text = sb.ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Validating the workflow&lt;/h2&gt;

&lt;p&gt;It would be nice to let the user know if the workflow is valid. Again quite easy to do by adding a IValidationErrorService to the WorkflowDesigner services collection. In this case I added a listbox to the form and let the IValidationErrorService add each error to the ListBox items. No need to call anything, the IValidationErrorService is automatically called as soon as anything in the workflow changes.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var validationErrorService = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ValidationErrorService(WorkflowErrors.Items);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;_workflowDesigner.Context.Services.Publish&amp;lt;IValidationErrorService&amp;gt;(validationErrorService);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The IValidationErrorService consists of a single function that gets the list of errors as a parameter.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; ValidationErrorService : IValidationErrorService&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;{&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; IList _errorList;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ValidationErrorService(IList errorList)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        _errorList = errorList;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; ShowValidationErrors(IList&amp;lt;ValidationErrorInfo&amp;gt; errors)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        _errorList.Clear();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (var error &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; errors)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;            _errorList.Add(error.Message);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;Running the workflow&lt;/h2&gt;

&lt;p&gt;Just to be able to run the workflow I added a bit of code that uses a WorkflowApplication to run the workflow. Loading it is also easy, just call the ActivityXamlServices.Load() passing in the file and it will return a DynamicActivity ready to run.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var writer = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StringWriter();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var workflow = ActivityXamlServices.Load(_fileName);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var wa = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WorkflowApplication(workflow);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;wa.Extensions.Add(writer);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;wa.Completed = WorkflowCompleted;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;wa.OnUnhandledException = WorkflowUnhandledException;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;wa.Run();&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;So all together I have a working application that I can use to edit and run workflows. So who still needs Visual Studio 2010?&lt;/p&gt;

&lt;p&gt;Sweet &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;

&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:8eb9d37f-1541-4f29-b6f4-1eea890d4876:0f451571-2106-45bf-9589-f78bfb238ce5" class="wlWriterEditableSmartContent"&gt;&lt;p&gt;&lt;div&gt;Download &lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.metablogapi/2543.CustomWorkflowDesigner_5F00_47FBA3A3.zip" target="_self"&gt;CustomWorkflowDesigner.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;
  &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1747392" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WF4/default.aspx">WF4</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VS2010/default.aspx">VS2010</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Beta2/default.aspx">Beta2</category></item><item><title>Nederlandse CodeCamp 2009</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/10/19/nederlandse-codecamp-2009.aspx</link><pubDate>Mon, 19 Oct 2009 10:26:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1732965</guid><dc:creator>Maurice</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1732965</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/10/19/nederlandse-codecamp-2009.aspx#comments</comments><description>&lt;p&gt;Op 21 november 2009 organiseren de &lt;a href="http://www.sdn.nl"&gt;SDN&lt;/a&gt;, &lt;a href="http://www.dotned.nl"&gt;Stichting dotNed&lt;/a&gt; en &lt;a href="http://www.VBcentral.nl"&gt;VBcentral&lt;/a&gt; samen het derde Nederlandse &lt;a href="http://www.codecamp.nl"&gt;Code Camp&lt;/a&gt;. Dit is een dag lang met code, code sharing, freaking en gezellig samenzijn. Een evenement door ontwikkelaars, voor ontwikkelaars. De regie ligt voor een belangrijk deel bij de deelnemers! Het aantal plaatsen voor deelnemers is wel beperkt tot maximaal 150. Wacht dus niet te lang met beslissen want voor je het weet is er geen plaats meer. Vergeet bij je aanmelding niet op te geven welke onderwerpen je interesse hebben. Bovendien nodigen we iedereen graag uit om zelf een sessie in te vullen.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Op de website, &lt;a href="http://www.codecamp.nl"&gt;www.codecamp.nl&lt;/a&gt;, vind je meer informatie en kan je je aanmelden.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1732965" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Visual+FoxPro/default.aspx">Visual FoxPro</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/webcast/default.aspx">webcast</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/ClickOnce/default.aspx">ClickOnce</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/SDN/default.aspx">SDN</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Data+Access/default.aspx">Data Access</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Using Model – View – ViewModel with Silverlight</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/04/07/using-model-view-viewmodel-with-silverlight.aspx</link><pubDate>Tue, 07 Apr 2009 14:23:46 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1685604</guid><dc:creator>Maurice</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1685604</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/04/07/using-model-view-viewmodel-with-silverlight.aspx#comments</comments><description>&lt;p&gt;The View – Model – ViewModel design pattern, also known as MVVM, is getting more popular these days. I have found it extremely easy to use when developing very different applications and have used the design pattern recently in both ASP.NET, WPF and Silverlight applications. However easy as it might be is seems to confuse people as I have seen some terrible examples where people make a complete mess of things. &lt;/p&gt;  &lt;p&gt;Josh Smith did an excellent screen cast for Pixel8 on using MVVM with WPF, you can find it &lt;a href="http://pixel8.infragistics.com/shows/mvvm-wpf.aspx#Episode:11933"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Even thought the UI technology used doesn&amp;#39;t change the basic MVVM pattern there are some subtle differences, like not easily being able to use ICommand in Silverlight, so I decided to create a small Silverlight sample.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The basic structure goes like this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The user interacts with a View, implemented as a Silverlight user control.&lt;/li&gt;    &lt;li&gt;The View is data bound to a ViewModel. This is the most important step to remember. The ViewModel is just another class.&lt;/li&gt;    &lt;li&gt;The ViewModel is a wrapper for a Model. Think of the Model as the data and the business rules.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Model&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The Model I am using is very simple and has two read-write properties, FirstName and LastName, and a single read-only property, FullName. The FullName property represents some business rule on how a name should be formatted. I know it is a bit of a lame business rule but it is just a sample &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;. The Model also implements INotifyPropertyChanged so the UI can be updated whenever a value is updated. The complete model looks like this:&lt;/p&gt;  &lt;div style="border-bottom:gray 1px solid;border-left:gray 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;max-height:200px;font-size:8pt;overflow:auto;border-top:gray 1px solid;cursor:text;border-right:gray 1px solid;padding-top:4px;"&gt;   &lt;div style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;     &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.ComponentModel;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   2:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   3:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; SilverlightMVVMDemo.Model&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Customer : INotifyPropertyChanged&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   7:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _firstName;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   8:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _lastName;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   9:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  10:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; FirstName&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  11:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  12:&lt;/span&gt;             get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _firstName; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  13:&lt;/span&gt;             set&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  14:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  15:&lt;/span&gt;                 _firstName = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  16:&lt;/span&gt;                 OnPropertyChanged(&lt;span style="color:#006080;"&gt;&amp;quot;FirstName&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  17:&lt;/span&gt;                 OnPropertyChanged(&lt;span style="color:#006080;"&gt;&amp;quot;FullName&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  18:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  19:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  20:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; LastName&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  21:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  22:&lt;/span&gt;             get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _lastName; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  23:&lt;/span&gt;             set&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  24:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  25:&lt;/span&gt;                 _lastName = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  26:&lt;/span&gt;                 OnPropertyChanged(&lt;span style="color:#006080;"&gt;&amp;quot;LastName&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  27:&lt;/span&gt;                 OnPropertyChanged(&lt;span style="color:#006080;"&gt;&amp;quot;FullName&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  28:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  29:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  30:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  31:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  32:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; FullName&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  33:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  34:&lt;/span&gt;             get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; FirstName + &lt;span style="color:#006080;"&gt;&amp;quot; &amp;quot;&lt;/span&gt; + LastName; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  35:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  36:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  37:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  38:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  39:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OnPropertyChanged(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; propertyName)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  40:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  41:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (PropertyChanged != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  42:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  43:&lt;/span&gt;                 var args = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; PropertyChangedEventArgs(propertyName);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  44:&lt;/span&gt;                 PropertyChanged(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, args);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  45:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  46:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  47:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  48:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The View&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The View is just a Silverlight user control that makes things visible for the user. All controls use data binding to get to their values. There is one interesting twist here. Just like I had a business rule about how to format a FullName I have a rule about the font weight to use to display the FullName. This is just UI so not a business rule and as a result it is not stored in the Model. We do not want to code this in the UI as that makes things hard to test. So that leaves one place, the ViewModel &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;. And the View uses data binding to set the FontWeight property.&lt;/p&gt;

&lt;p&gt;The complete View looks like this:&lt;/p&gt;

&lt;div style="border-bottom:gray 1px solid;border-left:gray 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;max-height:200px;font-size:8pt;overflow:auto;border-top:gray 1px solid;cursor:text;border-right:gray 1px solid;padding-top:4px;"&gt;
  &lt;div style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;
    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="color:#ff0000;"&gt;xmlns:SilverlightMVVMDemo_ViewModel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;clr-namespace:SilverlightMVVMDemo.ViewModel&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;xmlns:d&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/expression/blend/2008&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;xmlns:mc&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.openxmlformats.org/markup-compatibility/2006&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SilverlightMVVMDemo.View.CustomerView&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;400&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;300&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;mc:Ignorable&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   6:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   7:&lt;/span&gt;           &lt;span style="color:#ff0000;"&gt;Background&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;White&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   8:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   9:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0.133*&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  10:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0.133*&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  11:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0.133*&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  12:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0.18*&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  13:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0.42*&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  14:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  15:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  16:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0.3*&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  17:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0.7*&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  18:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  19:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Firstname:&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  20:&lt;/span&gt;                    &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  21:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding Path=FirstName, Mode=TwoWay}&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  22:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  23:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;8,8,8,8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  24:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Lastname:&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  25:&lt;/span&gt;                    &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  26:&lt;/span&gt;                    &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  27:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding Path=LastName, Mode=TwoWay}&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  28:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  29:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  30:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;8,8,8,8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  31:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Fullname:&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  32:&lt;/span&gt;                    &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  33:&lt;/span&gt;                    &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  34:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding Path=FullName}&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  35:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  36:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  37:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;8,8,8,8&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  38:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;FontWeight&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding Path=FullNameFontWeight}&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  39:&lt;/span&gt;                  &lt;span style="color:#ff0000;"&gt;IsReadOnly&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;True&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  40:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Button&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Content&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Save&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  41:&lt;/span&gt;                 &lt;span style="color:#ff0000;"&gt;Click&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Button_Click&amp;quot;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  42:&lt;/span&gt;                 &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;3&amp;quot;&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  43:&lt;/span&gt;                 &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  44:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  45:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The code behind is very simple and looks like this:&lt;/p&gt;

&lt;div style="border-bottom:gray 1px solid;border-left:gray 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;max-height:200px;font-size:8pt;overflow:auto;border-top:gray 1px solid;cursor:text;border-right:gray 1px solid;padding-top:4px;"&gt;
  &lt;div style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;
    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Windows.Controls;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   2:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; SilverlightMVVMDemo.ViewModel;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   3:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   4:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; SilverlightMVVMDemo.View&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   5:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   6:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; CustomerView : UserControl&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   8:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; CustomerView()&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   9:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  10:&lt;/span&gt;             InitializeComponent();&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  11:&lt;/span&gt;             DataContext = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; CustomerViewModel();&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  12:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  13:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  14:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Button_Click(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, System.Windows.RoutedEventArgs e)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  15:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  16:&lt;/span&gt;             var viewModel = (CustomerViewModel)DataContext;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  17:&lt;/span&gt;             viewModel.Save();&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  18:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  19:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  20:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In an ideal world there would be no code at all, or only that setting the DataContext but as Silverlight makes it a little harder to use commands there is a single line, okay two counting the cast, to pass the save command on to the ViewModel.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The ViewModel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The ViewModel class is the one that glues the View and the Model together, hence its name &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;. basically the ViewModel wraps each Model object, so if you want to use a collection of customer models you create a collection of CustomerViewModel objects and databind against them. The ViewModel catches all PropertyChanged events from the Model and passes them on to the user interface. Whenever the FullName property changes the FullNameFontWeight might also change so in that case an extra PropertyChanged event is raised. Note that calculation of the FontWeight to use is part of the ViewModel as the UI depends on this but it is not a business rule per se.&lt;/p&gt;

&lt;p&gt;Another example of a property like this would be the CSS class to use in an ASP.NET application. basically if a UI property changes, create a property get to do so and databind it.&lt;/p&gt;

&lt;p&gt;The complete ViewModel class looks like this:&lt;/p&gt;

&lt;div style="border-bottom:gray 1px solid;border-left:gray 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;max-height:200px;font-size:8pt;overflow:auto;border-top:gray 1px solid;cursor:text;border-right:gray 1px solid;padding-top:4px;"&gt;
  &lt;div style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;
    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.ComponentModel;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   2:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Windows;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   3:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; SilverlightMVVMDemo.Model;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   4:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   5:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; SilverlightMVVMDemo.ViewModel&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   6:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   7:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; CustomerViewModel : INotifyPropertyChanged&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   8:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;   9:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; Customer _model;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  10:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  11:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; CustomerViewModel()&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  12:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  13:&lt;/span&gt;             Model = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Customer() { FirstName = &lt;span style="color:#006080;"&gt;&amp;quot;Maurice&amp;quot;&lt;/span&gt;, LastName = &lt;span style="color:#006080;"&gt;&amp;quot;de Beijer&amp;quot;&lt;/span&gt; };&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  14:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  15:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  16:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; CustomerViewModel(Customer model)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  17:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  18:&lt;/span&gt;             Model = model;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  19:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  20:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  21:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  22:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Customer Model&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  23:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  24:&lt;/span&gt;             get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _model; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  25:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; set&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  26:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  27:&lt;/span&gt;                 &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_model != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  28:&lt;/span&gt;                     _model.PropertyChanged -= ModelPropertyChanged;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  29:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  30:&lt;/span&gt;                 _model = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  31:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  32:&lt;/span&gt;                 &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_model != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  33:&lt;/span&gt;                     _model.PropertyChanged += ModelPropertyChanged;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  34:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  35:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  36:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  37:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; ModelPropertyChanged(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, PropertyChangedEventArgs e)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  38:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  39:&lt;/span&gt;             OnPropertyChanged(e.PropertyName);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  40:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  41:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (e.PropertyName == &lt;span style="color:#006080;"&gt;&amp;quot;FullName&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  42:&lt;/span&gt;                 OnPropertyChanged(&lt;span style="color:#006080;"&gt;&amp;quot;FullNameFontWeight&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  43:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  44:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  45:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  46:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; FirstName&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  47:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  48:&lt;/span&gt;             get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; Model.FirstName; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  49:&lt;/span&gt;             set { Model.FirstName = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  50:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  51:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; LastName&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  52:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  53:&lt;/span&gt;             get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; Model.LastName; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  54:&lt;/span&gt;             set { Model.LastName = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  55:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  56:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  57:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; FullName&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  58:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  59:&lt;/span&gt;             get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; Model.FullName; }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  60:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  61:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  62:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; FontWeight FullNameFontWeight&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  63:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  64:&lt;/span&gt;             get&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  65:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  66:&lt;/span&gt;                 &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (FullName.Length &amp;gt; 20)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  67:&lt;/span&gt;                     &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; FontWeights.ExtraBold;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  68:&lt;/span&gt;                 &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (FullName.Length &amp;gt; 15)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  69:&lt;/span&gt;                     &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; FontWeights.Bold;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  70:&lt;/span&gt;                 &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (FullName.Length &amp;gt; 10)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  71:&lt;/span&gt;                     &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; FontWeights.Normal;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  72:&lt;/span&gt;                 &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  73:&lt;/span&gt;                     &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; FontWeights.Light;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  74:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  75:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  76:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  77:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  78:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  79:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OnPropertyChanged(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; propertyName)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  80:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  81:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (PropertyChanged != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  82:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  83:&lt;/span&gt;                 var args = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; PropertyChangedEventArgs(propertyName);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  84:&lt;/span&gt;                 PropertyChanged(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, args);&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  85:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  86:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  87:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  88:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Save()&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  89:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  90:&lt;/span&gt;             &lt;span style="color:#008000;"&gt;// Implement the logic to save the customer.&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  91:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  92:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;"&gt;  93:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In this case I duplicated all properties from the Model in the ViewModel. This is not a must, some people prefer to expose and bind to the Model directly. It saves a few lines of code but I prefer not to do so. Of course there is no need to duplicate properties the UI is never going to bind to directly.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model-View-ViewModel guidelines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not very difficult at all as long as you keep to a few guidelines:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Never set any UI properties from your CS code with the exception of the DataContext.&lt;/li&gt;

  &lt;li&gt;If you need an event handler in your code behind, like the button click, make it a single line and pass the request onto the ViewModel.&lt;/li&gt;

  &lt;li&gt;All UI control properties that need to change at runtime do so by data binding to a ViewModel property.&lt;/li&gt;

  &lt;li&gt;Organize your ViewModel types per View and not per Model. It is perfectly fine to create a ViewModel that wraps two different Models. A View has only a single DataContext so you cannot bind it to multiple ViewModel objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;
  &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now on Twitter at &lt;a href="http://twitter.com/mauricedb"&gt;http://twitter.com/mauricedb&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1685604" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>Surface at the last Software Developer Event</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/04/06/surface-at-the-last-software-developer-event.aspx</link><pubDate>Mon, 06 Apr 2009 07:27:04 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1685013</guid><dc:creator>Maurice</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1685013</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/04/06/surface-at-the-last-software-developer-event.aspx#comments</comments><description>&lt;p&gt;&lt;img height="356" src="http://www.sdn.nl/Portals/0/Gallery/Album/11/DSC_6308.JPG" width="535" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;As was to be expected the Surface machine at the last SDE was a big success and with lots of people wanting to have a go at it.&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.sdn.nl/Portals/0/Gallery/Album/11/DSC_6314.JPG" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Nice to see the interest. And I am grateful Martin Tirion from the Dutch Microsoft office let us borrow the machine for a day.&lt;/p&gt;  &lt;p&gt;&lt;img height="371" src="http://www.sdn.nl/Portals/0/Gallery/Album/11/DSC_6321.JPG" width="557" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;At the end of June we will have the next big event &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;  &lt;p&gt;Cu there.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;BTW you can find more pictures from the event &lt;a href="http://www.sdn.nl/SDN/Fotoalbum/tabid/86/AlbumID/452-11/Default.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;   &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And now on Twitter at &lt;a href="http://twitter.com/mauricedb"&gt;http://twitter.com/mauricedb&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1685013" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/SDN/default.aspx">SDN</category></item><item><title>Want to download all MIX sessions?</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/31/want-to-download-all-mix-sessions.aspx</link><pubDate>Tue, 31 Mar 2009 06:52:40 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1683235</guid><dc:creator>Maurice</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1683235</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/31/want-to-download-all-mix-sessions.aspx#comments</comments><description>&lt;p&gt;Then you should check Mike Swanson’s blog post &lt;a href="http://blogs.msdn.com/mswanson/archive/2009/03/26/mix09-keynote-and-session-videos.aspx"&gt;here&lt;/a&gt;. He has two batch files, the first downloads all MIX session recordings with in the format you like, the second renames them so it is easier to make sense of all the media file names.&lt;/p&gt;  &lt;p&gt;If you just want a list of all sessions with download links &lt;a href="http://videos.visitmix.com/MIX09/All"&gt;this&lt;/a&gt; page might be the thing for you.&lt;/p&gt;  &lt;p&gt;So much better than downloading them by hand. Not as good as going to the MIX itself but if you, like me, couldn’t go it is still a nice way to see all the content.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1683235" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/webcast/default.aspx">webcast</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/IronPython/default.aspx">IronPython</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Visual Basic QuickStarts and How-to Topics for the Composite Application Guidance for WPF and Silverlight</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/25/visual-basic-quickstarts-and-how-to-topics-for-the-composite-application-guidance-for-wpf-and-silverlight.aspx</link><pubDate>Wed, 25 Mar 2009 08:12:57 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1681248</guid><dc:creator>Maurice</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1681248</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/25/visual-basic-quickstarts-and-how-to-topics-for-the-composite-application-guidance-for-wpf-and-silverlight.aspx#comments</comments><description>&lt;p&gt;The P&amp;amp;P team have just release a VB version of the Prism quick starts.&lt;/p&gt;  &lt;p&gt;You can download the goods &lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=537da1cd-43e1-4799-88e7-a1da9166fb46"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1681248" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>Software Development Event march 30th</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/23/software-development-event-march-30th.aspx</link><pubDate>Mon, 23 Mar 2009 15:40:29 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1680616</guid><dc:creator>Maurice</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1680616</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/23/software-development-event-march-30th.aspx#comments</comments><description>&lt;p&gt;Just one week to go to the next Software Development Event. The schedule with all the sessions is looking good. But this time there is even more! &lt;/p&gt;  &lt;p align="center"&gt;&lt;img height="384" src="http://blogs.microsoft.nl/blogs/ux/MSSC_34View_7C1948A0.jpg" width="572" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;We will have a Microsoft &lt;a href="http://www.microsoft.com/surface/"&gt;Surface&lt;/a&gt; machine somewhere in the common area for people to try our. And if you have never played, oops tested, with a Surface machine before this is a truly exiting machine!&lt;/p&gt;  &lt;p&gt;Just goes to show, the SDN will go to extraordinary efforts to please all attendees &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt; &lt;/p&gt;  &lt;p&gt;You can see the full schedule &lt;a href="http://www.sdn.nl/SDN/SDNEvent/tabid/68/Default.aspx"&gt;here&lt;/a&gt;. And don’t forget, we are &lt;strong&gt;not&lt;/strong&gt; in Ede this time but in a great new &lt;a href="http://www.debergsebossen.nl/"&gt;location&lt;/a&gt; in Driebergen.&lt;/p&gt;  &lt;p&gt;Hope to see everyone there next week Monday.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;   &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And now on Twitter at &lt;a title="http://twitter.com/mauricedb" href="http://twitter.com/mauricedb"&gt;http://twitter.com/mauricedb&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1680616" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/SDN/default.aspx">SDN</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Looking back at the MVP Summit</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/07/looking-back-at-the-mvp-summit.aspx</link><pubDate>Sat, 07 Mar 2009 11:08:09 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1676278</guid><dc:creator>Maurice</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1676278</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/07/looking-back-at-the-mvp-summit.aspx#comments</comments><description>&lt;p&gt;Last week lots of MVP, myself included, where in Redmond visiting Microsoft on our yearly MVP pilgrimage. The MVP Summit is always a great event. Not only do we get to talk to the MS team members who actually design and build all the software we love and use but we also get to meet each other. And with MVP’s being located around the world that is kind of rare as well.&lt;/p&gt;  &lt;p&gt;Despite this being a great event I still have very mixed feelings about this last MVP summit. The problem isn’t the events itself or the people I met, that was al great &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;. No the problem was in some of the technological decisions made in product groups. Unfortunately I can’t divulge details yet because I have signed an NDA but as soon .NET 4.0 as beta 1 is made public I will be able to blog about some of these decisions. And rest assured I will!&lt;/p&gt;  &lt;p&gt;The reason we really need to is the way these important changes are communicated. Or should I say not communicated. Some very important changes where not communicated at all and could only be derived by bullet points missing from PowerPoint slides. Only when directly asked about the missing bullet point would someone say “Yes that is right, we decided to …. NDA … because … NDA …”. Sorry about the NDA part &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;.&lt;/p&gt;  &lt;p&gt;I can only say that these decisions are a big problem and I know several MVP’s who decided to skip other sessions on the same product as a result. I didn’t, as far as I am concerned ignoring a problem is not going to make it go away, but I really think this product team needs to reevaluate this decision and the general future trend.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Despite this hiccup I am very exited about lots of the things I got to see and am really looking forward to .NET 4 and Visual Studio 2010. Now if we only could have a beta today &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;. When we will have a first beta is still a big question though. If a date was announced I missed it, the best I heard was a quarter and is quite a time span.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Enjoy.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;   &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1676278" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WF4/default.aspx">WF4</category></item><item><title>Presenting at VB Central</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/03/presenting-at-vb-central.aspx</link><pubDate>Tue, 03 Mar 2009 13:46:17 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1675358</guid><dc:creator>Maurice</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1675358</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/03/03/presenting-at-vb-central.aspx#comments</comments><description>&lt;p&gt;Next week, on march 10th, I will be doing a presentation on getting started with WCF at the VB Central user group in the Netherlands. Its a free event so if you are in the neighborhood feel free to drop by. They do ask you register beforehand. Besides my session on WCF there will also be a session on using WPF and data binding.&lt;/p&gt;  &lt;p&gt;Mode details and the registration page can be found &lt;a href="http://www.vbcentral.nl/tabid/175/Default.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Hope to see you there.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;   &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt; &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1675358" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category></item><item><title>Patterns &amp; Practices release Prism version 2</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2009/02/18/patterns-amp-practices-release-prism-version-2.aspx</link><pubDate>Wed, 18 Feb 2009 19:01:01 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1672856</guid><dc:creator>Maurice</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1672856</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2009/02/18/patterns-amp-practices-release-prism-version-2.aspx#comments</comments><description>&lt;p&gt;The &lt;a href="http://msdn.microsoft.com/en-us/practices/default.aspx"&gt;Patterns &amp;amp; Practices&lt;/a&gt; group at Microsoft have just released Prism version 2. I am pretty exited about this because Prism version 2 supports both WPF and Silverlight. And as it makes extensive use of the Model - View - ViewModel amongst other design patterns it is a great place to learn, even if you don&amp;#39;t use it as is.&lt;/p&gt; &lt;p&gt;Check out the main &amp;quot;Composite Application Guidance for WPF and Silverlight&amp;quot; page &lt;a href="http://msdn.microsoft.com/en-us/library/dd458809.aspx"&gt;here&lt;/a&gt;. Or read Blaine Wastell about it &lt;a href="http://blogs.msdn.com/blaine/archive/2009/02/18/prism-2-0-is-live.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1672856" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>Data validation - Silverlight versus WPF part 2</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/30/data-validation-silverlight-versus-wpf-part-2.aspx</link><pubDate>Tue, 30 Dec 2008 16:04:52 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1658092</guid><dc:creator>Maurice</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1658092</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/30/data-validation-silverlight-versus-wpf-part-2.aspx#comments</comments><description>&lt;p&gt;In a &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/24/data-validation-silverlight-versus-wpf.aspx"&gt;previous blog post&lt;/a&gt; I pointed out that quite a difference between data validation between Silverlight and WFP. As I don’t think adding data validation in the UI is a good thing I focused on validation in the business object by throwing an exception when the value was not acceptable. As &lt;a href="http://blogs.msdn.com/bethmassi/default.aspx"&gt;Beth&lt;/a&gt; pointed out WPF also supports the IDataErrorInfo interface as she demonstrates &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/06/27/displaying-data-validation-messages-in-wpf.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I think using the IDataErrorInfo interface is superior to throwing exceptions. After all exceptions should be exceptional and users entering invalid data in real applications is not very exceptional&amp;#160; &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;. However Silverlight only contains a subset of the .NET framework and doesn’t include the IDataErrorInfo interface. &lt;/p&gt;  &lt;p&gt;So using the IDataErrorInfo in Silverlight will option will not work right?&lt;/p&gt;  &lt;p&gt;Wrong, it is a very simple interface and we can just add it ourselves. We can even add it using the same namespace System.ComponentModel to when the interface gets added to Silverlight we can just remove our copy &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;.&lt;/p&gt;  &lt;p&gt;So this is my Silverlight implementation of the IDataErrorInfo interface:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; System.ComponentModel
{
    &lt;span style="color:#008000;"&gt;// Summary:&lt;/span&gt;
    &lt;span style="color:#008000;"&gt;//     Provides the functionality to offer custom error information that a user&lt;/span&gt;
    &lt;span style="color:#008000;"&gt;//     interface can bind to.&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IDataErrorInfo
    {
        &lt;span style="color:#008000;"&gt;// Summary:&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//     Gets an error message indicating what is wrong with this object.&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;// Returns:&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//     An error message indicating what is wrong with this object. The default is&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//     an empty string (&amp;quot;&amp;quot;).&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Error { get; }

        &lt;span style="color:#008000;"&gt;// Summary:&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//     Gets the error message for the property with the given name.&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;// Parameters:&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//   columnName:&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//     The name of the property whose error message to get.&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;// Returns:&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;//     The error message for the property. The default is an empty string (&amp;quot;&amp;quot;).&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;[&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; columnName] { get; }
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I just copied this code by right clicking the IDataErrorInfo in my WPF application and selecting all the code shown.&lt;/p&gt;

&lt;p&gt;So how do WPF and Silverlight compare when using the IDataErrorInfo interface?&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;The sample business object is the same person as in the pervious blog post. Only this time I did implement both the IDataErrorInfo and the INotifyPropertyChanged interface. The INotifyPropertyChanged is not really needed in WPF here, it will work just as well without it, but is a good practice to do every time.&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Person : IDataErrorInfo, INotifyPropertyChanged
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _firstName;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; FirstName
    {
        get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _firstName; }
        set
        {
            _firstName = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;;
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.IsNullOrEmpty(_firstName))
                _errors[&lt;span style="color:#006080;"&gt;&amp;quot;FirstName&amp;quot;&lt;/span&gt;] = &lt;span style="color:#006080;"&gt;&amp;quot;The first name cannot be empty.&amp;quot;&lt;/span&gt;;
            &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;
                _errors[&lt;span style="color:#006080;"&gt;&amp;quot;FirstName&amp;quot;&lt;/span&gt;] = &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;;
            OnPropertyChanged(&lt;span style="color:#006080;"&gt;&amp;quot;FirstName&amp;quot;&lt;/span&gt;);
        }
    }

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _lastName;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; LastName
    {
        get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _lastName; }
        set
        {
            _lastName = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;;
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.IsNullOrEmpty(_lastName))
                _errors[&lt;span style="color:#006080;"&gt;&amp;quot;LastName&amp;quot;&lt;/span&gt;] = &lt;span style="color:#006080;"&gt;&amp;quot;The last name cannot be empty.&amp;quot;&lt;/span&gt;;
            &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;
                _errors[&lt;span style="color:#006080;"&gt;&amp;quot;LastName&amp;quot;&lt;/span&gt;] = &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;;
            OnPropertyChanged(&lt;span style="color:#006080;"&gt;&amp;quot;LastName&amp;quot;&lt;/span&gt;);
        }
    }

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt; _errors = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Error
    {
        get
        {
            StringBuilder sb = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StringBuilder();
            &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (var item &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; _errors)
                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (item.Value != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
                    sb.AppendLine(item.Value);

            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; sb.ToString();
        }
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;[&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; columnName]
    {
        get
        {
            &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; result = &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;;
            _errors.TryGetValue(columnName, &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; result);

            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; result;
        }
    }

    &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OnPropertyChanged(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; propertyName)
    {
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (PropertyChanged != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            PropertyChanged(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; PropertyChangedEventArgs(propertyName));
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The WPF application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The XAML in the WPF application is simple, even simpler as previous blog post and looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;150&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Firstname:&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding FirstName, ValidatesOnDataErrors=True}&amp;quot;&lt;/span&gt; 
             &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Lastname:&amp;quot;&lt;/span&gt; 
               &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding LastName, ValidatesOnDataErrors=True}&amp;quot;&lt;/span&gt; 
             &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Button&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Content&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Close&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Nice, no longer do we need to add the ValidationRules collection and add the ExceptionValidationRule to it, instead all we have to do it set the ValidatesOnDataErrors to true. Much nicer &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_261EBC91.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="114" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_thumb_5F00_03C9B7C9.png" width="304" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How about the Silverlight application?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Silverlight XAML isn’t much more complicated and looks like this:&lt;/p&gt;
&lt;font color="#ff0000" size="2"&gt;
  &lt;div&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Background&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;White&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;150&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt;  &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;20&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Firstname:&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding FirstName, Mode=TwoWay}&amp;quot;&lt;/span&gt; 
             &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;local:ErrorStatus&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;PropertyName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;FirstName&amp;quot;&lt;/span&gt;  &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Lastname:&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding LastName, Mode=TwoWay}&amp;quot;&lt;/span&gt; 
             &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;local:ErrorStatus&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;PropertyName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LastName&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Button&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Content&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Close&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Click&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Button_Click&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
  &lt;/div&gt;

  &lt;p&gt;&lt;/p&gt;

  &lt;p&gt;&lt;font color="#ffffff"&gt;The main difference is the addition of two local:ErrorStatus elements. Most of the extra complexity is in this control which is needed because Silverlight has no default way to display validation errors. Please note that there is no longer a BindingValidationError handler involved, everything the app needs is done in XAML, much better than the approach when throwing exceptions. Also note that all I need to do is set the PropertyName attribute to indicate which property validation to display. When run this page looks like this: &lt;/font&gt;&lt;/p&gt;
&lt;/font&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_6C9E3D4A.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="238" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_thumb_5F00_5BB9995A.png" width="507" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The ErrorStatus control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All “magic” happens inside of the ErrorStatus control. This is a real simple user control. Now if I wanted to create a reusable control I would need to put some more work into it and use the VisualStateManager with the States&amp;amp;Parts model but this simple control is enough to demonstrate the solution.&lt;/p&gt;

&lt;p&gt;The ErrorStatus.xaml looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SilverlightApplication5.ErrorStatus&amp;quot;&lt;/span&gt;
    &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt; 
    &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt; 
    &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;16&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;16&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Ellipse&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Fill&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Red&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Foreground&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;White&amp;quot;&lt;/span&gt; 
                   &lt;span style="color:#ff0000;"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; 
                   &lt;span style="color:#ff0000;"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Stretch&amp;quot;&lt;/span&gt; 
                   &lt;span style="color:#ff0000;"&gt;FontWeight&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Bold&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;!&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Real simple, just a red circle with a white exclamation mark in it.&lt;/p&gt;

&lt;p&gt;The code is not very complex either. Most of it is related to either checking if the DataContext changed, see &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/29/how-to-know-when-the-datacontext-changed-in-your-control.aspx"&gt;this post&lt;/a&gt; for an explanation, and when a property value has changed.&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; ErrorStatus : UserControl
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ErrorStatus()
    {
        InitializeComponent();
        SetBinding(MyDataContextProperty, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Binding());
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; DependencyProperty MyDataContextProperty =
        DependencyProperty.Register(&lt;span style="color:#006080;"&gt;&amp;quot;MyDataContext&amp;quot;&lt;/span&gt;, 
                                    &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;), 
                                    &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(ErrorStatus), 
                                    &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; PropertyMetadata(DataContextChanged));

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; DependencyProperty PropertyNameProperty =
        DependencyProperty.Register(&lt;span style="color:#006080;"&gt;&amp;quot;PropertyName&amp;quot;&lt;/span&gt;,
                                    &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;),
                                    &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(ErrorStatus),
                                    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DataContextChanged(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, DependencyPropertyChangedEventArgs e)
    {
        INotifyPropertyChanged person;
        ErrorStatus errorStatus = (ErrorStatus)sender;

        person = e.OldValue &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; INotifyPropertyChanged;
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (person != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            person.PropertyChanged -= errorStatus.person_PropertyChanged;

        person = e.NewValue &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; INotifyPropertyChanged;
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (person != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            person.PropertyChanged += errorStatus.person_PropertyChanged;

        errorStatus.UpdateStatus(e.NewValue);
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; PropertyName
    {
        get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;)GetValue(PropertyNameProperty); }
        set { SetValue(PropertyNameProperty, &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;); }
    }

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; person_PropertyChanged(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, PropertyChangedEventArgs e)
    {
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (e.PropertyName == PropertyName)
            UpdateStatus(sender);
    }

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; UpdateStatus(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender)
    {
        IDataErrorInfo person = sender &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; IDataErrorInfo;
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (person != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        {
            &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; errorText = person[PropertyName];
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.IsNullOrEmpty(errorText))
                Opacity = 0;
            &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;
                Opacity = 100;

            ToolTipService.SetToolTip(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, errorText);
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The real work happens in the UpdateStatus() function right at the bottom. This function is called every time the target property changes or the DataContext is set. Basically it checks if there are any errors and makes the control visible or invisible depending on the result. Besides the control’s visibility it also sets the tooltip text to the error. The only other thing worth mentioning is that I make the control invisible by using the Opacity instead of the Visibility property. The reason is that I do not want to change the layout of the controls on the page just because the validation status changed. WPF has a Visibility option of Visibility.Hidden but unfortunately Silverlight doesn’t support this. Not a big problem as making a control transparent is just a good in this case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using the IDataErrorInfo is a much nicer approach and creating just one, pretty simple, control in Silverlight makes it work just as easy in Silverlight as WPF. So much better than throwing exceptions &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;

&lt;div class="wlWriterEditableSmartContent" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:093dd83a-8472-4629-be8a-751284e2a741" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;p&gt;Download &lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/SilverlightApplication5_5F00_7C07B48C.zip" target="_blank"&gt;the source&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1658092" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>How to know when the DataContext changed in your control</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/29/how-to-know-when-the-datacontext-changed-in-your-control.aspx</link><pubDate>Mon, 29 Dec 2008 13:52:23 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1657976</guid><dc:creator>Maurice</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1657976</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/29/how-to-know-when-the-datacontext-changed-in-your-control.aspx#comments</comments><description>&lt;p&gt;The DataContext is a wonderful property, you can set it somewhere in the logical tree and any child control can just bind to properties without having to know where the DataContext was set. A great capability that makes live much simpler when writing XAML. But sometimes when building a control of some sorts you just need to know when the DataContext has changed. For example when binding to events on whatever object is set as the current DataContext.&lt;/p&gt;  &lt;p&gt;Take for example the following simple form.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_38F12D90.png"&gt;&lt;img title="image" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="258" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_thumb_5F00_51835B91.png" width="354" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In this form I am data bound to a real simple Person object which implements the INotifyPropertyChanged interface so we can be informed that a property has changed. The bottom control is a very simple custom control that displays the last property being changed. The code looks like this:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; MyControl : UserControl
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; MyControl()
    {
        InitializeComponent();
        Loaded += &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; RoutedEventHandler(MyControl_Loaded);
    }

    &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; MyControl_Loaded(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)
    {
        INotifyPropertyChanged person = DataContext &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; INotifyPropertyChanged;
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (person != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            person.PropertyChanged += &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; PropertyChangedEventHandler(person_PropertyChanged);
    }

    &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; person_PropertyChanged(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, PropertyChangedEventArgs e)
    {
        PropertyName.Text = e.PropertyName;
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The Page code looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Page : UserControl
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Page()
    {
        InitializeComponent();
        DataContext = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Person() { FirstName = &lt;span style="color:#006080;"&gt;&amp;quot;Maurice&amp;quot;&lt;/span&gt;, LastName = &lt;span style="color:#006080;"&gt;&amp;quot;de Beijer&amp;quot;&lt;/span&gt; };
    }

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Button_Click(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)
    {
        DataContext = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Person() { FirstName = &lt;span style="color:#006080;"&gt;&amp;quot;John&amp;quot;&lt;/span&gt;, LastName = &lt;span style="color:#006080;"&gt;&amp;quot;Doe&amp;quot;&lt;/span&gt; };
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Pretty simple and it works just fine as long as I don’t press the button.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Pressing the button means I set the DataContext to a new person object. The data binding notices and shows the required changes just fine. However the INotifyPropertyChanged event is still hooked on the old person object and we somehow need to unhook this object and hook the new person object.&lt;/p&gt;

&lt;p&gt;In WPF there is an DataContextChanged event that will let us know the DataContext is changed and we need to change out event binding. Unfortunately Silverlight the FrameworkElement class in Silverlight has the same event but it is marked as internal so we cannot use it &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So how can we know the DataContext has changed is the event is not public? &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It turns out the standard DataBinding holds the answer to the problem. All we need to do is create an extra DependencyProperty and bind that to the DataContext. Sounds complicated but is actually quite simple.&lt;/p&gt;

&lt;p&gt;The new version of my custom control is below.&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; MyControl : UserControl
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; MyControl()
    {
        InitializeComponent();
        SetBinding(MyDataContextProperty, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Binding());
    }


    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; DependencyProperty MyDataContextProperty =
        DependencyProperty.Register(&lt;span style="color:#006080;"&gt;&amp;quot;MyDataContext&amp;quot;&lt;/span&gt;,
                                    &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(Object),
                                    &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(MyControl),
                                    &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; PropertyMetadata(DataContextChanged));

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DataContextChanged(
        &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, 
        DependencyPropertyChangedEventArgs e)
    {
        MyControl myControl = (MyControl)sender;
        INotifyPropertyChanged person = e.NewValue &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; INotifyPropertyChanged;
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (person != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            person.PropertyChanged += myControl.person_PropertyChanged;
    }

    &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; person_PropertyChanged(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, PropertyChangedEventArgs e)
    {
        PropertyName.Text = e.PropertyName;
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Instead of just reading the DataContext property I first created a new DependencyProperty called MyDataContextProperty. The reason this exists is so we can set the PropertyChangedCallback that lets us know when the property is changed. Note there are no normal property get and set methods as we don’t need them. The remaining and most important part to this to work is the line:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;SetBinding(MyDataContextProperty, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Binding());&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This line in the constructor actually bind the value of the MyDataContext to the real DataContext property. &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;With this set up I am free to do whatever I want in the DataContextChanged event that gets fired whenever the DataContext changes. In this example the code just removes the vent handler for the old DataContext PropertyChanged event and adds an event hook on the PropertyChanged event for the new DataContext.&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DataContextChanged(
    &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender,
    DependencyPropertyChangedEventArgs e)
{
    MyControl myControl = (MyControl)sender;
    INotifyPropertyChanged person;

    person = e.OldValue &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; INotifyPropertyChanged;
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (person != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        person.PropertyChanged -= myControl.person_PropertyChanged;

    person = e.NewValue &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; INotifyPropertyChanged;
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (person != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        person.PropertyChanged += myControl.person_PropertyChanged;
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;So all it takes is a few lines of code and we know exactly when the DataContext was changed &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;
  &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1657976" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>Data validation - Silverlight versus WPF</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/24/data-validation-silverlight-versus-wpf.aspx</link><pubDate>Wed, 24 Dec 2008 14:00:34 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1657661</guid><dc:creator>Maurice</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1657661</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/24/data-validation-silverlight-versus-wpf.aspx#comments</comments><description>&lt;p&gt;When I am creating business applications validating the data in business objects, and displaying any errors, is always a big deal. Even though WPF and Silverlight both use XAML and support data binding the default way to display errors is quite different. Now I am focusing on validation in the business object here even though WPF has additional capabilities of validating input in the XAML using ValidationRules. While there might be some good reason to validate data directly in the UI in some cases I find it a requirement to validate data inside a business object so the validation is done regardless of the way the business object is configured.&lt;/p&gt;  &lt;p&gt;Both with Silverlight and WPF it is possible to create business objects that validate their properties. Unfortunately the normal way to do this is by throwing an exception in the property setter if the validation fails. Now I don&amp;#39;t really like this approach, in fact I prefer the approach taken by Rocky Lhotka in &lt;a href="http://www.lhotka.net/cslanet/"&gt;CSLA&lt;/a&gt; or Paul Stovell in his article about &lt;a href="http://www.codeproject.com/KB/cs/DelegateBusinessObjects.aspx"&gt;Delegates and Business Objects&lt;/a&gt;. But that is a subject for another post, lets first take a look at the out of the box behavior.&lt;/p&gt;  &lt;p&gt;The test &amp;quot;business object&amp;quot; I am working with is real simple. In fact so simple that I don&amp;#39;t even implement INotifyPropertyChanged, something I recommend you always do. But for the purposes of validation it serves no useful purpose so I left it out. The Person class, used both in WPF and Silverlight looks like this:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Person
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; FirstName { get; set; }

    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _lastName;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; LastName
    {
        get { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _lastName; }
        set
        {
            _lastName = &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;;
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.IsNullOrEmpty(_lastName))
                &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ArgumentNullException();
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Pretty simple right, the &amp;quot;business rule&amp;quot; here is that the LastName property cannot be empty.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Validation in WPF&lt;/h3&gt;

&lt;p&gt;The XAML used in the WPF sample looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Window&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;WpfApplication1.Window1&amp;quot;&lt;/span&gt;
    &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt;
    &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt;
    &lt;span style="color:#ff0000;"&gt;Title&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Window1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;400&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;150&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Firstname:&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding FirstName}&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Lastname:&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox.Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Binding&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Path&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LastName&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Binding.ValidationRules&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ExceptionValidationRule&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Binding.ValidationRules&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Binding&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;                
            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox.Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Button&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Content&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Close&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Window&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Not very complex but as we can see there is quite a difference between the FirstName TextBox with no validation and the LastName TextBox which must handle the not empty validation. In order for the UI to know about the validation we need to add the Binding.ValidationRules element and add to that the ExceptionValidationRule. The ExceptionValidationRule basically says that any exception raised during the property setter is a failed validation rule. Not very complicated but it does add quite a bit of XAML just to be able to display the fact that something is wrong. When we run the code and empty the LastName TextBox the result looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.DatavalidationSilverlightversusWPF_5F00_C6AD/image_5F00_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="127" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.DatavalidationSilverlightversusWPF_5F00_C6AD/image_5F00_thumb.png" width="444" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The red line around the TextBox indicates that there is some kind of error. Where does the red box come from? Well that is just the default ErrorTemplate used and you are free to change it by setting the Validation.ErrorTemplate property on the TextBox.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Validation in Silverlight&lt;/h3&gt;

&lt;p&gt;The XAML in Silverlight looks somewhat different. The main XAML is pretty much the same but as soon as we get into data binding things look very different. See for yourself:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SilverlightApplication1.Page&amp;quot;&lt;/span&gt;
    &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt; 
    &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt; 
    &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;400&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;300&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Background&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;White&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;150&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;RowDefinition&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Firstname:&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding FirstName}&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Lastname:&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox.Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Binding&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Path&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LastName&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Mode&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;TwoWay&amp;quot;&lt;/span&gt; 
                         &lt;span style="color:#ff0000;"&gt;NotifyOnValidationError&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;True&amp;quot;&lt;/span&gt; 
                         &lt;span style="color:#ff0000;"&gt;ValidatesOnExceptions&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;True&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox.Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBox&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Button&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Content&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Close&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Row&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;2&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Grid&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;Column&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;This time we need to set the NotifyOnValidationError and ValidatesOnExceptions properties of the binding to true. In WPF these properties don&amp;#39;t exist and we used the ValidationRules and ExceptionValidationRule to reach the same effect. So what happens when we run this and clear out the LastName TextBox? Actually the validation fails, the exception is thrown and we don&amp;#39;t see anything at all &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;. The reason is that in Silverlight there is no Validation.ErrorTemplate, instead we have to do something to let the user know an error occurred. In order to do so we need to subscribe to the BindingValidationError event that fires as soon as a validation fails. To achieve a similar effect as the WPF application we could use some code like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Page()
{
    InitializeComponent();
    BindingValidationError += &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; EventHandler&amp;lt;ValidationErrorEventArgs&amp;gt;(Page_BindingValidationError);
}

&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; Brush _borderBrush = &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;;
&lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Page_BindingValidationError(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, ValidationErrorEventArgs e)
{
    Control control = (Control)e.OriginalSource;

    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (_borderBrush == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        _borderBrush = control.BorderBrush;

    &lt;span style="color:#0000ff;"&gt;switch&lt;/span&gt; (e.Action)
    {
        &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; ValidationErrorEventAction.Added:
            control.BorderBrush = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Red);
            &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
        &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; ValidationErrorEventAction.Removed:
            control.BorderBrush = _borderBrush;
            &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
        &lt;span style="color:#0000ff;"&gt;default&lt;/span&gt;:
            &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Not very complicated but still we need to do so in code. Of course the BindingValidationError event doesn&amp;#39;t exist in WPF either so non of this XAML or code would post from Silverlight back to WPF &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;.&lt;/p&gt;

&lt;p&gt;The effect is the same as in WPF however and looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.DatavalidationSilverlightversusWPF_5F00_C6AD/image_5F00_4.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="267" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.DatavalidationSilverlightversusWPF_5F00_C6AD/image_5F00_thumb_5F00_1.png" width="463" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Validation is quite different in WPF and Silverlight making for non portable XAML and code. However the biggest deal is that validation, at least on the WPF side, is more focused on the UI that the business layer where it should be. And the small part where the validation in the UI is used it is completely focused on exceptions and not in business rules, something far superior. So for any serious business application this subject needs some significant work, just like Rock Lhotka had to do with his CSLA framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;
  &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1657661" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>WrapPanel in ListBox revisited</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/08/wrappanel-in-listbox-revisited.aspx</link><pubDate>Mon, 08 Dec 2008 18:11:42 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1656182</guid><dc:creator>Maurice</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1656182</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/08/wrappanel-in-listbox-revisited.aspx#comments</comments><description>&lt;p&gt;Last week logged about using a WrapPanel in a listBox and demonstrated how to get the content to wrap around, read about it &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/11/18/some-more-fun-with-a-silverlight-listbox.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Turns out the XAML can be even easier. In the previous post I used a ControlTemplate with a Grid to stop the WrapPanel from just expanding horizontally. Turns out there us an even easier way to do so by disabling the horizontal scrollbar using the ListBox ScrollViewer. The following XAML will do the trick just fine:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;xmlns:controls&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls&amp;quot;&lt;/span&gt;  
             &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SilverlightApplication4.Page&amp;quot;&lt;/span&gt;
             &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt; 
             &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt; 
             &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;400&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;300&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Background&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;White&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ListBox&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;DemoList&amp;quot;&lt;/span&gt; 
                 &lt;span style="color:#ff0000;"&gt;ScrollViewer&lt;/span&gt;.&lt;span style="color:#ff0000;"&gt;HorizontalScrollBarVisibility&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Disabled&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ListBox.ItemsPanel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ItemsPanelTemplate&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;controls:WrapPanel&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;ItemsPanelTemplate&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;ListBox.ItemsPanel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTemplate&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;TextBlock&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding}&amp;quot;&lt;/span&gt; 
                   &lt;span style="color:#ff0000;"&gt;TextAlignment&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Right&amp;quot;&lt;/span&gt; 
                   &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;25&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;DataTemplate&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;ListBox&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Used in combination with the following code:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Linq;
&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Windows;
&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Windows.Controls;

&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; SilverlightApplication4
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Page : UserControl
    {
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Page()
        {
            InitializeComponent();
            Loaded += &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; RoutedEventHandler(Page_Loaded);
        }

        &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Page_Loaded(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)
        {
            DemoList.ItemsSource = Enumerable.Range(1, 250);
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;it produces this Silverlight page:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_4C441D02.png"&gt;&lt;img title="image" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="244" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_thumb_5F00_0BA46144.png" width="234" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We even get some keyboard support with the new XAML although I am not quite sure if I am happy about that or not. Selecting an element and pressing the down arrow key makes the selection move to the right. Makes sense in that it is the next item in the ItemsSource bit not quite what I was hoping for.&lt;/p&gt;

&lt;p&gt;Just for a quick comparison I copied the XAML and code to a WPF application to see what would happen there. Fortunately the only change I hard to make to the ListBox was removing the controls namespace. Great &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_71D2BBC5.png"&gt;&lt;img title="image" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="244" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_thumb_5F00_01092493.png" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;When I ran the same in WPF I do see the keyboard behavior I would like. Pressing the down arrow selects the next item below the current, the same with up and the other arrow keys and even the page up/down scroll a page but move in the same column. Now this is much better behavior!&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;
  &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1656182" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>Unit testing in Silverlight part 2</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/07/unit-testing-in-silverlight-part-2.aspx</link><pubDate>Sun, 07 Dec 2008 21:11:23 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1656093</guid><dc:creator>Maurice</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1656093</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/12/07/unit-testing-in-silverlight-part-2.aspx#comments</comments><description>&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/02/unit-testing-in-silverlight-part-1.aspx"&gt;Part 1&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/07/unit-testing-in-silverlight-part-2.aspx"&gt;Part 2&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/07/unit-testing-in-silverlight-part-3.aspx"&gt;Part 3&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2009/01/26/unit-testing-in-silverlight-part-4-the-ui.aspx"&gt;Part 4&lt;/a&gt;   &lt;p&gt;In my previous post I described the basic setup of unit testing in Silverlight, you can read all about it &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/02/unit-testing-in-silverlight-part-1.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The basics where very nice but lots of code we write in Silverlight has to do with networking and in Silverlight that means asynchronous code, something that is always hard to test!&lt;/p&gt;  &lt;p&gt;Because, just I like using &lt;a href="http://www.flickr.com"&gt;Flickr&lt;/a&gt;, lets download some pictures and see what it takes to make that testable. Below is the very simple application we need to unit test, basically a list of pictures from &lt;a href="http://www.flickr.com/photos/mauricedb/"&gt;my Flickr photo stream&lt;/a&gt;.&lt;/p&gt; &lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_2698148C.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="215" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_thumb_5F00_6376D922.png" width="244" border="0" /&gt;&lt;/a&gt;   &lt;p&gt;Nothing fancy, just a ListBox with pictures &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;  &lt;p&gt;The code in the page is no big deal either and looks like this:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Page : UserControl
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Page()
    {
        InitializeComponent();
        Loaded += &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; RoutedEventHandler(Page_Loaded);
    }

    &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Page_Loaded(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)
    {
        PhotoCollection photoCollection = 
            (PhotoCollection)Resources[&lt;span style="color:#006080;"&gt;&amp;quot;PhotoCollectionDS&amp;quot;&lt;/span&gt;];
        FlickrRequest request = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FlickrRequest();

        request.PhotoSearchByUser(&lt;span style="color:#006080;"&gt;&amp;quot;97044050@N00&amp;quot;&lt;/span&gt;, 
            (photo) =&amp;gt; photoCollection.Add(photo));
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Basically it just retrieves the PhotoCollection, creates a FlickrRequest object and tells it to search for a users photos and add each photo found to the collection. The PhotoCollection is no big deal either and is just a ObservableCollection&amp;lt;Photo&amp;gt;.&lt;/p&gt;

&lt;p&gt;The interesting stuff is in the FlickrRequest class. This is the one that needs to be unit tested and looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; FlickrRequest
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;const&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _flickrUrl = &lt;span style="color:#006080;"&gt;&amp;quot;http://api.flickr.com/services/rest&amp;quot;&lt;/span&gt;;

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; PhotoSearchByUser(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; userId, Action&amp;lt;Photo&amp;gt; action)
    {
        &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; url = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(
            &lt;span style="color:#006080;"&gt;@&amp;quot;{0}/?method={1}&amp;amp;api_key={2}&amp;amp;user_id={3}&amp;amp;extras=original_format&amp;quot;&lt;/span&gt;,
            _flickrUrl, &lt;span style="color:#006080;"&gt;&amp;quot;flickr.photos.search&amp;quot;&lt;/span&gt;, App.FlickrApiKey, userId);

        WebClient client = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WebClient();
        client.OpenReadCompleted += (sender, e) =&amp;gt;
        {
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (e.Error == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            {
                FlickrResponse response = DeserializeResult(e.Result);
                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (response.Status == &lt;span style="color:#006080;"&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;)
                {
                    &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (var photo &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; response.Photos.Photos)
                        action(photo);

                    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (response.Photos.Page &amp;lt; response.Photos.PageCount)
                    {
                        &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; nextUrl = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color:#006080;"&gt;&amp;quot;{0}&amp;amp;page={1}&amp;quot;&lt;/span&gt;, 
                            url, response.Photos.Page + 1);
                        client.OpenReadAsync(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Uri(nextUrl));
                    }
                }
            }
        };

        client.OpenReadAsync(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Uri(url));
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; FlickrResponse DeserializeResult(Stream stream)
    {
        FlickrResponse response = &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;;
        &lt;span style="color:#0000ff;"&gt;try&lt;/span&gt;
        {
            XmlSerializer ser = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; XmlSerializer(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(FlickrResponse));
            response = (FlickrResponse)ser.Deserialize(stream);
        }
        &lt;span style="color:#0000ff;"&gt;catch&lt;/span&gt; (InvalidOperationException)
        {
            response = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FlickrResponse();
        }

        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (response.Photos == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            response.Photos = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ResponsePhotoCollection();
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (response.Photos.Photos == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
            response.Photos.Photos = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Photo[] { };

        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; response;
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The PhotoSearchByUser function here is the interesting one as it uses the WebClient class and the Flickr REST API to download the photo information. This code also has the complexity that not all the data is returned from the first call but we need to do multiple calls to get all the photo information. Creating a unit test should be straightforward expect for the fact that we do not want to depend on Flickr and fake out the networking parts. After all if we didn’t it would be a integration test instead of a unit test. So we need to somehow fake the networking behavior.&lt;/p&gt;

&lt;p&gt;With regular .NET code I use TypeMock to help out with unit testing and I am sure that would make live easy here but unfortunately there is no Silverlight version of TypeMock yet. In fact, as far as I am aware, there is not a single mock framework for use with Silverlight. So we need to do this some other way.&lt;/p&gt;

&lt;p&gt;First we need to get rid of the WebClient class because non of its methods are virtual and we cannot substitute another type. So the first thing I did was create a TestableWebClient, which looks just like the original WebClient only it allows me to change the behavior for testing purposes. The TestableWeblient looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; TestableWebClient
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;event&lt;/span&gt; EventHandler&amp;lt;TestableOpenReadCompletedEventArgs&amp;gt; OpenReadCompleted;

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OpenReadAsync(Uri address)
    {
        WebClient client = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WebClient();
        client.OpenReadCompleted += (s, e) =&amp;gt;
            {
                OnOpenReadCompleted(e);
            };
        client.OpenReadAsync(address);
    }

    &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OnOpenReadCompleted(OpenReadCompletedEventArgs e)
    {
        TestableOpenReadCompletedEventArgs args = &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; TestableOpenReadCompletedEventArgs(e);
        OnOpenReadCompleted(args);
    }

    &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OnOpenReadCompleted(TestableOpenReadCompletedEventArgs e)
    {
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (OpenReadCompleted != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        {
            OpenReadCompleted(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, e);
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Unfortunately the OpenReadCompletedEventArgs type doesn’t have a public constructor so I cannot create one myself so I have to use a TestableOpenReadCompletedEventArgs instead. This class looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; TestableOpenReadCompletedEventArgs : AsyncCompletedEventArgs
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; TestableOpenReadCompletedEventArgs(
        Stream result, Exception error, &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; cancelled, &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; userState)
        : &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;(error, cancelled, userState)
    {
        Result = result;
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; TestableOpenReadCompletedEventArgs(
        OpenReadCompletedEventArgs args)
        : &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;(args.Error, args.Cancelled, args.UserState)
    {
        Result = args.Result;
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Stream Result { get; &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; set; }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So with these new classes I can change the PhotoSearchByUser function to use the new class and it now looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; PhotoSearchByUser(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; userId, Action&amp;lt;Photo&amp;gt; action)
{
    &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; url = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(
        &lt;span style="color:#006080;"&gt;@&amp;quot;{0}/?method={1}&amp;amp;api_key={2}&amp;amp;user_id={3}&amp;amp;extras=original_format&amp;quot;&lt;/span&gt;,
        _flickrUrl, &lt;span style="color:#006080;"&gt;&amp;quot;flickr.photos.search&amp;quot;&lt;/span&gt;, App.FlickrApiKey, userId);

    TestableWebClient client = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; TestableWebClient();
    client.OpenReadCompleted += (sender, e) =&amp;gt;
    {
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (e.Error == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        {
            FlickrResponse response = DeserializeResult(e.Result);
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (response.Status == &lt;span style="color:#006080;"&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;)
            {
                &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (var photo &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; response.Photos.Photos)
                    action(photo);

                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (response.Photos.Page &amp;lt; response.Photos.PageCount)
                {
                    &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; nextUrl = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color:#006080;"&gt;&amp;quot;{0}&amp;amp;page={1}&amp;quot;&lt;/span&gt;, 
                        url, response.Photos.Page + 1);
                    client.OpenReadAsync(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Uri(nextUrl));
                }
            }
        }
    };

    client.OpenReadAsync(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Uri(url));
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Not much changes, in fact only a single line changed but we are not quite there yet. We still need a way to get our unit tests to use a different TestableWebClient implementation. Do do so I will pass in the type of TestableWebClient to use with the FlickrRequest constructor. Check the new code:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; FlickrRequest
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; _flickrUrl = &lt;span style="color:#006080;"&gt;&amp;quot;http://api.flickr.com/services/rest&amp;quot;&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; Type _webClientType = &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(TestableWebClient);

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; FlickrRequest()
    {
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; FlickrRequest(Type webClientType)
    {
        _webClientType = webClientType;
    }

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; PhotoSearchByUser(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; userId, Action&amp;lt;Photo&amp;gt; action)
    {
        &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; url = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(
            &lt;span style="color:#006080;"&gt;@&amp;quot;{0}/?method={1}&amp;amp;api_key={2}&amp;amp;user_id={3}&amp;amp;extras=original_format&amp;quot;&lt;/span&gt;,
            _flickrUrl, &lt;span style="color:#006080;"&gt;&amp;quot;flickr.photos.search&amp;quot;&lt;/span&gt;, App.FlickrApiKey, userId);

        TestableWebClient client = (TestableWebClient)&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Activator.CreateInstance(_webClientType);
        
        &lt;span style="color:#008000;"&gt;// Rest of the code left out.&lt;/span&gt;
    }
}&lt;/pre&gt;
&lt;/div&gt;
Now we can start testing this code &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt; 

&lt;p&gt;I created two unit tests for this code as an example, they look like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;[TestClass]
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; FlickrDownloadTest : SilverlightTest
{
    [TestMethod]
    [Asynchronous]
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Test1()
    {
        FlickrRequest request = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FlickrRequest(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(MockTestableWebClient));

        request.PhotoSearchByUser(&lt;span style="color:#006080;"&gt;&amp;quot;97044050@N00&amp;quot;&lt;/span&gt;, (photo) =&amp;gt; EnqueueTestComplete());
    }
    
    [TestMethod]
    [Asynchronous]
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Test2()
    {
        &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; pageCount = 0;
        FlickrRequest request = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FlickrRequest(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(MockTestableWebClient));

        request.PhotoSearchByUser(&lt;span style="color:#006080;"&gt;&amp;quot;97044050@N00&amp;quot;&lt;/span&gt;, (photo) =&amp;gt; pageCount++);
        EnqueueConditional(() =&amp;gt;
            {
                &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; pageCount == 5;
            });
        EnqueueTestComplete();
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The fake, or mock, WebClient looks like this:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; MockTestableWebClient : TestableWebClient
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; _page = 0;

    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OpenReadAsync(Uri address)
    {
        _page++;

        FlickrResponse response = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FlickrResponse();
        response.Status = &lt;span style="color:#006080;"&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;;
        response.Photos = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ResponsePhotoCollection();
        response.Photos.Page = _page;
        response.Photos.PageCount = 5;
        response.Photos.Photos = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Photo[] { &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Photo() };
        Stream stream = SerializeResult(response);
        stream.Position = 0;
        TestableOpenReadCompletedEventArgs args = 
            &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; TestableOpenReadCompletedEventArgs(stream, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);
        OnOpenReadCompleted(args);
    }


    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; Stream SerializeResult(FlickrResponse response)
    {
        MemoryStream stream = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; MemoryStream();
        XmlSerializer ser = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; XmlSerializer(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(FlickrResponse));
        ser.Serialize(stream, response);

        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; stream;
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Basically I just return a response stating that there are 5 pages and each contains a single blank photo.&lt;/p&gt;

&lt;p&gt;Running these tests produces the following output showing both tests passed &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_0C17D5DB.png"&gt;&lt;img title="image" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="413" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver/image_5F00_thumb_5F00_5FB5E1FA.png" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Am I happy with the changes I had to make to the Silverlight app to make it unit testable? Well yes and no. I didn’t like having to create a wrapper class for the WebClient and the OpenReadCompletedEventArgs. Bit now that I have done so creating using other test for code using the WebClient is a lot easier. In this case I only added the OpenReadAsync() function but doing the same with the other functions is a breeze. And the end result is I could unit test the code in PhotoSearchByUser() pretty much the way I wrote it without having to change the code a lot just to make it unit testable and that is good! So overall I am reasonably happy with the result &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;

&lt;p&gt;I pretty much skipped all details of the actual unit testing code itself. Now there is some new stuff so in a future blog post I am going to explain what I did in the unit tests themselves.&lt;/p&gt;

&lt;p&gt;And thanks to &lt;a href="http://www.jeff.wilcox.name/"&gt;Jeff Wilcox&lt;/a&gt; for providing some useful feedback.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Update: &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/02/unit-testing-in-silverlight-part-1.aspx"&gt;Part 1&lt;/a&gt;, &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/07/unit-testing-in-silverlight-part-2.aspx"&gt;Part 2&lt;/a&gt;, &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/12/28/unit-testing-in-silverlight-part-3.aspx"&gt;Part 3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1656093" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>PDC session download</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/11/01/pdc-session-download.aspx</link><pubDate>Sat, 01 Nov 2008 10:17:52 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1652746</guid><dc:creator>Maurice</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1652746</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/11/01/pdc-session-download.aspx#comments</comments><description>&lt;p&gt;Want to download and watch all PDC content? Then there are a couple of ways to get at them. The official way if to go through the session agenda at the conference site. See &lt;a title="https://sessions.microsoftpdc.com/public/timeline.aspx" href="https://sessions.microsoftpdc.com/public/timeline.aspx"&gt;https://sessions.microsoftpdc.com/public/timeline.aspx&lt;/a&gt;. You see all sessions but it takes a bit of work. Another nice way is through Channel 9 by using the following feed: &lt;a title="http://channel9.msdn.com/posts/pdc2008/RSS/?tag=videos" href="http://channel9.msdn.com/posts/pdc2008/RSS/?tag=videos"&gt;http://channel9.msdn.com/posts/pdc2008/RSS/?tag=videos&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;But the best as far as I am concerned is using the list compiled by Greg Duncan. Check this list &lt;a title="http://coolthingoftheday.blogspot.com/2008/10/pdc2008-quick-video-link-list.html" href="http://coolthingoftheday.blogspot.com/2008/10/pdc2008-quick-video-link-list.html"&gt;http://coolthingoftheday.blogspot.com/2008/10/pdc2008-quick-video-link-list.html&lt;/a&gt;. And it even has the Visual Basic source code used to generate the list &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt; &lt;p&gt;Enjoy the videos!&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;&lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1652746" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/webcast/default.aspx">webcast</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/ClickOnce/default.aspx">ClickOnce</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/SqlCe/default.aspx">SqlCe</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/IronPython/default.aspx">IronPython</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/PDC/default.aspx">PDC</category></item><item><title>Using the ReplicatorActivity in Parallel mode</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/10/22/using-the-replicatoractivity-in-parallel-mode.aspx</link><pubDate>Wed, 22 Oct 2008 15:17:11 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1651624</guid><dc:creator>Maurice</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1651624</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/10/22/using-the-replicatoractivity-in-parallel-mode.aspx#comments</comments><description>&lt;p&gt;I have heard quite a few times that the ReplicatorActivity can only be use in parallel mode with a custom activity. The reason being that you need an extra property to store the current child data.&lt;/p&gt; &lt;p&gt;When the ReplicatorActivity works in sequential mode the following code works just fine:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;private void &lt;/span&gt;codeActivity1_ExecuteCode(&lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, &lt;span style="color:#2b91af;"&gt;EventArgs &lt;/span&gt;e)
{
    &lt;span style="color:blue;"&gt;int &lt;/span&gt;value = (&lt;span style="color:blue;"&gt;int&lt;/span&gt;)replicatorActivity1.CurrentChildData[replicatorActivity1.CurrentIndex];
    &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Loop value = {0}&amp;quot;&lt;/span&gt;, value);
}&lt;/pre&gt;
&lt;p&gt;However when run in parallel the current index always point to the last item so this doesn&amp;#39;t work. As an aside I think this is a bug as it results in hard to find errors. IMHO the ReplicatorActivity CurrentIndex should be -1 or some other value that would trigger either an IndexOutOfRangeException or an InvalidOperationException. Unfortunately that is not the case &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;.&lt;/p&gt;
&lt;p&gt;Instead when we set the mode to parallel we need to use the ChildInitialized event to save the child data for that loop. So we need a place to store it.&lt;/p&gt;
&lt;p&gt;Traditional thinking results in an extra property being added that is being scoped to the loop and an extra property means a custom activity to add it to.&lt;/p&gt;
&lt;p&gt;But wait a minute doesn&amp;#39;t every workflow foundation activity derive from DependencyObject and isn&amp;#39;t that class all about using dependency properties?&lt;/p&gt;
&lt;p&gt;Yes it is and that is exactly the reason you don&amp;#39;t need a custom activity. In fact you can add as much extra data to any activity as you like!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;How to add custom data to the standard activities&lt;/h2&gt;
&lt;p&gt;The trick is in using a DependencyProperty that is created using the DependencyProperty.RegisterAttached() function. This creates an attached property you can use to store data in activities that have no clue about the data. So the first step is to create a dependency property like this:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public static &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;DependencyProperty &lt;/span&gt;LoopValueProperty = 
    &lt;span style="color:#2b91af;"&gt;DependencyProperty&lt;/span&gt;.RegisterAttached(&lt;span style="color:#a31515;"&gt;&amp;quot;LoopValue&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt;), &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;Workflow1&lt;/span&gt;));
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Now in the ChildInitialized event we van store the loop value in child activity like this:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;private void &lt;/span&gt;replicatorActivity1_ChildInitialized(
    &lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, 
    &lt;span style="color:#2b91af;"&gt;ReplicatorChildEventArgs &lt;/span&gt;e)
{
    e.Activity.SetValue(LoopValueProperty, e.InstanceData);
}&lt;/pre&gt;
&lt;p&gt;Easy right &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;
&lt;p&gt;So if I add a code activity as the child just to print the data all I need is the following code:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;private void &lt;/span&gt;codeActivity1_ExecuteCode(&lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, &lt;span style="color:#2b91af;"&gt;EventArgs &lt;/span&gt;e)
{
    &lt;span style="color:#2b91af;"&gt;Activity &lt;/span&gt;activity = (&lt;span style="color:#2b91af;"&gt;Activity&lt;/span&gt;)sender;
    &lt;span style="color:blue;"&gt;int &lt;/span&gt;value = (&lt;span style="color:blue;"&gt;int&lt;/span&gt;)activity.GetValue(LoopValueProperty);&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;    Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;The current value = {0}&amp;quot;&lt;/span&gt;, value); 
}
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;h2&gt;A slightly larger example showing the parallel behavior&lt;/h2&gt;
&lt;p&gt;Below is a slightly more complex example showing this. I have added a DelayActivity with a random timeout just to show that the ReplicatorActivity is really running in parallel.&lt;/p&gt;
&lt;p&gt;The workflow looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.UsingtheReplicatorActivityinParallelmode_5F00_ECF8/image_5F00_2.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="461" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.UsingtheReplicatorActivityinParallelmode_5F00_ECF8/image_5F00_thumb.png" width="607" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;And when run this produces the following output:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.UsingtheReplicatorActivityinParallelmode_5F00_ECF8/image_5F00_4.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="335" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/theproblemsolver.UsingtheReplicatorActivityinParallelmode_5F00_ECF8/image_5F00_thumb_5F00_1.png" width="672" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The complete code behind file looks like this:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public sealed partial class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Workflow1 &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;SequentialWorkflowActivity
&lt;/span&gt;{
    &lt;span style="color:blue;"&gt;public &lt;/span&gt;Workflow1()
    {
        InitializeComponent();
    }

    &lt;span style="color:blue;"&gt;public static &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;DependencyProperty &lt;/span&gt;LoopValueProperty = 
        &lt;span style="color:#2b91af;"&gt;DependencyProperty&lt;/span&gt;.RegisterAttached(&lt;span style="color:#a31515;"&gt;&amp;quot;LoopValue&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt;), &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;Workflow1&lt;/span&gt;));


    &lt;span style="color:blue;"&gt;private void &lt;/span&gt;replicatorActivity1_Initialized(&lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, &lt;span style="color:#2b91af;"&gt;EventArgs &lt;/span&gt;e)
    {
        &lt;span style="color:#2b91af;"&gt;ReplicatorActivity &lt;/span&gt;replicator = (&lt;span style="color:#2b91af;"&gt;ReplicatorActivity&lt;/span&gt;)sender;
        replicator.InitialChildData = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt;(&lt;span style="color:#2b91af;"&gt;Enumerable&lt;/span&gt;.Range(1, 20));
    }

    &lt;span style="color:blue;"&gt;private void &lt;/span&gt;delayActivity1_InitializeTimeoutDuration(&lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, &lt;span style="color:#2b91af;"&gt;EventArgs &lt;/span&gt;e)
    {
        &lt;span style="color:#2b91af;"&gt;DelayActivity &lt;/span&gt;delay = (&lt;span style="color:#2b91af;"&gt;DelayActivity&lt;/span&gt;)sender;
        &lt;span style="color:#2b91af;"&gt;Random &lt;/span&gt;random = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Random&lt;/span&gt;();
        delay.TimeoutDuration = &lt;span style="color:#2b91af;"&gt;TimeSpan&lt;/span&gt;.FromSeconds(random.Next(5));
    }

    &lt;span style="color:blue;"&gt;private void &lt;/span&gt;replicatorActivity1_ChildInitialized(
        &lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, 
        &lt;span style="color:#2b91af;"&gt;ReplicatorChildEventArgs &lt;/span&gt;e)
    {
        e.Activity.SetValue(LoopValueProperty, e.InstanceData);
    }

    &lt;span style="color:blue;"&gt;private void &lt;/span&gt;codeActivity1_ExecuteCode(&lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, &lt;span style="color:#2b91af;"&gt;EventArgs &lt;/span&gt;e)
    {
        &lt;span style="color:#2b91af;"&gt;Activity &lt;/span&gt;activity = (&lt;span style="color:#2b91af;"&gt;Activity&lt;/span&gt;)sender;
        &lt;span style="color:blue;"&gt;int &lt;/span&gt;value = (&lt;span style="color:blue;"&gt;int&lt;/span&gt;)activity.Parent.GetValue(LoopValueProperty);&lt;span style="color:#2b91af;"&gt;&lt;br /&gt;        Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;The current value = {0}&amp;quot;&lt;/span&gt;, value);
    }
}
&lt;/pre&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;&lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1651624" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category></item><item><title>Red Gate to continue development of .NET Reflector</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/08/20/red-gate-to-continue-development-of-net-reflector.aspx</link><pubDate>Wed, 20 Aug 2008 07:04:54 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1645153</guid><dc:creator>Maurice</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1645153</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/08/20/red-gate-to-continue-development-of-net-reflector.aspx#comments</comments><description>&lt;p&gt;.NET Reflector, by Lutz Roeder, must be one of the most useful tools I have when developing .NET code. Usually it is the first thing I install right after Visual Studio not even waiting until I need it because I know I will.&lt;/p&gt; &lt;p&gt;So the big news is that Red Gate, makers of the Ants profiler and lots of other tools, are taking over from Lutz Roeder and will continue developing .NET Reflector. Interesting move and I hope this means a bright future for the .NET Reflector.&lt;/p&gt; &lt;p&gt;Read more about this &lt;a href="http://www.simple-talk.com/reflector/interview.htm"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Enjoy!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.theproblemsolver.nl/"&gt;www.TheProblemSolver.nl &lt;/a&gt;&lt;br /&gt;&lt;a href="http://wiki.windowsworkflowfoundation.eu/"&gt;Wiki.WindowsWorkflowFoundation.eu&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1645153" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/SqlCe/default.aspx">SqlCe</category></item><item><title>Using a TransactionScopeActivity within a ReceiveActivity in a state machine workflow</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/08/13/using-a-transactionscopeactivity-within-a-receiveactivity-in-a-state-machine-workflow.aspx</link><pubDate>Wed, 13 Aug 2008 10:31:45 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1644506</guid><dc:creator>Maurice</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1644506</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/08/13/using-a-transactionscopeactivity-within-a-receiveactivity-in-a-state-machine-workflow.aspx#comments</comments><description>&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/08/06/using-a-transactionscopeactivity-with-a-wcf-receiveactivity.aspx"&gt;Part 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/08/08/more-on-using-a-transactionscopeactivity-within-a-receiveactivity.aspx"&gt;part 2&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/08/13/using-a-transactionscopeactivity-within-a-receiveactivity-in-a-state-machine-workflow.aspx"&gt;Part 3&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/09/16/a-bit-more-about-using-transactionscopeactivity-within-a-receiveactivity.aspx"&gt;Part 4&lt;/a&gt;  &lt;p&gt;In two previous blog posts, &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/08/06/using-a-transactionscopeactivity-with-a-wcf-receiveactivity.aspx"&gt;part one&lt;/a&gt; and &lt;a href="http://msmvps.com/blogs/theproblemsolver/archive/2008/08/08/more-on-using-a-transactionscopeactivity-within-a-receiveactivity.aspx"&gt;part two&lt;/a&gt;, I covered the fact that the ReceiveActivity and the TransactionScopeActivity don&amp;#39;t work together very well. I demonstrated this using a sequential workflow and did show a, clumsy and hacky, workaround to get at least the initial request working. So while the request that starts the sequential workflow could work the same is not true for any subsequent calls.&lt;/p&gt; &lt;h2&gt;But what about a state workflow?&lt;/h2&gt; &lt;p&gt;State workflow&amp;#39;s are very different then sequential workflow&amp;#39;s because they are completely event driven. With every state you need to add an EventDrivenActivity and the first child should implement the IEventActivity interface. Well the ReceiveActivity does just that so we can use it to initiate a state machine workflow and triggers its events. However as you might expect a TransactionScopeActivity is not an IEventActivity so it cannot be the first child of the EventDrivenActivity. And that means you cannot wrap the ReceiveActivity inside of an TransactionScopeActivity, something that sort of solved the problem with a sequential workflow. Of course nesting the TransactionScopeActivity inside of the ReceiveActivity won&amp;#39;t work either for the reasons described in the first two post. So far so bad &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;&lt;/p&gt; &lt;h2&gt;So we need another workaround&lt;/h2&gt; &lt;p&gt;Again there is no real good workaround &lt;img src="http://msmvps.com/emoticons/emotion-6.gif" alt="Sad" /&gt;. In fact the only one I can come up with is stop using the TransactionScopeActivity all together. So how to do transactions without using the TransactionScopeActivity?&lt;/p&gt; &lt;p&gt;Well the solution, ahem workaround, is to use the WorkflowEnvironment.WorkBatch object and add all pending work to it. The first parameter is an object of type IPendingWork and this is the one that is actually going to be called to do the work. The second parameter, the workItem, contains the data. Now when a workflow per persistence point is reached the IPendingWork object is called to do its work. &lt;/p&gt;&lt;span style="color:blue;"&gt;&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Serializable()]
&lt;/span&gt;&lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Workflow1PendingWork : IPendingWork
{
    &lt;/span&gt;&lt;span style="color:blue;"&gt;#region IPendingWork Members

    public void Commit(&lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Transaction transaction, ICollection items)
    {
        &lt;/span&gt;&lt;span style="color:blue;"&gt;foreach (var Workflow1PendingWork in items)
        {
            using (&lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TransactionScope tx = &lt;/span&gt;&lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TransactionScope(transaction))
            {
                &lt;/span&gt;&lt;span style="color:green;"&gt;// Do my own transaction work
                tx.Complete();
            }
        }
    }

    &lt;/span&gt;&lt;span style="color:blue;"&gt;public void Complete(bool succeeded, &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ICollection items)
    {
    }

    &lt;/span&gt;&lt;span style="color:blue;"&gt;public bool MustCommit(&lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ICollection items)
    {
        &lt;/span&gt;&lt;span style="color:gray;"&gt;/// &lt;/span&gt;&lt;span style="color:green;"&gt;We want to commit!
        &lt;/span&gt;&lt;span style="color:blue;"&gt;return true;
    }

    #endregion
}

&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/span&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;p&gt;The MustCommit function is called to check if the Commit needs to be called. The Commit itself is called as part of the workflow persistence point. Now you can use something like a CodeActivity and add your workItem to the batch like this:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color:#2b91af;"&gt;WorkflowEnvironment.WorkBatch.Add(_pendingWork, myTransactionData);
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;When do we reach a persistence point?&lt;/h2&gt;
&lt;p&gt;This leaves us with the question of when these persistence point occur. The best way to think if these is when a workflow reaches a state that is final, no matter what happens. This includes the point where a workflow is done and when it is persisted to the persistence store. Using the SqlWorkflowPersistenceService with the PersistOnIdle option set to true will mean this will happen as soon as the event handler is done executing and the workflow is idle. However sometimes that just isn&amp;#39;t good enough and you need to do so sooner. Well the easiest way is to create a custom activity, I call it the PersistStateActivity, and decorate it with the PersistOnClose attribute. No need to add any code, all we are interested in is the attribute. &lt;/p&gt;&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;PersistOnClose()]
&lt;/span&gt;&lt;span style="color:blue;"&gt;public partial class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;PersistStateActivity : Activity
{
    &lt;/span&gt;&lt;span style="color:blue;"&gt;public PersistStateActivity()
    {
    }
}
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;p&gt;Now drop the activity at any point where you want your transactional data to be committed and the workflow runtime will take care of things for you &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Although these workarounds are possible they are all but intuitive and it took quite a bit of digging around and brainstorming with some people to get this to work. So be very careful when using the TransactionScopeActivity, or any form of transactions for that matter, and the WCF ReceiveActivity!&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;span style="color:blue;"&gt;&lt;/p&gt;&lt;/span&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1644506" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category></item><item><title>Visual Studio 2008 Service Pack 1 available</title><link>http://msmvps.com/blogs/theproblemsolver/archive/2008/08/11/visual-studio-2008-service-pack-1-available.aspx</link><pubDate>Mon, 11 Aug 2008 15:33:33 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1644248</guid><dc:creator>Maurice</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/theproblemsolver/rsscomments.aspx?PostID=1644248</wfw:commentRss><comments>http://msmvps.com/blogs/theproblemsolver/archive/2008/08/11/visual-studio-2008-service-pack-1-available.aspx#comments</comments><description>&lt;p&gt;It is available from the subscriptions download at &lt;a title="http://msdn.microsoft.com/en-us/subscriptions/default.aspx" href="http://msdn.microsoft.com/en-us/subscriptions/default.aspx"&gt;http://msdn.microsoft.com/en-us/subscriptions/default.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Get it while it is hot &lt;img src="http://msmvps.com/emoticons/emotion-1.gif" alt="Smile" /&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1644248" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/NetFx3/default.aspx">NetFx3</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/VB/default.aspx">VB</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/ClickOnce/default.aspx">ClickOnce</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/WPF/default.aspx">WPF</category><category domain="http://msmvps.com/blogs/theproblemsolver/archive/tags/SqlCe/default.aspx">SqlCe</category></item></channel></rss>