<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>Patrick Cauldwell's Blog</title>
    <link>http://www.cauldwell.net/patrick/blog/</link>
    <description>all about me, me, me (OK, and some other stuff)</description>
    <language>en-us</language>
    <copyright>Patrick Cauldwell</copyright>
    <lastBuildDate>Wed, 17 Jun 2009 17:19:27 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.6264.0</generator>
    <managingEditor>patrick@cauldwell.net</managingEditor>
    <webMaster>patrick@cauldwell.net</webMaster>
    <geo:lat>45.491024</geo:lat><geo:long>-122.957452</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/2.0/</creativeCommons:license><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/PatrickCauldwellsBlog" type="application/rss+xml" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=0aa76e13-9130-4044-b16c-ecf2fc46e58f</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,0aa76e13-9130-4044-b16c-ecf2fc46e58f.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,0aa76e13-9130-4044-b16c-ecf2fc46e58f.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=0aa76e13-9130-4044-b16c-ecf2fc46e58f</wfw:commentRss>
      
      <title>New classes in the lineup</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,0aa76e13-9130-4044-b16c-ecf2fc46e58f.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/i7gjZhkVlhc/NewClassesInTheLineup.aspx</link>
      <pubDate>Wed, 17 Jun 2009 17:19:27 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
We’ve added some new classes to the &lt;a href="http://www.sftsrc.com"&gt;SoftSource&lt;/a&gt; training &lt;a href="http://events.sftsrc.com"&gt;calendar&lt;/a&gt;,&#xD;
including a one-day &lt;a href="http://events.sftsrc.com/EventDescription.aspx?EventId=1076&amp;amp;AbstractId=687"&gt;Blend&#xD;
2&lt;/a&gt; class, and &lt;a href="http://events.sftsrc.com/EventDescription.aspx?EventId=1061&amp;amp;AbstractId=682"&gt;SQL&#xD;
2008 for Developers&lt;/a&gt;.  Other offerings coming up are “Agile in a Day”, WPF,&#xD;
WCF, ASP.NET 3.5, LINQ, Silverlight, and of course, C#.  Discounts available&#xD;
for multiple students from the same organization, and custom on-site training also.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=i7gjZhkVlhc:TCbKfvQ6Ek4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=i7gjZhkVlhc:TCbKfvQ6Ek4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=i7gjZhkVlhc:TCbKfvQ6Ek4:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=i7gjZhkVlhc:TCbKfvQ6Ek4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=i7gjZhkVlhc:TCbKfvQ6Ek4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=i7gjZhkVlhc:TCbKfvQ6Ek4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=i7gjZhkVlhc:TCbKfvQ6Ek4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=i7gjZhkVlhc:TCbKfvQ6Ek4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=i7gjZhkVlhc:TCbKfvQ6Ek4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,0aa76e13-9130-4044-b16c-ecf2fc46e58f.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/NewClassesInTheLineup.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=49140780-5f83-46da-8079-e6389a39a490</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,49140780-5f83-46da-8079-e6389a39a490.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,49140780-5f83-46da-8079-e6389a39a490.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=49140780-5f83-46da-8079-e6389a39a490</wfw:commentRss>
      
      <title>Default button semantics in Silverlight revisited</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,49140780-5f83-46da-8079-e6389a39a490.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/nuSlYxSE0VM/DefaultButtonSemanticsInSilverlightRevisited.aspx</link>
      <pubDate>Thu, 11 Jun 2009 19:03:22 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
A month or so ago I posted on a &lt;a href="http://www.cauldwell.net/patrick/blog/ALdquodefaultButtonrdquoInSilverlight.aspx"&gt;solution&lt;/a&gt; for&#xD;
simulating “default button” semantics in a Silverlight app, meaning that if you are&#xD;
entering text in a text box and you hit the enter key, the “default button” for the&#xD;
“page” should be pressed.  Very natural for form entry, etc.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
An issue came up (discovered by &lt;a href="http://johnpapa.net/"&gt;John Papa&lt;/a&gt;) with&#xD;
the solution in a Prism app, because my solution depends on being able to find the&#xD;
“default” button in the visual tree using the FindName method.  That means that&#xD;
you have to be high enough up the visual tree to find the button, since it only works&#xD;
“down” the tree.  In a Prism app, it’s not necessarily clear where “high enough”&#xD;
might be.  Plus, because the solution requires unique names, and Prism modules&#xD;
may have nothing to do with one another, they may have duplicate names, etc.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Here’s a revision to the solution that doesn’t require unique names, and doesn’t require&#xD;
any static references that might interfere with proper garbage collection… &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
First, a new object called DefaultButtonHub that keeps track of the relationship between&#xD;
text boxes and buttons.  It also exposes an Attached Property that takes a DefaultButtonHub&#xD;
reference so we can hook up text boxes and buttons to the “hub” in XAML.&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:4c5596a4-5334-43ea-a5fc-014754ff037a" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;public class DefaultButtonHub&#xD;
{&#xD;
   ButtonAutomationPeer peer = null;&#xD;
&#xD;
   private void Attach(DependencyObject source)&#xD;
   {&#xD;
       if (source is Button)&#xD;
       {&#xD;
           peer = new ButtonAutomationPeer(source as Button);&#xD;
       }&#xD;
       else if (source is TextBox)&#xD;
       {&#xD;
           TextBox tb = source as TextBox;&#xD;
           tb.KeyUp += OnKeyUp;&#xD;
       }&#xD;
       else if (source is PasswordBox)&#xD;
       {&#xD;
           PasswordBox pb = source as PasswordBox;&#xD;
           pb.KeyUp += OnKeyUp;&#xD;
       }&#xD;
   }&#xD;
&#xD;
   private void OnKeyUp(object sender, KeyEventArgs arg)&#xD;
   {&#xD;
       if(arg.Key == Key.Enter)&#xD;
           if (peer != null)&#xD;
               ((IInvokeProvider)peer).Invoke();&#xD;
   }&#xD;
&#xD;
   public static DefaultButtonHub GetDefaultHub(DependencyObject obj)&#xD;
   {&#xD;
       return (DefaultButtonHub)obj.GetValue(DefaultHubProperty);&#xD;
   }&#xD;
&#xD;
   public static void SetDefaultHub(DependencyObject obj, DefaultButtonHub value)&#xD;
   {&#xD;
       obj.SetValue(DefaultHubProperty, value);&#xD;
   }&#xD;
&#xD;
   // Using a DependencyProperty as the backing store for DefaultHub.  This enables animation, styling, binding, etc...&#xD;
   public static readonly DependencyProperty DefaultHubProperty =&#xD;
       DependencyProperty.RegisterAttached("DefaultHub", typeof(DefaultButtonHub), typeof(DefaultButtonHub), new PropertyMetadata(OnHubAttach));&#xD;
&#xD;
   private static void OnHubAttach(DependencyObject source, DependencyPropertyChangedEventArgs prop)&#xD;
   {&#xD;
       DefaultButtonHub hub = prop.NewValue as DefaultButtonHub;&#xD;
       hub.Attach(source);&#xD;
   }&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
Basically we’re expecting that both the text boxes and the button will register themselves&#xD;
with the “hub”.  If it’s a button that’s being registered, we wrap it in a ButtonAutomationPeer&#xD;
so we can “press” it later.  If it’s a text box, we hook up a KeyUp handler that&#xD;
will “press” the button if it’s there.  The requirement in the XAML is only marginally&#xD;
heavier than in my previous solution…we have to add a resource of type DefaultButtonHub,&#xD;
and point the button and text boxes at it using the {StaticResource} markup extension.&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:28f99d3a-6b2a-4ff1-8c7c-a058329caeb0" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: xml; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;&amp;lt;UserControl x:Class="DefaultButton.Page"&#xD;
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" &#xD;
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" &#xD;
    xmlns:my="clr-namespace:DefaultButton"&#xD;
    Width="400" Height="300"&amp;gt;&#xD;
    &amp;lt;UserControl.Resources&amp;gt;&#xD;
        &amp;lt;my:DefaultButtonHub x:Key="defaultHub"/&amp;gt;&#xD;
    &amp;lt;/UserControl.Resources&amp;gt;&#xD;
    &amp;lt;Grid x:Name="LayoutRoot" Background="White"&amp;gt;&#xD;
        &amp;lt;Grid.RowDefinitions&amp;gt;&#xD;
            &amp;lt;RowDefinition/&amp;gt;&#xD;
            &amp;lt;RowDefinition/&amp;gt;&#xD;
        &amp;lt;/Grid.RowDefinitions&amp;gt;&#xD;
        &amp;lt;TextBox x:Name="theText" Grid.Row="0"&#xD;
                 my:DefaultButtonHub.DefaultHub="{StaticResource defaultHub}"/&amp;gt;&#xD;
        &amp;lt;Button x:Name="theButton" Grid.Row="1" Content="Default"&#xD;
                Click="theButton_Click" my:DefaultButtonHub.DefaultHub="{StaticResource defaultHub}"/&amp;gt;&#xD;
    &amp;lt;/Grid&amp;gt;&#xD;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
Note that the new DefaultHub attached property is applied to both the text box and&#xD;
the button, each pointing the the single resource.  This way everything gets&#xD;
wired up property, there isn’t any problem with name resolution (aside from the usual&#xD;
resource name scoping) and everything will get cleaned up if the form needs to be&#xD;
GC’d.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=nuSlYxSE0VM:sVcydJmgFo8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=nuSlYxSE0VM:sVcydJmgFo8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=nuSlYxSE0VM:sVcydJmgFo8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=nuSlYxSE0VM:sVcydJmgFo8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=nuSlYxSE0VM:sVcydJmgFo8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=nuSlYxSE0VM:sVcydJmgFo8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=nuSlYxSE0VM:sVcydJmgFo8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=nuSlYxSE0VM:sVcydJmgFo8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=nuSlYxSE0VM:sVcydJmgFo8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,49140780-5f83-46da-8079-e6389a39a490.aspx</comments>
      <category>Silverlight;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/DefaultButtonSemanticsInSilverlightRevisited.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=c1dec284-c7c5-4742-b96e-22dcd1975d74</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,c1dec284-c7c5-4742-b96e-22dcd1975d74.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,c1dec284-c7c5-4742-b96e-22dcd1975d74.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=c1dec284-c7c5-4742-b96e-22dcd1975d74</wfw:commentRss>
      
      <title>RIA Services: the client side</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,c1dec284-c7c5-4742-b96e-22dcd1975d74.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/hwl9MogoDxw/RIAServicesTheClientSide.aspx</link>
      <pubDate>Fri, 05 Jun 2009 21:47:59 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Last &lt;a href="http://www.cauldwell.net/patrick/blog/NETRIAServicesFromScratch.aspx"&gt;time&lt;/a&gt;,&#xD;
I talked about how to build a Domain Service from scratch using whatever POCO you&#xD;
have lying around.  Now it’s time to talk about how that works on the client&#xD;
side…&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
One of the coolest things about RIA Services is that you don’t even have to “Add Service&#xD;
Reference…” to get a reference to the Domain Service.  If your Silverlight project&#xD;
is linked to the ASP.NET project correctly (see the RIA Services doc for how this&#xD;
works) the build steps will take care of generating the right code in your Silverlight&#xD;
project, and away you go.  There are several ways of accessing the service client-side,&#xD;
from dead-easy to a bit more involved.  We’ll start with dead easy.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The very easiest way to get things hooked up is to use the DomainDataSource control. &#xD;
It wraps your DomainDataContext (the client-side generated bit) with a data source&#xD;
you can bind directly against in XAML.&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:279e77b7-a94f-4eb3-b698-6c72bbf848a3" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: xml; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;&amp;lt;ria:DomainDataSource x:Name="PeopleDataSource" LoadMethodName="LoadPersons" AutoLoad="True"&amp;gt;&#xD;
  &amp;lt;ria:DomainDataSource.DomainContext&amp;gt;&#xD;
      &amp;lt;services:PeopleDomainContext/&amp;gt;&#xD;
  &amp;lt;/ria:DomainDataSource.DomainContext&amp;gt;&#xD;
&amp;lt;/ria:DomainDataSource&amp;gt;&#xD;
&amp;lt;dataControls:DataForm x:Name="dfPeople" CanUserAddItems="True" CanUserDeleteItems="true"&#xD;
                     ItemsSource="{Binding ElementName=PeopleDataSource, Path=Data}" &#xD;
                     ItemEditEnded="dfPeople_ItemEditEnded"&amp;gt;&#xD;
&amp;lt;/dataControls:DataForm&amp;gt;&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
The LoadMethodName attribute on the DomainDataSource tells it what method on the DomainContext&#xD;
to call in order to correctly populate the data context.  You can also pass parameters&#xD;
defined in XAML to the Load method if you only need to load a subset.  The DataForm&#xD;
control is bound to the Data property of the DomainDataSource, and away you go. &#xD;
You get this&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image.png"&gt;&#xD;
            &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://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_thumb.png" width="438" height="281"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Because the Insert/Update/Delete methods are implemented on the server-side DomainService,&#xD;
the DataForm automagically enables the edit, add and delete buttons at the top. &#xD;
If I edit or add a record, the save button shows up…&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_3.png"&gt;&#xD;
            &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://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_thumb_3.png" width="448" height="287"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Pressing either the Save or Cancel button fires the ItemEditEnded event, which we&#xD;
can grab to submit the changes back to the server&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:61ef5152-d951-4742-8042-f2981031a464" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;private void dfPeople_ItemEditEnded(object sender, DataFormItemEditEndedEventArgs e)&#xD;
{&#xD;
  if (e.EditAction == DataFormEditAction.Commit)&#xD;
      PeopleDataSource.SubmitChanges();&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
this is the very simplest case.  Calling SubmitChanges() here will send the edits/inserts&#xD;
up to the server right away.  For the sake of bandwidth, etc. I might want to&#xD;
implement my own “Save” button that batches up a whole set of change to the server&#xD;
rather than committing each edit individually.  You would still call PeopleDataSource.SubmitChanges,&#xD;
but not in response to the DataForm’s events.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
One of the great things about the way this works on the client side is that way the&#xD;
data validation attributes we set on the server-side POCO objects get propagated to&#xD;
the client.  For example, the server side LastName property looks like this (at&#xD;
least in the metadata class…)&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:a24de189-0bf0-4d3a-b486-9105fc6ade9e" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;[Required]&#xD;
[RegularExpression("[a-zA-z]*")]&#xD;
public string LastName;&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
The property that gets generated on the client side is&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:e47b1c66-9465-4a43-b623-55c64a8249ee" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;[DataMember()]&#xD;
[RegularExpression("[a-zA-z]*")]&#xD;
[Required()]&#xD;
public string LastName&#xD;
{&#xD;
  get&#xD;
  {&#xD;
      return this._lastName;&#xD;
  }&#xD;
  set&#xD;
  {&#xD;
      if ((this._lastName != value))&#xD;
      {&#xD;
          this.ValidateProperty("LastName", value);&#xD;
          this.RaiseDataMemberChanging("LastName");&#xD;
          this._lastName = value;&#xD;
          this.RaiseDataMemberChanged("LastName");&#xD;
      }&#xD;
  }&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
It maintains the [Required] and [RegularExpression] attributes.  Plus, in the&#xD;
property setter, it calls ValidateProperty, which uses reflection to examine those&#xD;
attributes and throw validation exceptions if necessary.  By default, then, I&#xD;
get UI on the Silverlight client for validation.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_4.png"&gt;&#xD;
            &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://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_thumb_4.png" width="449" height="288"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The DataForm provides the UI around both the field in question and the summary at&#xD;
the bottom.  In this case, I probably don’t want to tell the user what RegEx&#xD;
I’m validating against, so I need to add the ErrorMessage property to the validation&#xD;
attribute&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:16a66730-1d71-416f-9f72-c73fc9f617aa" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;[Required]&#xD;
[RegularExpression("[a-zA-z]*", ErrorMessage="Alpha characters only please!")]&#xD;
public string LastName;&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_5.png"&gt;&#xD;
            &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://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_thumb_5.png" width="455" height="292"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
When that error is corrected and I press the Save button, the Custom Validation routine&#xD;
is applied (see &lt;a href="http://www.cauldwell.net/patrick/blog/NETRIAServicesFromScratch.aspx"&gt;last&#xD;
post&lt;/a&gt; for details)&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_6.png"&gt;&#xD;
            &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://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_thumb_6.png" width="463" height="297"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt; &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
When all the errors are corrected, and the save happens (and gets committed back to&#xD;
the server) the DataForm is updated to show the correct ID value (from the server)&#xD;
as well as the calculated Age property.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_7.png"&gt;&#xD;
            &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://www.cauldwell.net/patrick/blog/images/RIAServicestheclientside_CFB3/image_thumb_7.png" width="466" height="299"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
For next to no work, I get a pretty good user experience for browsing, editing, inserting&#xD;
and deleting records.  If I wanted a bit more control, I could load the data&#xD;
into the DataContext myself, and then setup the databinding, rather than using the&#xD;
DomainDataSource in XAML&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:b239a716-d51d-4f0d-ab90-f9a97d4f0540" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;private PeopleDomainContext _context = new PeopleDomainContext();&#xD;
&#xD;
private void UserControl_Loaded(object sender, RoutedEventArgs e)&#xD;
{&#xD;
  if (_context.Persons.Count == 0)&#xD;
  {&#xD;
      _context.Loaded += (s, arg) =&amp;gt; loadPeople();&#xD;
      _context.LoadPersons();&#xD;
  }&#xD;
  else&#xD;
      loadPeople();&#xD;
}&#xD;
&#xD;
private void loadPeople()&#xD;
{&#xD;
  dfPeople.ItemsSource = _context.Persons;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
This would give me an opportunity to only load some people based on parameters, or&#xD;
whatever else I wanted to do to affect the loading of data before the data binding&#xD;
happens.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Next time… more cool things you can do with the DomainDataContext&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hwl9MogoDxw:C8F27QdBtss:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hwl9MogoDxw:C8F27QdBtss:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hwl9MogoDxw:C8F27QdBtss:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hwl9MogoDxw:C8F27QdBtss:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hwl9MogoDxw:C8F27QdBtss:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=hwl9MogoDxw:C8F27QdBtss:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hwl9MogoDxw:C8F27QdBtss:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=hwl9MogoDxw:C8F27QdBtss:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hwl9MogoDxw:C8F27QdBtss:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,c1dec284-c7c5-4742-b96e-22dcd1975d74.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/RIAServicesTheClientSide.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=7ac6946a-d494-433d-a0c2-5737ae2e9ee8</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,7ac6946a-d494-433d-a0c2-5737ae2e9ee8.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,7ac6946a-d494-433d-a0c2-5737ae2e9ee8.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=7ac6946a-d494-433d-a0c2-5737ae2e9ee8</wfw:commentRss>
      
      <title>.NET RIA Services from Scratch</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,7ac6946a-d494-433d-a0c2-5737ae2e9ee8.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/1l6mOwe5e98/NETRIAServicesFromScratch.aspx</link>
      <pubDate>Tue, 02 Jun 2009 22:53:18 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Most of the demos/samples I’ve looked at so far for &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=76bb3a07-3846-4564-b0c3-27972bcaabce&amp;amp;displaylang=en"&gt;RIA&#xD;
Services&lt;/a&gt; have started with a LINQ to SQL or ADO.NET Entity model and generated&#xD;
Domain Service classes from those.  I decided to start from something super simple&#xD;
(a POCO, if you will) and work up from there.  I started with a canonical &#xD;
“Person” class&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:c0d7eccf-2fd5-43f8-8f63-1952d006701e" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;public partial class Person : INotifyPropertyChanged&#xD;
{&#xD;
   #region INotifyPropertyChanged Members&#xD;
&#xD;
   public event PropertyChangedEventHandler PropertyChanged;&#xD;
&#xD;
   #endregion&#xD;
&#xD;
   protected virtual void Changed(string propertyName)&#xD;
   {&#xD;
       PropertyChangedEventHandler handler = PropertyChanged;&#xD;
       if (handler != null)&#xD;
       {&#xD;
           handler(this, new PropertyChangedEventArgs(propertyName));&#xD;
       }&#xD;
   }&#xD;
&#xD;
   private int _personId;&#xD;
   public int PersonId&#xD;
   {&#xD;
       get&#xD;
       {&#xD;
           return _personId;&#xD;
       }&#xD;
       set&#xD;
       {&#xD;
           if (_personId != value)&#xD;
           {&#xD;
               _personId = value;&#xD;
               Changed("PersonId");&#xD;
           }&#xD;
       }&#xD;
   }&#xD;
&#xD;
   private string _firstName;&#xD;
   public string FirstName&#xD;
   {&#xD;
...&#xD;
   }&#xD;
   private string _lastName;&#xD;
   public string LastName&#xD;
   {&#xD;
...&#xD;
   }&#xD;
   private System.DateTime _birthDate;&#xD;
   public System.DateTime BirthDate&#xD;
   {&#xD;
...&#xD;
   }&#xD;
}&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
Nothing to see here.  It’s just a simple POCO that supports INotifyPropertyChanged&#xD;
for databinding.  Note that it’s a partial class…  The simplest path would&#xD;
be to add RIA Services attributes directly to these properties for things like data&#xD;
validation, but I wanted to try out all the features, so I split out the metadata&#xD;
into another file&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:70bb36b8-81ba-48fc-8512-e36482d4ed2e" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;[MetadataTypeAttribute(typeof(RiaServices.Web.Person.PersonMetadata))]&#xD;
public partial class Person&#xD;
{&#xD;
&#xD;
   internal sealed class PersonMetadata&#xD;
   {&#xD;
       [Key]&#xD;
       [Required]&#xD;
       public int PersonId;&#xD;
&#xD;
       [Required]&#xD;
       [RegularExpression("[a-zA-z]*")]&#xD;
       public string FirstName;&#xD;
&#xD;
       [Required]&#xD;
       [RegularExpression("[a-zA-z]*")]&#xD;
       public string LastName;&#xD;
&#xD;
       [Required]&#xD;
       public DateTime BirthDate;&#xD;
   }&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
This is kind of an interesting trick, and allows me to separate out all the RIA specific&#xD;
metadata from the original class definition.  This makes total sense when you&#xD;
look at the way they handle LINQ to SQL, for example.  In that case you already&#xD;
have Entity classes defined by the LINQ to SQL wizard, so this extra metadata class&#xD;
allows you to associate the right attributes without touching the (generated) LINQ&#xD;
to SQL classes.  Clever.  Notice that the metadata class uses fields, not&#xD;
properties, and just matches the names for the sake of simplicity.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
In this case, the additional metadata defines data validation rules that get enforced&#xD;
both server and client side.  There are other attributes to enforcing string&#xD;
length and ranges.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
This all works because RIA Services generates “proxy” entity classes on the client&#xD;
side that are Silverlight compilable and also DataContracts (for serializing, which&#xD;
is cool…).  However, what happens if I have a calculated property that’s not&#xD;
just storage?  There’s a solution for that too, and it involves another piece&#xD;
of the partial class&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:09baa7be-63e0-47af-9d21-d18ecf0d1fcb" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;public partial class Person&#xD;
{&#xD;
   [Shared]&#xD;
   public int Age&#xD;
   {&#xD;
       get&#xD;
       {&#xD;
           this.Changed("Age");&#xD;
           return Convert.ToInt32(Math.Floor((DateTime.Now - _birthDate).Days / 365.25));&#xD;
       }&#xD;
   }&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
This bit goes in a file called Person.shared.cs, and it will be copied to the client&#xD;
project and compiled there as well as on the server.  The [Shared] attribute&#xD;
marks the bits that need to be thus propagated.  Again, clever.  Of course,&#xD;
any such shared code has to compile in Silverlight.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The other piece of code I want to share (using the same method) is a custom validator. &#xD;
In addition to the [Required] or [RegularExpression] attributes used above, you can&#xD;
register a custom validation routine that can examine the state of the entity as a&#xD;
whole.  The validation routine looks like this&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:1eef0b66-a7ec-418b-b4d3-9bb6ac09199d" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;[Shared]&#xD;
public class PersonValidator&#xD;
{&#xD;
   public static bool IsPersonValid(Person p, ValidationContext context, out ValidationResult result)&#xD;
   {&#xD;
       bool valid = true;&#xD;
&#xD;
       result = null;&#xD;
&#xD;
       if (p.Age &amp;gt; 130)&#xD;
           valid = false;&#xD;
&#xD;
       if (!valid)&#xD;
       {&#xD;
           result = new ValidationResult("Birthdate is invalid, people can't be that old", new []{"BirthDate"});&#xD;
       }&#xD;
&#xD;
       return valid;&#xD;
&#xD;
   }&#xD;
}&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
That’s in a file called PersonValidator.shared.cs, so that it will be available client&#xD;
and server-side.  It’s associated with the Person entity with an additional attribute&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:d75e9da4-a94d-4440-b0ac-e9beb3db8ed7" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true; highlight: 1 ;"&gt;[CustomValidation(typeof(PersonValidator), "IsPersonValid")]&#xD;
[MetadataTypeAttribute(typeof(RiaServices.Web.Person.PersonMetadata))]&#xD;
public partial class Person&#xD;
...&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
With the Person entity all ready, I can expose it to the client by creating a new&#xD;
DomainService class with methods for Get, Insert, Update, Delete, etc.&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:9a554f7f-e2a6-4f0e-b838-7c7ee3bd3b71" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;[EnableClientAccess()]&#xD;
public class PeopleDomainService : DomainService&#xD;
{&#xD;
   public IQueryable&amp;lt;Person&amp;gt; GetPersons()&#xD;
   {&#xD;
&#xD;
       return PeopleData.Persons.AsQueryable&amp;lt;Person&amp;gt;();&#xD;
   }&#xD;
&#xD;
   public IQueryable&amp;lt;Person&amp;gt; GetPerson(int personId)&#xD;
   {&#xD;
       return (from p in PeopleData.Persons&#xD;
               where p.PersonId == personId&#xD;
               select p).AsQueryable&amp;lt;Person&amp;gt;();&#xD;
   }&#xD;
&#xD;
   public void UpdatePerson(Person person)&#xD;
   {&#xD;
       Person oldP = (from p in PeopleData.Persons&#xD;
                      where p.PersonId == person.PersonId&#xD;
                      select p).FirstOrDefault();&#xD;
&#xD;
       if (oldP != null)&#xD;
       {&#xD;
           PeopleData.Persons.Remove(oldP);&#xD;
           PeopleData.Persons.Add(person);&#xD;
       }&#xD;
   }&#xD;
&#xD;
   public void InsertPerson(Person person)&#xD;
   {&#xD;
       if (person.PersonId == 0)&#xD;
       {&#xD;
           int max = PeopleData.Persons.Max(p =&amp;gt; p.PersonId);&#xD;
           person.PersonId = max + 1;&#xD;
       }&#xD;
&#xD;
       PeopleData.Persons.Add(person);&#xD;
   }&#xD;
&#xD;
   public void DeletePerson(Person person)&#xD;
   {&#xD;
       Person oldP = (from p in PeopleData.Persons&#xD;
                      where p.PersonId == person.PersonId&#xD;
                      select p).FirstOrDefault();&#xD;
&#xD;
       if (oldP != null)&#xD;
       {&#xD;
           PeopleData.Persons.Remove(oldP);&#xD;
       }&#xD;
   }&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
PersonData.People in this case is a List&amp;lt;Person&amp;gt; that’s populated with some&#xD;
sample data.  The [EnableClientAccess] attribute causes the build-time bits to&#xD;
generate a client side proxy for calling the service without the client project needing&#xD;
a service reference.  It really makes the Silverlight and the Web projects feel&#xD;
like parts of the same app rather than disconnected pieces.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The corresponding class that is generated on the client side is a DomainDataContext,&#xD;
which feels much like a LINQ to SQL DataContext only it’s lazy-loaded like the Astoria&#xD;
ones.  The GetPersons method on the server results in LoadPersons on the client,&#xD;
etc.  If I hadn’t implemented the Insert/Update/Delete methods on the server&#xD;
side, the DomainDataContext would simple behave like a read only data source. &#xD;
This model works really well with the DataForm class.  If I set the ItemsSource&#xD;
of the DataForm to the Persons “table” in the client side data context, it will properly&#xD;
enable/disable the add/delete buttons depending on the capabilities of the data context. &#xD;
Neat.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Coming in future posts… hooking up the PersonDataContext to the Silverlight 3 UI,&#xD;
and in ASP.NET&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=1l6mOwe5e98:h0VfHi1urng:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=1l6mOwe5e98:h0VfHi1urng:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=1l6mOwe5e98:h0VfHi1urng:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=1l6mOwe5e98:h0VfHi1urng:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=1l6mOwe5e98:h0VfHi1urng:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=1l6mOwe5e98:h0VfHi1urng:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=1l6mOwe5e98:h0VfHi1urng:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=1l6mOwe5e98:h0VfHi1urng:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=1l6mOwe5e98:h0VfHi1urng:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,7ac6946a-d494-433d-a0c2-5737ae2e9ee8.aspx</comments>
      <category>Silverlight;Work;RIA Services</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/NETRIAServicesFromScratch.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=064786e2-4c83-47e5-b897-b276f428c781</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,064786e2-4c83-47e5-b897-b276f428c781.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,064786e2-4c83-47e5-b897-b276f428c781.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=064786e2-4c83-47e5-b897-b276f428c781</wfw:commentRss>
      
      <title>Silverlight: Taking it on the road</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,064786e2-4c83-47e5-b897-b276f428c781.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/0AaXE3E8fdg/SilverlightTakingItOnTheRoad.aspx</link>
      <pubDate>Thu, 28 May 2009 23:38:16 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Shaun and I will be doing a one-day training, “&lt;a href="http://events.sftsrc.com/EventDescription.aspx?EventId=1062&amp;amp;AbstractId=681"&gt;Practical&#xD;
Silverlight 3&lt;/a&gt;”, in lovely San Francisco, CA on July 8th.  It’s a full day&#xD;
of Silverlighty goodness, starting with the basics and movin’ on up.  We like&#xD;
to think of it as a 300 level technical introduction to the subject, so you will come&#xD;
away with a better understanding of the fundamentals, and where to look next.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Topics include&#xD;
&lt;/p&gt;&#xD;
        &lt;ul&gt;&#xD;
          &lt;li&gt;&#xD;
An introduction to Silverlight 3&lt;/li&gt;&#xD;
          &lt;li&gt;&#xD;
All about controls (styling, templating, building your own)&lt;/li&gt;&#xD;
          &lt;li&gt;&#xD;
Integrating with the browser&lt;/li&gt;&#xD;
          &lt;li&gt;&#xD;
Communicating with the server via WCF, REST/POX, Sockets, you name it&lt;/li&gt;&#xD;
        &lt;/ul&gt;&#xD;
        &lt;p&gt;&#xD;
If you are or will be in NorCal, come check it out.  It’s a good introduction&#xD;
for a very reasonable price.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=0AaXE3E8fdg:9MF1Ssy5KC4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=0AaXE3E8fdg:9MF1Ssy5KC4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=0AaXE3E8fdg:9MF1Ssy5KC4:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=0AaXE3E8fdg:9MF1Ssy5KC4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=0AaXE3E8fdg:9MF1Ssy5KC4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=0AaXE3E8fdg:9MF1Ssy5KC4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=0AaXE3E8fdg:9MF1Ssy5KC4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=0AaXE3E8fdg:9MF1Ssy5KC4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=0AaXE3E8fdg:9MF1Ssy5KC4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,064786e2-4c83-47e5-b897-b276f428c781.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/SilverlightTakingItOnTheRoad.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=6594227c-d582-4e66-98ef-be3bc0a5244c</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,6594227c-d582-4e66-98ef-be3bc0a5244c.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,6594227c-d582-4e66-98ef-be3bc0a5244c.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=6594227c-d582-4e66-98ef-be3bc0a5244c</wfw:commentRss>
      
      <title>Debugging session at PDX Code Camp</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,6594227c-d582-4e66-98ef-be3bc0a5244c.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/S0msRNL6pzc/DebuggingSessionAtPDXCodeCamp.aspx</link>
      <pubDate>Tue, 26 May 2009 20:51:11 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.sftsrc.com"&gt;SoftSource&lt;/a&gt; developer &lt;a href="http://www.debuggingblog.com"&gt;Prashant&#xD;
Sinha&lt;/a&gt; is going to be presenting on &lt;a href="http://portlandcodecamp.org/session.aspx?sid=3dd15647-a032-4448-b259-70728b23ad14"&gt;“Production&#xD;
Debugging for Silverlight and ASP.NET”&lt;/a&gt; at Code Camp.  Prashant is a debugging&#xD;
wiz, and teaches our two-day .NET debugging course, so this should be a very useful&#xD;
session.  &#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=S0msRNL6pzc:wYmateN-K8E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=S0msRNL6pzc:wYmateN-K8E:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=S0msRNL6pzc:wYmateN-K8E:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=S0msRNL6pzc:wYmateN-K8E:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=S0msRNL6pzc:wYmateN-K8E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=S0msRNL6pzc:wYmateN-K8E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=S0msRNL6pzc:wYmateN-K8E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=S0msRNL6pzc:wYmateN-K8E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=S0msRNL6pzc:wYmateN-K8E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,6594227c-d582-4e66-98ef-be3bc0a5244c.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/DebuggingSessionAtPDXCodeCamp.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=4864bfbe-c60e-4829-b092-092ed46cde82</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,4864bfbe-c60e-4829-b092-092ed46cde82.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,4864bfbe-c60e-4829-b092-092ed46cde82.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=4864bfbe-c60e-4829-b092-092ed46cde82</wfw:commentRss>
      
      <title>Code Contracts</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,4864bfbe-c60e-4829-b092-092ed46cde82.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/Shz8JXaDF3Y/CodeContracts.aspx</link>
      <pubDate>Thu, 21 May 2009 21:50:38 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
In my &lt;a href="http://www.amazon.com/dp/0470259248?tag=patricvikkica-20&amp;amp;camp=14573&amp;amp;creative=327641&amp;amp;linkCode=as1&amp;amp;creativeASIN=0470259248&amp;amp;adid=0806NXZ2A5V5VPGTAE5D&amp;amp;"&gt;book&lt;/a&gt;,&#xD;
I talked a bit about programming by contract and how that makes everyone’s lives easier. &#xD;
Say I have a method that divides one integer by another&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:dfce7d2c-7373-4959-ae45-84cf2ae78204" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;public double Divide(int dividend, int divisor)&#xD;
{&#xD;
  return dividend / divisor;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
I’d like to be able to let callers know that they can’t pass a 0 for the divisor,&#xD;
because that will result in a DivideByZeroException, and nobody wants that. &#xD;
In the past I had a couple of choices on how to express that, mostly involving writing&#xD;
different kids of code, because C# doesn’t have a native expression of design by contract&#xD;
like Eiffel does.  One way is to use Debug.Assert&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:225e6e36-d5f2-417d-99bd-9aa339fc66a2" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;public double Divide(int dividend, int divisor)&#xD;
{&#xD;
  Debug.Assert(divisor != 0);&#xD;
&#xD;
  return dividend / divisor;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
That way any caller that passes a 0 will get an assertion dialog at runtime, which&#xD;
brings it pretty dramatically to everyone’s attention.  The assumption is that&#xD;
using the Debug.Assert will flush out all cases where people are incorrectly calling&#xD;
my method during development, so it’s OK that the assertion will get compiled out&#xD;
of my Release build.  However, that doesn’t make it impossible for a caller to&#xD;
pass a 0 at runtime and cause the exception.  Another option is explicitly checking&#xD;
parameters and throwing a different exception.&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:15cc7a83-ea90-4d71-a05e-4f361652cc58" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;public double Divide(int dividend, int divisor)&#xD;
{&#xD;
  if (divisor == 0)&#xD;
      throw new ArgumentException("divisor cannot be zero", "divisor");&#xD;
&#xD;
  return dividend / divisor;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/05/17/book-review-code-leader-by-patrick-cauldwell-a-digression-on-contracts.aspx"&gt;Patrick&lt;/a&gt; argues&#xD;
that this has now moved from defining contract to defining behavior, and I can agree&#xD;
with that, although I’d probably argue that it defines both contract and behavior&#xD;
since I’ve extended the functionality of the Debug.Assert to the release build, while&#xD;
also protecting my internal state from bad data.  But that’s really a separate&#xD;
discussion… :)&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Now thanks to the &lt;a href="http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx"&gt;Microsoft&#xD;
Code Contracts&lt;/a&gt; project, I have a third option.  The Code Contracts project&#xD;
is the evolution of the work done on Spec#, but in a language neutral way.  The&#xD;
Code Contracts tools are currently available from DevLabs for VS 2008, as well as&#xD;
shipping with VS 2010 B 1.  Just at the moment, there are more features in the&#xD;
DevLabs version that what made it into the 2010 beta.  With Code Contracts, I&#xD;
can rewrite my Divide method like this&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:de17865f-a475-4949-9f7c-68013b211d3e" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;public double Divide(int dividend, int divisor)&#xD;
{&#xD;
  Contract.Requires(divisor != 0);&#xD;
&#xD;
  return dividend / divisor;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
I like the syntax, as it calls out quite explicitly that I’m talking about contract,&#xD;
and making an explicit requirement.  The default behavior of this method at runtime&#xD;
is identical to Debug.Assert, it brings up an assertion dialog and brings everything&#xD;
to a screeching halt. However, it’s configurable at build time, so I can have it throw&#xD;
exceptions instead, or do whatever might be appropriate for my environment if the&#xD;
contract is violated.  I can even get the best of both worlds, with a generic&#xD;
version of Requires that specifies an exception&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:80a3b1b7-94eb-4dfe-bc89-1895ef757aa9" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;public double Divide(int dividend, int divisor)&#xD;
{&#xD;
  Contract.Requires&amp;lt;ArgumentException&amp;gt;(divisor != 0, "divisor");&#xD;
&#xD;
  return dividend / divisor;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
I could configure this to bring up the assertion dialog in Debug builds, but throw&#xD;
ArgumentNullException in Release builds.  Good stuff. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The example above demonstrates a required “precondition”.  With Code Contracts,&#xD;
I can also specify “postconditions”.  &#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:640f428b-ea7b-4994-8b7f-389e352dbb36" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;public void Transfer(Account from, Account to, decimal amount)&#xD;
{&#xD;
  Contract.Requires(from != null);&#xD;
  Contract.Requires(to != null);&#xD;
  Contract.Requires(amount &amp;gt; 0);&#xD;
  Contract.Ensures(from.Balance &amp;gt;= 0);&#xD;
&#xD;
  if (from.Balance &amp;lt; 0 || from.Balance &amp;lt; amount)&#xD;
      throw new InsufficientFundsException();&#xD;
&#xD;
  from.Balance -= amount;&#xD;
  to.Balance += amount;&#xD;
&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
This isn’t the greatest example, but basically the Transfer method is promising (with&#xD;
the Contract.Ensures method) that it won’t ever leave the Balance a negative number. &#xD;
Again, this is arguably behavior rather than contract, but you get the point.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
A really nifty feature is that I can write an interface definition and associate it&#xD;
with a set of contract calls, so that anyone who implements the interface will automatically&#xD;
“inherit” the contract validation.  The syntax is a bit weird, but you can see&#xD;
why it would need to be like this…&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:6aaea4a2-2c02-43ae-bf54-2609c119a94e" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;[ContractClass(typeof(ContractForCalucluator))]&#xD;
interface ICalculator&#xD;
{&#xD;
   int Add(int op1, int op2);&#xD;
   double Divide(int dividend, int divisor);&#xD;
}&#xD;
&#xD;
[ContractClassFor(typeof(ICalculator))]&#xD;
class ContractForCalucluator : ICalculator&#xD;
{&#xD;
   #region ICalculator Members&#xD;
&#xD;
   public int Add(int op1, int op2)&#xD;
   {&#xD;
       return default(int);&#xD;
   }&#xD;
&#xD;
   public double Divide(int dividend, int divisor)&#xD;
   {&#xD;
       Contract.Requires(divisor != 0);&#xD;
&#xD;
       return default(double);&#xD;
   }&#xD;
&#xD;
   #endregion&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
Now any class that implements ICalculator will have the contract validated for the&#xD;
Divide method.  Cool.  The last thing I want to point out is that the team&#xD;
included a handy sample of how to work with contract validation in your MSTest unit&#xD;
test code.  The Contract class exposes an event called ContractFailed, and I&#xD;
can subscribe to the event to decide what happens on a failure.  For a test assembly,&#xD;
I can do this&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:2d2c7b05-8398-467c-b1d1-ddeef3b7fb8b" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;[AssemblyInitialize]&#xD;
public static void AssemblyInitialize(TestContext tc)&#xD;
{&#xD;
  Contract.ContractFailed += (sender, e) =&amp;gt;&#xD;
  {&#xD;
      e.SetHandled();&#xD;
      e.SetUnwind();&#xD;
      Assert.Fail(e.FailureKind.ToString() + " : " + e.Message);&#xD;
  };&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
which will translate contract failures into test failures with very explicit error&#xD;
messages.  In the case of my Divide method if I run this test&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:5727431d-7999-4bd2-94ec-eec819769016" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;[TestMethod()]&#xD;
public void DivideContractViolation()&#xD;
{&#xD;
  Calculator target = new Calculator(); &#xD;
  int dividend = 12; &#xD;
  int divisor = 0; &#xD;
  double actual;&#xD;
  actual = target.Divide(dividend, divisor);&#xD;
  Assert.Fail("Should have failed");&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
I get a test failure of&#xD;
&lt;/p&gt;&#xD;
        &lt;blockquote&gt;&#xD;
          &lt;p&gt;&#xD;
Test method CalculatorTests.CalculatorTest.DivideContractViolation threw exception: &#xD;
System.Diagnostics.Contracts.ContractException: Precondition failed: divisor != 0&#xD;
divisor ---&amp;gt;  Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException:&#xD;
Assert.Fail failed. Precondition : Precondition failed: divisor != 0 divisor.&#xD;
&lt;/p&gt;&#xD;
        &lt;/blockquote&gt;&#xD;
        &lt;p&gt;&#xD;
Cool.  This is definitely something I’ll be looking at more in the future.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Shz8JXaDF3Y:Zn4HD2hl8X8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Shz8JXaDF3Y:Zn4HD2hl8X8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Shz8JXaDF3Y:Zn4HD2hl8X8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Shz8JXaDF3Y:Zn4HD2hl8X8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Shz8JXaDF3Y:Zn4HD2hl8X8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=Shz8JXaDF3Y:Zn4HD2hl8X8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Shz8JXaDF3Y:Zn4HD2hl8X8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=Shz8JXaDF3Y:Zn4HD2hl8X8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Shz8JXaDF3Y:Zn4HD2hl8X8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,4864bfbe-c60e-4829-b092-092ed46cde82.aspx</comments>
      <category>Code Construction;Testing;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/CodeContracts.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=ff37319d-3c19-42ad-abe7-0a7be61b317e</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,ff37319d-3c19-42ad-abe7-0a7be61b317e.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,ff37319d-3c19-42ad-abe7-0a7be61b317e.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=ff37319d-3c19-42ad-abe7-0a7be61b317e</wfw:commentRss>
      
      <title>PDX Code Camp is coming up&amp;hellip;</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,ff37319d-3c19-42ad-abe7-0a7be61b317e.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/jO61OXw5-oE/PDXCodeCampIsComingUphellip.aspx</link>
      <pubDate>Wed, 20 May 2009 20:45:43 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Not this weekend but next (5/30) is &lt;a href="http://portlandcodecamp.org"&gt;PDX Code&#xD;
Camp 2009&lt;/a&gt;.  A whole day of free software learning and general nerdy hanging&#xD;
out.  I’ll be talking about building business apps in Silverlight 3, and my &lt;a href="http://www.sftsrc.com"&gt;SoftSource&lt;/a&gt; compadre&#xD;
Tim Johnson is going to be talking about making your web application more accessible&#xD;
for people with disabilities.  There are also a host of other sessions including&#xD;
some big names like Ward Cunningham, so it’s an event not to be missed, and cheap&#xD;
at twice the price!&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=jO61OXw5-oE:rXZJW8uJ-10:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=jO61OXw5-oE:rXZJW8uJ-10:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=jO61OXw5-oE:rXZJW8uJ-10:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=jO61OXw5-oE:rXZJW8uJ-10:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=jO61OXw5-oE:rXZJW8uJ-10:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=jO61OXw5-oE:rXZJW8uJ-10:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=jO61OXw5-oE:rXZJW8uJ-10:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=jO61OXw5-oE:rXZJW8uJ-10:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=jO61OXw5-oE:rXZJW8uJ-10:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,ff37319d-3c19-42ad-abe7-0a7be61b317e.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/PDXCodeCampIsComingUphellip.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=fa25181c-c4a7-4d8b-947a-6d14bc07ee12</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,fa25181c-c4a7-4d8b-947a-6d14bc07ee12.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,fa25181c-c4a7-4d8b-947a-6d14bc07ee12.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=fa25181c-c4a7-4d8b-947a-6d14bc07ee12</wfw:commentRss>
      
      <title>LINQ: joining data in memory with data in SQL Server</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,fa25181c-c4a7-4d8b-947a-6d14bc07ee12.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/Latf-7CnWEc/LINQJoiningDataInMemoryWithDataInSQLServer.aspx</link>
      <pubDate>Wed, 20 May 2009 20:38:43 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
This came up in class yesterday, so I did a little digging.  Everyone may already&#xD;
know this, but it came as news to me. :)&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
If I’ve got a collection in memory, as well as a LINQ to SQL DataContext&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:863b2a97-d5bd-42de-87fa-dfdd99572795" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;List&amp;lt;FavoriteFood&amp;gt; foods = new List&amp;lt;FavoriteFood&amp;gt;(){&#xD;
	new FavoriteFood{CustomerID = "ALFKI", Favorite="Chips"},&#xD;
	new FavoriteFood{CustomerID = "ANATR", Favorite = "Fish"}};&#xD;
&#xD;
NorthwindDataContext context = new NorthwindDataContext();&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
and I want to do an INNER JOIN between the &lt;code&gt;foods&lt;/code&gt; list and the Customer&#xD;
table in Northwind, it would seem like this should do it&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:14223c48-ead8-4350-ac80-44224c210c41" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;var bad = (from cust in context.Customers&#xD;
         join f in foods on cust.CustomerID equals f.CustomerID&#xD;
         select new&#xD;
         {&#xD;
             cust.ContactName,&#xD;
             f.Favorite&#xD;
         }).ToList();&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
but sadly, no.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/LINQjoiningdatainmemorywithdatainSQLServ_BF72/image.png"&gt;&#xD;
            &lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://www.cauldwell.net/patrick/blog/images/LINQjoiningdatainmemorywithdatainSQLServ_BF72/image_thumb.png" border="0" width="419" height="258"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
if you stop to think about it, it totally makes sense that it wouldn’t work like that,&#xD;
since there’s no way to translate that into SQL in any rational way to send to SQL&#xD;
server.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
OK, so the next step would be to first get the customers in memory, then do the join&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:991fb98d-884f-407f-b472-8e82fc69b354" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;//this executes the whole query, thus retrieving the entire customer table&#xD;
var customers = (from c in context.Customers&#xD;
             select c).ToList();&#xD;
&#xD;
//an inner join between the customers from SQL and the in-memory list&#xD;
var inner = from cust in customers&#xD;
     join f in foods on cust.CustomerID equals f.CustomerID&#xD;
     select new&#xD;
     {&#xD;
         cust.ContactName,&#xD;
         f.Favorite&#xD;
     };&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
That works, but I’ve had to pull the entire Customer table into memory just to join&#xD;
two rows.  If I wanted to do a LEFT OUTER JOIN, I’d need that anyway, like so&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:70268c0d-75a2-4c83-bf0e-df7eb45d01c3" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;//here's the left outer join between the customer list from SQL &#xD;
//and the in-memory favorites&#xD;
var leftouter = from cust in customers&#xD;
             join f in foods on cust.CustomerID equals f.CustomerID into custFoods&#xD;
             from custFood in custFoods.DefaultIfEmpty()&#xD;
             select new&#xD;
             {&#xD;
                 cust.ContactName,&#xD;
                 Favorite = custFood == null ? null : custFood.Favorite&#xD;
             };&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
but I want an inner join without pulling down all the customers, so I need to only&#xD;
fetch those rows that will join from Customer&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:26850cad-8cbd-4d00-b6b4-37cf6151d284" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;//this is how you manage the IN clause&#xD;
var x = from c1 in context.Customers&#xD;
     where (from cf in foods&#xD;
           select cf.CustomerID).Contains(c1.CustomerID)&#xD;
     select c1;&#xD;
&#xD;
//Note that to join the result in x back to the foods collection you would have to &#xD;
//execute the query just like with customers above...&#xD;
var littleInnerJoin = from filteredCustomer in x.ToList()&#xD;
                   join f in foods on filteredCustomer.CustomerID equals f.CustomerID&#xD;
                   select new&#xD;
                       {&#xD;
                           filteredCustomer.ContactName,&#xD;
                           f.Favorite&#xD;
                       };&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
It’s two steps, but now I’ve just loaded the rows that will join into memory, and&#xD;
then done the join with LINQ to Objects.  It bears a little thinking about, but&#xD;
doesn’t seem like too much overhead, IMHO.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Latf-7CnWEc:uecXFuwkDTY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Latf-7CnWEc:uecXFuwkDTY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Latf-7CnWEc:uecXFuwkDTY:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Latf-7CnWEc:uecXFuwkDTY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Latf-7CnWEc:uecXFuwkDTY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=Latf-7CnWEc:uecXFuwkDTY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Latf-7CnWEc:uecXFuwkDTY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=Latf-7CnWEc:uecXFuwkDTY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=Latf-7CnWEc:uecXFuwkDTY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,fa25181c-c4a7-4d8b-947a-6d14bc07ee12.aspx</comments>
      <category>Work;LINQ</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/LINQJoiningDataInMemoryWithDataInSQLServer.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=94fb91a2-2c6c-422f-a48e-3f46aabcd8a2</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,94fb91a2-2c6c-422f-a48e-3f46aabcd8a2.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,94fb91a2-2c6c-422f-a48e-3f46aabcd8a2.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=94fb91a2-2c6c-422f-a48e-3f46aabcd8a2</wfw:commentRss>
      
      <title>A &amp;ldquo;default button&amp;rdquo; in Silverlight</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,94fb91a2-2c6c-422f-a48e-3f46aabcd8a2.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/8YQEx5PKfD8/ALdquodefaultButtonrdquoInSilverlight.aspx</link>
      <pubDate>Thu, 07 May 2009 20:27:54 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Let’s say I’ve got to the effort of creating a modal dialog or it’s equivalent in&#xD;
a Silverlight application.  What I would like to complete the picture is a “default”&#xD;
button, so that if I hit the Enter key while in a text box, the dialog will be “submitted”. &#xD;
There are probably several ways of achieving this end, but I wanted something that&#xD;
was simple, and encapsulated in an attached property so the consumer wouldn’t have&#xD;
to deal with much code.  I wrote the attached property so that I could use it&#xD;
on text boxes like this&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:53e11dba-4d3e-4301-8129-6611a235d4fe" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: xml; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;&amp;lt;TextBox x:Name="theText" VerticalAlignment="Center" Margin="10,0,10,0" &#xD;
	Grid.Row="0" my:DefaultButtonService.DefaultButton="theButton"/&amp;gt;&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
where “theButton” here is the default button I want to be pressed when the Enter key&#xD;
happens inside my text box.  The downside is that I have to apply this property&#xD;
to every text box on the page, but so be it, that seems like a relatively small price&#xD;
to pay.  So I got as far as finding the named button in the visual tree, but&#xD;
the the question was, how to “press” the button.  The Button class in Silverlight&#xD;
has a protected OnClick that would do the trick, if it wasn’t protected.  I could&#xD;
derive my own control from Button and expose the OnClick method, but ewww.  If&#xD;
I did that then every dialog that wanted this behavior would have to remember to use&#xD;
the derived Button class.  I tried reflecting over the Button and Invoking OnClick&#xD;
anyway, but turns out you get a security exception.  OK.  Then, thanks to&#xD;
a presentation &lt;a href="http://blogs.sftsrc.com/stuart/Default.aspx"&gt;Stuart&lt;/a&gt; gave&#xD;
us yesterday on Accessibility, I remembered the Automation framework in Silverlight. &#xD;
That turned out to be super easy, just create an instance of ButtonAutmationPeer from&#xD;
the Button, then Invoke it.  Cool.&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="margin: 0px; padding: 0px; display: inline; float: none;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:77a2e41a-7d86-4263-9298-977c8aeb4971" class="wlWriterEditableSmartContent"&gt;&#xD;
          &lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4; toolbar: true;"&gt;public static class DefaultButtonService&#xD;
{&#xD;
   public static readonly DependencyProperty DefaultButtonProperty =&#xD;
       DependencyProperty.RegisterAttached("DefaultButton", typeof(string), typeof(DefaultButtonService), new PropertyMetadata(OnDefaultButtonChanged));&#xD;
&#xD;
&#xD;
   public static string GetDefaultButton(DependencyObject d)&#xD;
   {&#xD;
       return (string)d.GetValue(DefaultButtonProperty);&#xD;
   }&#xD;
&#xD;
   /// &amp;lt;summary&amp;gt;&#xD;
   /// Sets the CommandParameter property.&#xD;
   /// &amp;lt;/summary&amp;gt;&#xD;
   public static void SetDefaultButton(DependencyObject d, string value)&#xD;
   {&#xD;
       d.SetValue(DefaultButtonProperty, value);&#xD;
   }&#xD;
&#xD;
   private static void OnDefaultButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&#xD;
   {&#xD;
       TextBox tb = d as TextBox;&#xD;
       if (tb != null)&#xD;
       {&#xD;
           tb.KeyUp += new KeyEventHandler(tb_KeyUp);&#xD;
       }&#xD;
   }&#xD;
&#xD;
   static void tb_KeyUp(object sender, KeyEventArgs e)&#xD;
   {&#xD;
       switch (e.Key)&#xD;
       {&#xD;
           case Key.Enter:&#xD;
               string name = (string)((DependencyObject)sender).GetValue(DefaultButtonProperty);&#xD;
               object root = App.Current.RootVisual;&#xD;
               object button = ((FrameworkElement)root).FindName(name);&#xD;
               if (button is Button)&#xD;
               {&#xD;
                   ButtonAutomationPeer peer = new ButtonAutomationPeer((Button)button);&#xD;
&#xD;
                   IInvokeProvider ip = (IInvokeProvider)peer;&#xD;
                   ip.Invoke();&#xD;
               }&#xD;
               break;&#xD;
       }&#xD;
   }&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
          &lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=8YQEx5PKfD8:Jj84y3IpwI0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=8YQEx5PKfD8:Jj84y3IpwI0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=8YQEx5PKfD8:Jj84y3IpwI0:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=8YQEx5PKfD8:Jj84y3IpwI0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=8YQEx5PKfD8:Jj84y3IpwI0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=8YQEx5PKfD8:Jj84y3IpwI0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=8YQEx5PKfD8:Jj84y3IpwI0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=8YQEx5PKfD8:Jj84y3IpwI0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=8YQEx5PKfD8:Jj84y3IpwI0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,94fb91a2-2c6c-422f-a48e-3f46aabcd8a2.aspx</comments>
      <category>Silverlight;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/ALdquodefaultButtonrdquoInSilverlight.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=32617f89-fb84-46d3-a0de-cf028ba56521</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,32617f89-fb84-46d3-a0de-cf028ba56521.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,32617f89-fb84-46d3-a0de-cf028ba56521.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=32617f89-fb84-46d3-a0de-cf028ba56521</wfw:commentRss>
      
      <title>New one-day classes at SoftSource</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,32617f89-fb84-46d3-a0de-cf028ba56521.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/hOdTXB_mmxM/NewOnedayClassesAtSoftSource.aspx</link>
      <pubDate>Tue, 07 Apr 2009 17:41:19 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
We just added a set of new one day classes starting in May, including “Agile in day”,&#xD;
Silverlight 3, and UI design patterns for WPF and Silverlight.  These are lecture-style&#xD;
classes that will give you an in depth look at each subject.  Like our previous&#xD;
Silverlight event, these are 300-400 level, technical sessions that will give you&#xD;
a leg up on each subject in a day.  Because they are presented lecture style,&#xD;
we can offer them for only $125 each, so feel free to collect the whole set. :-) &#xD;
Details and registration &lt;a href="http://events.sftsrc.com/"&gt;here&lt;/a&gt;.  We may&#xD;
be adding some additional topics soon, so check back often.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hOdTXB_mmxM:1vVCt53__00:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hOdTXB_mmxM:1vVCt53__00:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hOdTXB_mmxM:1vVCt53__00:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hOdTXB_mmxM:1vVCt53__00:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hOdTXB_mmxM:1vVCt53__00:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=hOdTXB_mmxM:1vVCt53__00:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hOdTXB_mmxM:1vVCt53__00:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=hOdTXB_mmxM:1vVCt53__00:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=hOdTXB_mmxM:1vVCt53__00:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,32617f89-fb84-46d3-a0de-cf028ba56521.aspx</comments>
      <category>Silverlight;training;Work;Agile</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/NewOnedayClassesAtSoftSource.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=7d4b00dc-ce68-44f3-a493-9d7073d3bcdd</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,7d4b00dc-ce68-44f3-a493-9d7073d3bcdd.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,7d4b00dc-ce68-44f3-a493-9d7073d3bcdd.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=7d4b00dc-ce68-44f3-a493-9d7073d3bcdd</wfw:commentRss>
      <slash:comments>1</slash:comments>
      
      <title>MIX 09 - Thursday</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,7d4b00dc-ce68-44f3-a493-9d7073d3bcdd.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/b4Fr7MpFNW0/MIX09Thursday.aspx</link>
      <pubDate>Thu, 19 Mar 2009 20:45:58 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;I'll probably have some more cogent things&#xD;
to say about it all in a few days, but my first set of takeaways as of mid-day Thursday: &#xD;
&lt;ul&gt;&lt;li&gt;&#xD;
Silverlight 3 solves many if not most of the downsides of working in Silverlight vs.&#xD;
WPF&lt;/li&gt;&lt;li&gt;&#xD;
Silverlight 3 + .NET RIA services totally removes any and all barriers to building&#xD;
business apps in Silverlight&lt;/li&gt;&lt;li&gt;&#xD;
.NET RIA services is the killer app we’ve been waiting for as far as building RIA&#xD;
apps is concerned.  it’s like Astoria, only better, and doesn’t require Entities&#xD;
(long live LINQ to SQL!).  &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Blend 3 will revolutionize the way designers and developers work together, and make&#xD;
the design process much faster&lt;/li&gt;&lt;li&gt;&#xD;
Free martinis are both a blessing and a curse&lt;/li&gt;&lt;li&gt;&#xD;
Having a DJ at your keynotes is a fantastic idea&lt;/li&gt;&lt;li&gt;&#xD;
Not only would downtown Hillsboro (where I live) fit inside the Venetian, but you&#xD;
probably wouldn’t actually notice it.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b4Fr7MpFNW0:K-bbJI6gTCA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b4Fr7MpFNW0:K-bbJI6gTCA:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b4Fr7MpFNW0:K-bbJI6gTCA:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b4Fr7MpFNW0:K-bbJI6gTCA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b4Fr7MpFNW0:K-bbJI6gTCA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=b4Fr7MpFNW0:K-bbJI6gTCA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b4Fr7MpFNW0:K-bbJI6gTCA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=b4Fr7MpFNW0:K-bbJI6gTCA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b4Fr7MpFNW0:K-bbJI6gTCA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,7d4b00dc-ce68-44f3-a493-9d7073d3bcdd.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/MIX09Thursday.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=1b71604e-3348-423e-a127-8808e61db198</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,1b71604e-3348-423e-a127-8808e61db198.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,1b71604e-3348-423e-a127-8808e61db198.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=1b71604e-3348-423e-a127-8808e61db198</wfw:commentRss>
      
      <title>MVVM and a modal dialog</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,1b71604e-3348-423e-a127-8808e61db198.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/3kNDalxNp2A/MVVMAndAModalDialog.aspx</link>
      <pubDate>Tue, 10 Mar 2009 23:36:01 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
I’m building a MVVM app in WPF, and needed to show a modal dialog, but I couldn’t&#xD;
figure out how to make it work and still maintain the separation between ViewModels&#xD;
and Views.  I have been mapping Views to ViewModels using DataTemplates, so that&#xD;
the relationship is declarative in XAML rather than in code someplace.  What&#xD;
I ended up with was a new Window called Dialog that takes a type in its constructor&#xD;
that corresponds to a ViewModelBase-derived type.  (See &lt;a href="http://joshsmithonwpf.wordpress.com/"&gt;Josh&#xD;
Smith’s&lt;/a&gt;&lt;a href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx"&gt;WPF Apps&#xD;
With The Model-View-ViewModel Design Pattern&lt;/a&gt; article for background on how the&#xD;
pieces fit together…)  &#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;public partial class Dialog : Window&#xD;
{&#xD;
    public Dialog(Type vmType)&#xD;
    {&#xD;
        InitializeComponent();&#xD;
&#xD;
        ViewModelBase vmb = Activator.CreateInstance(vmType) as ViewModelBase;&#xD;
        &#xD;
        item.Content = vmb;&#xD;
&#xD;
        this.Title = vmb.DisplayName;&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
In the XAML for Dialog, there’s just a Grid that contains a ContentPresenter called&#xD;
“item”.  The constructor sets item’s content to be the ViewModel, and the DataTemplate&#xD;
takes care of associating the View (a UserControl) with the ViewModel.  Note&#xD;
the use of &lt;code&gt;SizeToContent="WidthAndHeight"&lt;/code&gt; on the Dialog window, which&#xD;
causes the window to resize to how ever big the UserControl that represents the View&#xD;
might be.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: xml"&gt;&amp;lt;Window x:Class="SomeNamespace.Dialog"&#xD;
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&#xD;
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&#xD;
    Title="Dialog" SizeToContent="WidthAndHeight"&amp;gt;&#xD;
    &amp;lt;Grid&amp;gt;&#xD;
        &amp;lt;ContentPresenter x:Name="item"&amp;gt;&#xD;
            &#xD;
        &amp;lt;/ContentPresenter&amp;gt;&#xD;
    &amp;lt;/Grid&amp;gt;&#xD;
&amp;lt;/Window&amp;gt;&lt;/pre&gt;&#xD;
        &lt;pre class="brush: xml"&gt;&amp;lt;DataTemplate DataType="{x:Type vm:NewThingViewModel}"&amp;gt;&#xD;
    &amp;lt;vw:NewThing/&amp;gt;&#xD;
&amp;lt;/DataTemplate&amp;gt;&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
To create an instance of the new modal dialog, I just create a new instance of Dialog&#xD;
and pass the type of ViewModel it’s supposed to host…&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;new Dialog(typeof(NewThingViewModel)).ShowDialog();&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
There are still some details to work out as far as getting results from said dialog,&#xD;
but hey, progress…&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=3kNDalxNp2A:z94GfSfENkU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=3kNDalxNp2A:z94GfSfENkU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=3kNDalxNp2A:z94GfSfENkU:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=3kNDalxNp2A:z94GfSfENkU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=3kNDalxNp2A:z94GfSfENkU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=3kNDalxNp2A:z94GfSfENkU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=3kNDalxNp2A:z94GfSfENkU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=3kNDalxNp2A:z94GfSfENkU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=3kNDalxNp2A:z94GfSfENkU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,1b71604e-3348-423e-a127-8808e61db198.aspx</comments>
      <category>Work;Design Patterns;WPF</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/MVVMAndAModalDialog.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=b1aa6fe5-fa05-4171-b565-25a4062e31f6</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,b1aa6fe5-fa05-4171-b565-25a4062e31f6.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,b1aa6fe5-fa05-4171-b565-25a4062e31f6.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=b1aa6fe5-fa05-4171-b565-25a4062e31f6</wfw:commentRss>
      <slash:comments>3</slash:comments>
      
      <title>MVVM: binding to Commands in Silverlight</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,b1aa6fe5-fa05-4171-b565-25a4062e31f6.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/b2wl5XB4SBc/MVVMBindingToCommandsInSilverlight.aspx</link>
      <pubDate>Thu, 05 Mar 2009 00:06:59 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
So yesterday I was reading &lt;a href="http://joshsmithonwpf.wordpress.com/"&gt;Josh Smith’s&lt;/a&gt;&lt;a href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx"&gt;WPF&#xD;
Apps With The Model-View-ViewModel Design Pattern&lt;/a&gt; article in last month’s MSDN&#xD;
magazine, and I really liked the sample app that he built.  It totally cleared&#xD;
up for me some rough edges (in my understanding) of MVVM.  Most specifically,&#xD;
I had been conflicted about where to put things like button click handlers. &#xD;
Do you put a Click event handler in your codebehind, which just defers to the View&#xD;
Model?  Do you create a generic CommandBinding handler to wire up commands to&#xD;
your View Model’s methods?  (I’ve seen both in various examples…)  The former&#xD;
seems like cheating a bit on MVVM (no code behind would be ideal, it seems to me)&#xD;
and the latter overly complicated.  Josh’s solution is to bind the Command property&#xD;
of the UIElement (button, menu item, whatever) to a property of type ICommand on the&#xD;
View Model.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
That totally made sense to me.  No more code behind (like at all, basically)&#xD;
and I don’t have to build additional framework to make it happen, with the exception&#xD;
of coming up with an ICommand implementation.  Josh solved that with a class&#xD;
he calls RelayCommand, which just wraps an ICommand implementation around a delegate&#xD;
(or lambda) of type Action&amp;lt;object&amp;gt;, with an optional Predicate&amp;lt;object&amp;gt;&#xD;
to handle the CanExecute method of ICommand.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Groovy, now my XAML knows absolutely nothing about the View Model, and it’s only links&#xD;
to said View Model are through data binding. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Then I got to wondering if something as easy could work in Silverlight…  The&#xD;
answer turned out to be almost, but not quite.  Since Silverlight controls don’t&#xD;
expose a Command property, you have to hook them up yourself, but otherwise it works&#xD;
just the same way.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
So if I’ve got a page with a single button on it&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/MVVMbindingtoCommandsinSilverlight_E1BC/CropperCapture10.png"&gt;&#xD;
            &lt;img style="border-width: 0px; display: inline;" title="CropperCapture[10]" alt="CropperCapture[10]" src="http://www.cauldwell.net/patrick/blog/images/MVVMbindingtoCommandsinSilverlight_E1BC/CropperCapture10_thumb.png" border="0" width="244" height="186"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;pre class="brush: xml"&gt;&amp;lt;UserControl x:Class="SilverlightCommands.Page"&#xD;
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" &#xD;
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" &#xD;
    xmlns:my="clr-namespace:SilverlightCommands"&#xD;
    Width="400" Height="300"&amp;gt;&#xD;
    &amp;lt;Grid x:Name="LayoutRoot" Background="White"&amp;gt;&#xD;
        &amp;lt;Button Content="Say Hello..." VerticalAlignment="Center" &#xD;
                HorizontalAlignment="Center" &#xD;
                my:ButtonService.Command="{Binding Path=SayHello}"/&amp;gt;&#xD;
    &amp;lt;/Grid&amp;gt;&#xD;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
I can add an attached property whose value is bound to the ICommand property on the&#xD;
View Model.  The attached property grabs the ICommand and hooks up the button’s&#xD;
click handler to the ICommand’s Execute method.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;#region Command&#xD;
&#xD;
/// &amp;lt;summary&amp;gt;&#xD;
/// Command Attached Dependency Property&#xD;
/// &amp;lt;/summary&amp;gt;&#xD;
public static readonly DependencyProperty CommandProperty =&#xD;
    DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(ButtonService),&#xD;
        new PropertyMetadata(OnCommandChanged));&#xD;
&#xD;
/// &amp;lt;summary&amp;gt;&#xD;
/// Gets the Command property.&#xD;
/// &amp;lt;/summary&amp;gt;&#xD;
public static ICommand GetCommand(DependencyObject d)&#xD;
{&#xD;
    return (ICommand)d.GetValue(CommandProperty);&#xD;
}&#xD;
&#xD;
/// &amp;lt;summary&amp;gt;&#xD;
/// Sets the Command property.&#xD;
/// &amp;lt;/summary&amp;gt;&#xD;
public static void SetCommand(DependencyObject d, ICommand value)&#xD;
{&#xD;
    d.SetValue(CommandProperty, value);&#xD;
}&#xD;
&#xD;
/// &amp;lt;summary&amp;gt;&#xD;
/// Handles changes to the Command property.&#xD;
/// &amp;lt;/summary&amp;gt;&#xD;
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&#xD;
{&#xD;
    if (d is Button)&#xD;
    {&#xD;
        Button b = d as Button;&#xD;
        ICommand c = e.NewValue as ICommand;&#xD;
        b.Click += delegate(object sender, RoutedEventArgs arg) { c.Execute(null); };&#xD;
    }&#xD;
}&#xD;
&#xD;
#endregion&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
In the View Model, then, is the actual handler for the command&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;public class PageViewModel&#xD;
{&#xD;
    public ICommand SayHello&#xD;
    {&#xD;
        get&#xD;
        {&#xD;
            return new RelayCommand(param =&amp;gt; MessageBox.Show("HelloWorld"));&#xD;
        }&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
Note that I’m using Josh’s RelayCommand helper to wrap the simple lambda.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
That feels like not too terribly much infrastructure, although I might have to create&#xD;
separate attached properties to handle different control types (e.g. those that don’t&#xD;
have a Click event).  It would be pretty straightforward to support command parameters&#xD;
in the same way, by creating a CommandParameter attached property and picking up its&#xD;
value in the OnCommandChanged handler…&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&#xD;
{&#xD;
    if (d is Button)&#xD;
    {&#xD;
        string parameter = d.GetValue(CommandParameterProperty) as string;&#xD;
        Button b = d as Button;&#xD;
        ICommand c = e.NewValue as ICommand;&#xD;
        b.Click += delegate(object sender, RoutedEventArgs arg) { c.Execute(parameter); };&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
The only thing that doesn’t really handle well is the CanExecute method, which in&#xD;
WPF would automatically enable/disable the button based on the result of the ICommand’s&#xD;
CanExecute method.  I tried a couple ways of wiring it up during the OnCommandChanged&#xD;
handler, but couldn’t come up with anything that didn’t look to have nasty side-effect&#xD;
(garbage collection, etc.) or be just ugly.  I’d probably just bind the IsEnable&#xD;
property of the button to a separate boolean on the View Model and deal with it there.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Update:&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Code is &lt;a href="http://www.cauldwell.net/patrick/work/SilverlightCommands.zip"&gt;here&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b2wl5XB4SBc:KS8p4KYuhmc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b2wl5XB4SBc:KS8p4KYuhmc:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b2wl5XB4SBc:KS8p4KYuhmc:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b2wl5XB4SBc:KS8p4KYuhmc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b2wl5XB4SBc:KS8p4KYuhmc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=b2wl5XB4SBc:KS8p4KYuhmc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b2wl5XB4SBc:KS8p4KYuhmc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=b2wl5XB4SBc:KS8p4KYuhmc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=b2wl5XB4SBc:KS8p4KYuhmc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,b1aa6fe5-fa05-4171-b565-25a4062e31f6.aspx</comments>
      <category>Design Patterns;Silverlight;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/MVVMBindingToCommandsInSilverlight.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=2c0a4bfd-69ca-4e3a-8e6f-96abb31f954b</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,2c0a4bfd-69ca-4e3a-8e6f-96abb31f954b.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,2c0a4bfd-69ca-4e3a-8e6f-96abb31f954b.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2c0a4bfd-69ca-4e3a-8e6f-96abb31f954b</wfw:commentRss>
      
      <title>Replacing JavaScript with Silverlight</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,2c0a4bfd-69ca-4e3a-8e6f-96abb31f954b.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/dcQwK8VIbZo/ReplacingJavaScriptWithSilverlight.aspx</link>
      <pubDate>Mon, 02 Mar 2009 23:08:15 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://blogs.sftsrc.com/shaun"&gt;Shaun&lt;/a&gt; posted a nice concise &lt;a href="http://blogs.sftsrc.com/shaun/archive/2009/02/23.aspx"&gt;example&lt;/a&gt; of&#xD;
replacing JavaScript code with similar compiled code in Silverlight.  If you&#xD;
have any complex business logic currently written in JavaScript, this would be a great&#xD;
way of turning that into compiled, type-safe C#.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=dcQwK8VIbZo:-4J9jhFIExk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=dcQwK8VIbZo:-4J9jhFIExk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=dcQwK8VIbZo:-4J9jhFIExk:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=dcQwK8VIbZo:-4J9jhFIExk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=dcQwK8VIbZo:-4J9jhFIExk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=dcQwK8VIbZo:-4J9jhFIExk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=dcQwK8VIbZo:-4J9jhFIExk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=dcQwK8VIbZo:-4J9jhFIExk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=dcQwK8VIbZo:-4J9jhFIExk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,2c0a4bfd-69ca-4e3a-8e6f-96abb31f954b.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/ReplacingJavaScriptWithSilverlight.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=42d6dbf8-b4d4-4b0b-9f64-db577b4db03a</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,42d6dbf8-b4d4-4b0b-9f64-db577b4db03a.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,42d6dbf8-b4d4-4b0b-9f64-db577b4db03a.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=42d6dbf8-b4d4-4b0b-9f64-db577b4db03a</wfw:commentRss>
      
      <title>MVVM and testing Silverlight</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,42d6dbf8-b4d4-4b0b-9f64-db577b4db03a.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/XXhjVQrsfxc/MVVMAndTestingSilverlight.aspx</link>
      <pubDate>Mon, 02 Mar 2009 22:42:25 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
After reading Justin Angel’s very good &lt;a href="http://silverlight.net/blogs/justinangel/archive/2009/02/25/silverlight-unit-testing-rhinomocks-unity-and-resharper.aspx"&gt;summary&lt;/a&gt; of&#xD;
unit testing Silverlight using the Silverlight UnitTest framework, RhinoMocks, &lt;a href="http://msdn.microsoft.com/en-us/library/dd362339.aspx"&gt;Unity&lt;/a&gt; etc.&#xD;
I decided to give it a go and find out how easy it was for a “real” application. &#xD;
I converted the course evaluation &lt;a href="http://www.cauldwell.net/patrick/blog/ADatadrivenSurveyInSilverlight.aspx"&gt;app&lt;/a&gt; I’ve&#xD;
been working on since December to MVVM using Unity, and then set about trying to test&#xD;
it with the testing tools.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I must say I do rather like the MVVM pattern, so that part went pretty well, as did&#xD;
the use of Unity, although there was some learning to do there.  It’s not quite&#xD;
as obvious as it maybe should be, but it didn’t take too long.  The biggest issue&#xD;
I had with both Unity and the test tools come in relation to the WCF proxy that I’m&#xD;
using to talk back to the server from Silverlight.  I think it would be a bit&#xD;
easier using the asynchronous interface that is generated as part of the proxy (the&#xD;
one that has all the BeginXXX, EndXXX methods on it) but I’m using the interface that&#xD;
consists of completion events and XXXAsync methods.  That object (in my case&#xD;
it’s called “EvalServiceClient”) doesn’t like being created by Unity, presumably somewhere&#xD;
down in the WCF infrastructure, so I had to create it myself and register the instance&#xD;
with Unity.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;Current = new UnityContainer();&#xD;
Current.RegisterInstance(typeof(EvalServiceClient), new EvalServiceClient());&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
That isn’t too terrible, but it did take a while to figure out.  One of the things&#xD;
that makes that harder is that the errors that come back just say “Unity couldn’t&#xD;
create your thing” and it takes a bit of digging to find out where and why it actually&#xD;
failed.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The blogosphere suggests (and I agree) that implementing MVVM in Silverlight isn’t&#xD;
quite as straightforward as it might be in WPF, largely due to the lack of commands. &#xD;
There are a couple of declarative solutions for mapping UI elements to methods in&#xD;
a View Model, but most relied on quite a bit of infrastructure.  I decided it&#xD;
was OK (enough) to put just enough code in my code-behind to wire up event handlers&#xD;
to methods on the View Model.  Icky?  No too bad.  Commands would obviously&#xD;
be better, but there it is.  &#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;private void submitEval_Click(object sender, RoutedEventArgs e)&#xD;
{&#xD;
    ViewModel.SubmitEval();&#xD;
}&#xD;
&#xD;
private void lstCourse_SelectionChanged(object sender, SelectionChangedEventArgs e)&#xD;
{&#xD;
    CourseInfo ci = lstCourse.SelectedItem as CourseInfo;&#xD;
    ViewModel.CourseSelected(ci);&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
I found that the reliance on data binding makes it much easier to separate presentation&#xD;
from business logic.  The View Model can represent any UI specific logic like&#xD;
which buttons should be enabled when (which the underlying business/domain model doesn’t&#xD;
care about) and allow a designer to work strictly with XAML.  Because INotifyPropertyChanged&#xD;
really works, you don’t have to worry about pushing data into the interface, just&#xD;
on which properties have to be marked as changed.  For a computed property like&#xD;
“should the submit button be shown” it may take a few extra notification calls to&#xD;
make sure the UI gets updated properly, but that seems reasonable.  &#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;public bool CanSubmit&#xD;
{&#xD;
    get&#xD;
    {&#xD;
        _canSubmit = (_registrationId.HasValue &amp;amp;&amp;amp; _questionCategories != null);&#xD;
        return _canSubmit;&#xD;
    }&#xD;
    set&#xD;
    {&#xD;
        if (_canSubmit != value)&#xD;
        {&#xD;
            _canSubmit = value;&#xD;
            Changed("CanSubmit");&#xD;
        }&#xD;
    }&#xD;
}&#xD;
&#xD;
public int? RegistrationId&#xD;
{&#xD;
    get&#xD;
    {&#xD;
        return _registrationId;&#xD;
    }&#xD;
    set&#xD;
    {&#xD;
        if (_registrationId != value)&#xD;
        {&#xD;
            _registrationId = value;&#xD;
            Changed("RegistrationId");&#xD;
            Changed("CanSubmit");&#xD;
        }&#xD;
    }&#xD;
}&#xD;
&#xD;
public System.Collections.ObjectModel.ObservableCollection&amp;lt;Evaluation.EvaluationServer.QuestionCategory&amp;gt; QuestionCategories&#xD;
{&#xD;
    get&#xD;
    {&#xD;
        return _questionCategories;&#xD;
    }&#xD;
    set&#xD;
    {&#xD;
        if (_questionCategories != value)&#xD;
        {&#xD;
            _questionCategories = value;&#xD;
            Changed("QuestionCategories");&#xD;
            Changed("CanSubmit");&#xD;
        }&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
In the example above, the value of “CanSubit” relies on the state of RegistrationID&#xD;
and QuestionCategories, so the property setters for those properties also “invalidate”&#xD;
CanSubmit so the UI will update properly.  In the XAML, the IsEnabled property&#xD;
of the Submit button is bound to the CanSubmit property of the View Model.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The next challenge was getting the test code to work.  Because I didn’t want&#xD;
the test code to call the real web service, I had to mock the calls to the EvalServiceClient. &#xD;
For whatever reason, I didn’t have any luck with mocking the object itself. &#xD;
I think this had to do with the asynchronous nature of the calls.  The code registers&#xD;
an event handler for each completion event, then calls XXXAsync to call the web service. &#xD;
When it returns, it fires the completion handler.  To make that work with RhinoMocks,&#xD;
you have to record the event hookup, then capture an IEventRasier interface that will&#xD;
let you raise the desired event.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;using (mocks.Record())&#xD;
{&#xD;
    client.GetStudentNameCompleted += null;&#xD;
    raiser = LastCall.IgnoreArguments().GetEventRaiser();&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
That call to GetEventRaiser fails if I mock the EvalServiceClient object itself, so&#xD;
I had to create an interface that I could mock instead.  Luckily, the generated&#xD;
proxy is a partial class, so it’s easy to add a new interface.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;public interface IEvalServiceClient&#xD;
{&#xD;
    event System.EventHandler&amp;lt;GetStudentNameCompletedEventArgs&amp;gt; GetStudentNameCompleted;&#xD;
&#xD;
    void GetStudentNameAsync();&#xD;
}&#xD;
&#xD;
public partial class EvalServiceClient : IEvalServiceClient&#xD;
{&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
Now the RhinoMocks code mock the IEvalServiceClient interface, and the GetEventRaiser&#xD;
call works just fine.  Because the WCF client actually gets created by Unity,&#xD;
we have to register the new mock instance with the UnityContainer.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp;highlight:[10,19]"&gt;MockRepository mocks = new MockRepository();&#xD;
IEvalServiceClient client = mocks.StrictMock&amp;lt;IEvalServiceClient&amp;gt;();&#xD;
&#xD;
IoC.Current.RegisterInstance&amp;lt;IEvalServiceClient&amp;gt;(client);&#xD;
IEventRaiser raiser;&#xD;
&#xD;
using (mocks.Record())&#xD;
{&#xD;
    client.GetStudentNameCompleted += null;&#xD;
    raiser = LastCall.IgnoreArguments().GetEventRaiser();&#xD;
&#xD;
    client.GetStudentNameAsync();&#xD;
&#xD;
}&#xD;
&#xD;
using (mocks.Playback())&#xD;
{&#xD;
    Page page = new Page();&#xD;
    raiser.Raise(client, new GetStudentNameCompletedEventArgs(new object[]{"Jones, Fred"}, null, false, null));&#xD;
    WaitFor(page, "Loaded");&#xD;
    TestPanel.Children.Add(page);&#xD;
&#xD;
    EnqueueCallback(() =&amp;gt; Assert.IsTrue(page.lblStudent.Text == "Jones, Fred"));&#xD;
&#xD;
    EnqueueTestComplete();&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
During playback, we can use the IEventRaiser to fire the completion event, then check&#xD;
the UI to make sure the property got set correctly.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I’m pretty convinced that MVVM is a good idea, but this method of testing seems awfully&#xD;
cumbersome to me, plus pretty invasive.  I had to make quite a few changes to&#xD;
my app to make the testing work, including creating the interface for the EvalServiceClient,&#xD;
and marking any controls I needed to write tests against with x:FieldModifier=”public”&#xD;
in my XAML.  It’s good to know how to make this work, but I’m not sure I’d use&#xD;
this method to test everything in my Silverlight app.  Probably only the highest&#xD;
risk areas, or places that would be tedious for a tester to hit.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=XXhjVQrsfxc:2bMONliNXmM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=XXhjVQrsfxc:2bMONliNXmM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=XXhjVQrsfxc:2bMONliNXmM:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=XXhjVQrsfxc:2bMONliNXmM:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=XXhjVQrsfxc:2bMONliNXmM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=XXhjVQrsfxc:2bMONliNXmM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=XXhjVQrsfxc:2bMONliNXmM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?i=XXhjVQrsfxc:2bMONliNXmM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?a=XXhjVQrsfxc:2bMONliNXmM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PatrickCauldwellsBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,42d6dbf8-b4d4-4b0b-9f64-db577b4db03a.aspx</comments>
      <category>Silverlight;Testing;Web Services;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/MVVMAndTestingSilverlight.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=265d8ab9-edda-4560-b00b-702639e389a8</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,265d8ab9-edda-4560-b00b-702639e389a8.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,265d8ab9-edda-4560-b00b-702639e389a8.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=265d8ab9-edda-4560-b00b-702639e389a8</wfw:commentRss>
      
      <title>Validation UI revisitied: attached properties</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,265d8ab9-edda-4560-b00b-702639e389a8.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/xA4pe6JdhUY/ValidationUIRevisitiedAttachedProperties.aspx</link>
      <pubDate>Fri, 20 Feb 2009 23:32:07 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
On Wednesday I &lt;a href="http://www.cauldwell.net/patrick/blog/DatabindingValidationInSilverlightAUIPerspective.aspx"&gt;posted&lt;/a&gt; about&#xD;
coming up with a way of decorating any UIElement with a red border in response to&#xD;
a validation error.  The only drawback (that I could see just then) was that&#xD;
I had to add borders to all the elements that I might want to exhibit this behavior. &#xD;
Today &lt;a href="http://blogs.sftsrc.com/shaun/Default.aspx"&gt;Shaun&lt;/a&gt; suggested that&#xD;
I try it as an attached property instead, which might save that hassle.  Indeed&#xD;
it does.  Because of the way attached properties work in Silverlight, it’s possible&#xD;
to use them to attach behavior as well as data be hooking the value changed event. &#xD;
Here’s the same (basically) logic as an attached property&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;public class ValidationService&#xD;
{&#xD;
    public static readonly DependencyProperty ValidationBehaviorProperty =&#xD;
        DependencyProperty.RegisterAttached("ValidationBehavior", typeof(bool), typeof(ValidationService),&#xD;
                                    new PropertyMetadata(OnValidationBehaviorChanged));&#xD;
&#xD;
    public static bool GetValidationBehavior(DependencyObject d)&#xD;
    {&#xD;
        return (bool)d.GetValue(ValidationBehaviorProperty);&#xD;
    }&#xD;
&#xD;
    public static void SetValidationBehavior(DependencyObject d, bool value)&#xD;
    {&#xD;
        d.SetValue(ValidationBehaviorProperty, value);&#xD;
    }&#xD;
&#xD;
    private static void OnValidationBehaviorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&#xD;
    {&#xD;
        if (d is FrameworkElement)&#xD;
        {&#xD;
            FrameworkElement fe = d as FrameworkElement;&#xD;
&#xD;
            if ((bool)e.OldValue)&#xD;
            {&#xD;
&#xD;
            }&#xD;
            if ((bool)e.NewValue)&#xD;
            {&#xD;
                fe.BindingValidationError += new EventHandler&amp;lt;ValidationErrorEventArgs&amp;gt;(fe_BindingValidationError);&#xD;
            }&#xD;
        }&#xD;
    }&#xD;
&#xD;
    static void fe_BindingValidationError(object sender, ValidationErrorEventArgs e)&#xD;
    {&#xD;
        FrameworkElement fe = e.OriginalSource as FrameworkElement;&#xD;
        DependencyObject parent = fe.Parent;&#xD;
        Border b = null;&#xD;
&#xD;
        if (parent is Grid)&#xD;
        {&#xD;
            b = new Border() { BorderBrush = new SolidColorBrush(Colors.Red), BorderThickness = new Thickness(0) };&#xD;
&#xD;
            Grid g = parent as Grid;&#xD;
            g.Children.Add(b);&#xD;
            int column = (int)fe.GetValue(Grid.ColumnProperty);&#xD;
            b.SetValue(Grid.ColumnProperty, column);&#xD;
            int row = (int)fe.GetValue(Grid.RowProperty);&#xD;
            b.SetValue(Grid.RowProperty, row);&#xD;
            g.Children.Remove((UIElement)fe);&#xD;
            b.Margin = fe.Margin;&#xD;
            fe.Margin = new Thickness(0);&#xD;
            b.Child = (UIElement)fe;&#xD;
        }&#xD;
        else if (parent is Border)&#xD;
        {&#xD;
            b = parent as Border;&#xD;
        }&#xD;
&#xD;
        if (e.Action == ValidationErrorEventAction.Added)&#xD;
        {&#xD;
            if (b != null)&#xD;
            {&#xD;
                b.BorderThickness = new Thickness(1);&#xD;
            }&#xD;
            ToolTipService.SetToolTip(fe, new TextBlock() { Text = e.Error.Exception.Message });&#xD;
        }&#xD;
        if (e.Action == ValidationErrorEventAction.Removed)&#xD;
        {&#xD;
            if (b != null)&#xD;
            {&#xD;
                b.BorderThickness = new Thickness(0);&#xD;
            }&#xD;
            ToolTipService.SetToolTip(fe, null);&#xD;
        }&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
Note that when registering the attached property, we register a value changed handler&#xD;
(in this case &lt;code&gt;OnValidationBehaviorChanged&lt;/code&gt;).  This will get called&#xD;
the first time the property is set, which gives us an opportunity to mess with the&#xD;
element that the property is attached to.  If the value of the property is being&#xD;
set to true, we hook up the &lt;code&gt;BindingValidationError&lt;/code&gt; handler.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
In the validation error handler, we have to find out if the element is currently surrounded&#xD;
by a Border, and add one if it isn’t.  Note: in this example it will only work&#xD;
if the element is originally the child of a Grid.  This could easily be modified&#xD;
to support the other Panel types.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Once the parent is a border, then the old logic from the previous example can be reused&#xD;
to set the border and tooltip on or off as appropriate.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Notice that we don’t mark the BindingValidationError event as Handled so that it will&#xD;
bubble.  That allows us to write additional forms specific error handling higher&#xD;
up in the visual hierarchy.  At the form level we might want to invalidate the&#xD;
submit button if validation failed, or something similar, while letting the logic&#xD;
in the attached property handle the UI effects.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
In the XAML, this new attached property can be used to attached the desired visual&#xD;
effect to any FrameworkElement like so&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: xml; highlight: [3]"&gt;&amp;lt;TextBox Width="Auto" x:Name="txtNewHours"  Text="{Binding Hours, Mode=TwoWay, Converter={StaticResource hoursConverter}, &#xD;
    NotifyOnValidationError=true, ValidatesOnExceptions=true}" &#xD;
    my:ValidationService.ValidationBehavior="true"&#xD;
    Grid.Row="1" Grid.Column="1" Margin="5,5,5,5"/&amp;gt;&lt;/pre&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=9mcja1ap"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=EoGYJWQm"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=28ISYQW5"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=EUHLb6x2"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=HXWkYLTr"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=HXWkYLTr" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=aO9SVP9U"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=aO9SVP9U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,265d8ab9-edda-4560-b00b-702639e389a8.aspx</comments>
      <category>Silverlight;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/ValidationUIRevisitiedAttachedProperties.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=53cdf2d5-86eb-419f-aab5-a687858eb8eb</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,53cdf2d5-86eb-419f-aab5-a687858eb8eb.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,53cdf2d5-86eb-419f-aab5-a687858eb8eb.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=53cdf2d5-86eb-419f-aab5-a687858eb8eb</wfw:commentRss>
      
      <title>LINQ order by with dymanic &amp;ldquo;column&amp;rdquo; names</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,53cdf2d5-86eb-419f-aab5-a687858eb8eb.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/2PgI9efVU3U/LINQOrderByWithDymanicLdquocolumnrdquoNames.aspx</link>
      <pubDate>Thu, 19 Feb 2009 21:38:59 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://blogs.sftsrc.com/stuart"&gt;Stuart&lt;/a&gt; posted a great &lt;a href="http://blogs.sftsrc.com/stuart/archive/2009/02/19/130.aspx"&gt;solution&lt;/a&gt; he&#xD;
came up with for writing dynamic orderby queries in LINQ when you don’t know the “column”&#xD;
name that you want to sort by ahead of time. &#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=040dkavR"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=mKfGJHXp"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=DUNXXIF0"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=g2ouP1qL"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=Pj5OqV52"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=Pj5OqV52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=MkH6wSt7"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=MkH6wSt7" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,53cdf2d5-86eb-419f-aab5-a687858eb8eb.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/LINQOrderByWithDymanicLdquocolumnrdquoNames.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=ca50b99b-0907-46cc-aea6-339db453b878</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,ca50b99b-0907-46cc-aea6-339db453b878.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,ca50b99b-0907-46cc-aea6-339db453b878.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=ca50b99b-0907-46cc-aea6-339db453b878</wfw:commentRss>
      
      <title>New hands on Continuous Integration course at SoftSource</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,ca50b99b-0907-46cc-aea6-339db453b878.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/G0Y7YultZF8/NewHandsOnContinuousIntegrationCourseAtSoftSource.aspx</link>
      <pubDate>Thu, 19 Feb 2009 20:37:26 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
I’m going to be teaching two new one-day courses on setting up a Continuous Integration&#xD;
process, one using freely available tools, and one using Microsoft Team Foundation&#xD;
Server.  For more details and to register, see our &lt;a href="https://events.sftsrc.com"&gt;registration&#xD;
page&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Both classes will be held at the Westside campus of &lt;a href="http://www.oit.edu"&gt;&lt;img title="OIT" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="54" alt="OIT" src="http://www.cauldwell.net/patrick/blog/images/NewhandsonContinuousIntegrationcourseatS_B0B5/image.png" width="118" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Course Description: &lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
This one day course will provide a hands on look at setting up a Continuous Integration&#xD;
process using freely available tools from beginning to end. Students will learn the&#xD;
theory and practice behind establishing a Continuous Integration process, including&#xD;
setting up a build script, running unit tests, setting up an automated build/test&#xD;
server, and capturing reporting information for the whole process.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Course Technology&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
This course uses Microsoft Windows XP, the Microsoft .NET 3.5 Framework, NAnt, NUnit,&#xD;
and CruiseControl.NET. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;At the end of the course you will be able to: &lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;ul&gt;&#xD;
          &lt;li&gt;&#xD;
Create a build script using NAnt or MSBuild &#xD;
&lt;/li&gt;&#xD;
          &lt;li&gt;&#xD;
Create and run unit tests using NUnit &#xD;
&lt;/li&gt;&#xD;
          &lt;li&gt;&#xD;
Set up and run an automated build using CruiseControl.NET &#xD;
&lt;/li&gt;&#xD;
          &lt;li&gt;&#xD;
Capture reporting data from the automated CI process &#xD;
&lt;/li&gt;&#xD;
        &lt;/ul&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;strong&gt;Course Outline&lt;/strong&gt;&#xD;
        &lt;ul&gt;&#xD;
Continuous Integration in Theory &#xD;
&lt;ul&gt;&lt;li&gt;&#xD;
Why CI is important &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
How CI fits into the Software Development process &#xD;
&lt;/li&gt;&lt;/ul&gt;&#xD;
Creating a build script &#xD;
&lt;ul&gt;&lt;li&gt;&#xD;
What goes in a build script? &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
How does NAnt work? &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
How does MSBuild work? &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Creating build scripts for NAnt or MSBuild &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Running an automated build &#xD;
&lt;/li&gt;&lt;/ul&gt;&#xD;
Adding unit tests to your build &#xD;
&lt;ul&gt;&lt;li&gt;&#xD;
Writing NUnit tests &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Running tests as part of a build &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Capturing test results &#xD;
&lt;/li&gt;&lt;/ul&gt;&#xD;
Continuous Integration with CruiseControl.NET &#xD;
&lt;ul&gt;&lt;li&gt;&#xD;
Installing and configuring CC.NET &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Adding projects to a build server &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Reporting with CC.NET &#xD;
&lt;/li&gt;&lt;li&gt;&#xD;
Running multiple builds on the same server &#xD;
&lt;ul&gt;&#xD;
Dependencies between builds&#xD;
&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;strong&gt;Prerequisites&lt;/strong&gt;&#xD;
        &lt;p&gt;&#xD;
This class is intended for experienced .NET 2.0 software developers. &#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=9hOk1jku"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=hsgcccbb"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=MVl1iTI5"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=hjv7MU26"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=p5QbjWXC"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=p5QbjWXC" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=zcZhEcIA"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=zcZhEcIA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,ca50b99b-0907-46cc-aea6-339db453b878.aspx</comments>
      <category>Continuous Integration;training;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/NewHandsOnContinuousIntegrationCourseAtSoftSource.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=f333fdfc-6c0b-4fe0-8b65-1ddf8430143b</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,f333fdfc-6c0b-4fe0-8b65-1ddf8430143b.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,f333fdfc-6c0b-4fe0-8b65-1ddf8430143b.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=f333fdfc-6c0b-4fe0-8b65-1ddf8430143b</wfw:commentRss>
      
      <title>Databinding validation in Silverlight, a UI perspective</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,f333fdfc-6c0b-4fe0-8b65-1ddf8430143b.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/ImfT50FKK84/DatabindingValidationInSilverlightAUIPerspective.aspx</link>
      <pubDate>Wed, 18 Feb 2009 22:10:45 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
I was having a bit of trouble getting validation to work during data binding in SL,&#xD;
but that seems to be resolved now.  I’ve got a little time tracking app, and&#xD;
want to be able to log new time entries…&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/DatabindingvalidationinSilverlightaUIper_C68C/CropperCapture8.png"&gt;&#xD;
            &lt;img title="CropperCapture[8]" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="94" alt="CropperCapture[8]" src="http://www.cauldwell.net/patrick/blog/images/DatabindingvalidationinSilverlightaUIper_C68C/CropperCapture8_thumb.png" width="465" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I want the user to be able to enter hours only in 1/4 hour increments.  The way&#xD;
that gets handled in Silverlight is different from WPF.  To make it work in Silverlight&#xD;
the data binding source has the throw an exception if the new value is unacceptable. &#xD;
In this case, the source is a “LogEntry” class that has a property “Hours” that implements &lt;code&gt;INotifyPropertyChanged&lt;/code&gt; to&#xD;
support full two-way data binding.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;public class LogEntry : INotifyPropertyChanged&#xD;
{&#xD;
&#xD;
    private decimal hours;&#xD;
    public decimal Hours &#xD;
    {&#xD;
        get&#xD;
        {&#xD;
            return hours;&#xD;
        }&#xD;
        set&#xD;
        {&#xD;
            if ((value % .25M) != 0)&#xD;
            {&#xD;
                throw new Exception("please enter time in quarter-hour increments");&#xD;
            }&#xD;
            if (hours != value)&#xD;
            {&#xD;
                hours = value;&#xD;
&#xD;
                NotifyPropertyChanged("Hours");&#xD;
            }&#xD;
        }&#xD;
    }&#xD;
&#xD;
    private void NotifyPropertyChanged(string p)&#xD;
    {&#xD;
        if (PropertyChanged != null)&#xD;
        {&#xD;
            PropertyChanged(this, new PropertyChangedEventArgs(p));&#xD;
        }&#xD;
    }&#xD;
&#xD;
    #region INotifyPropertyChanged Members&#xD;
&#xD;
    public event PropertyChangedEventHandler PropertyChanged;&#xD;
&#xD;
    #endregion&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
In the property setting for the Hours property, if the value isn’t evenly divisible&#xD;
by .25 an Exception gets thrown.  In the XAML, the binding is set up to notify&#xD;
(as a binding error) when an exception gets thrown&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
 &#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: xml"&gt;&amp;lt;TextBox Width="Auto" x:Name="txtNewHours"  Text="{Binding Hours, &#xD;
    Mode=TwoWay, &#xD;
    Converter={StaticResource hoursConverter}, &#xD;
    NotifyOnValidationError=true, ValidatesOnExceptions=true}"/&amp;gt;&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
The grid that holds all the controls handles the BindingValidationError event, which&#xD;
is where all the fun stuff happens…&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;private void newEntryGrid_BindingValidationError(object sender, ValidationErrorEventArgs e)&#xD;
{&#xD;
    if (e.Action == ValidationErrorEventAction.Added)&#xD;
    {&#xD;
        //not valid&#xD;
    }&#xD;
    if (e.Action == ValidationErrorEventAction.Removed)&#xD;
    {&#xD;
        //now it's valid&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
OK, so now I know when the value isn’t valid, but what to do about it.  In WPF,&#xD;
the easiest thing to do would be to use a “decorator” to add a border around the UI&#xD;
element that failed validation, but in Silverlight we don’t get decorators. &#xD;
Instead, I wrapped each item that needed to support validation in a red border with&#xD;
a thickness of 0 in XAML.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: xml"&gt;&amp;lt;Border BorderBrush="Red" BorderThickness="0"&amp;gt;&#xD;
    &amp;lt;TextBox x:Name="txtNewHours" Text="{Binding ...}"/&amp;gt;&#xD;
&amp;lt;/Border&amp;gt;&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
That’s a little extra work that I’d rather not do, but there it is.  It would&#xD;
be easy to wrap up this behavior in a custom control, but this was much quicker. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
In the validation handler then, all we have to do is get the original source of the&#xD;
binding error and use the VisualTreeHelper to get it’s parent.  If that parent&#xD;
happens to be a border, set the border’s thickness to 1 to make it visible. &#xD;
I’m also setting the tooltip for that offending control to be the message of the validation&#xD;
error.  If the &lt;code&gt;ValidationErrorEventAction == Removed&lt;/code&gt;, then get rid&#xD;
of the tooltip and set the border’s thickness back to 0.&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="brush: csharp"&gt;private void newEntryGrid_BindingValidationError(object sender, ValidationErrorEventArgs e)&#xD;
{&#xD;
    if (e.Action == ValidationErrorEventAction.Added)&#xD;
    {&#xD;
        DependencyObject ui = e.OriginalSource as DependencyObject &#xD;
        DependencyObject parent = VisualTreeHelper.GetParent(ui);&#xD;
        if (parent is Border)&#xD;
        {&#xD;
            ((Border)parent).BorderThickness = new Thickness(1);&#xD;
        }&#xD;
        ToolTipService.SetToolTip(ui, new TextBlock() { Text = e.Error.Exception.Message });&#xD;
    }&#xD;
    if (e.Action == ValidationErrorEventAction.Removed)&#xD;
    {&#xD;
        DependencyObject ui = e.OriginalSource as DependencyObject &#xD;
        DependencyObject parent = VisualTreeHelper.GetParent(ui);&#xD;
        if (parent is Border)&#xD;
        {&#xD;
            ((Border)parent).BorderThickness = new Thickness(0);&#xD;
        }&#xD;
        ToolTipService.SetToolTip(ui, null);&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/DatabindingvalidationinSilverlightaUIper_C68C/CropperCapture9.png"&gt;&#xD;
            &lt;img title="CropperCapture[9]" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="91" alt="CropperCapture[9]" src="http://www.cauldwell.net/patrick/blog/images/DatabindingvalidationinSilverlightaUIper_C68C/CropperCapture9_thumb.png" width="458" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
That same code should work for any control that I want to do validation on, as long&#xD;
as I remember to add the borders in XAML.  &#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=SLIaj6zk"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=GGqaFVOj"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=EnjjJ82m"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=SWwoXiz7"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=QW0iZx9l"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=QW0iZx9l" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=ALVzP7Mi"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=ALVzP7Mi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,f333fdfc-6c0b-4fe0-8b65-1ddf8430143b.aspx</comments>
      <category>Silverlight;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/DatabindingValidationInSilverlightAUIPerspective.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=0913dda2-9cef-4b66-a83d-2a26f8f0519e</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,0913dda2-9cef-4b66-a83d-2a26f8f0519e.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,0913dda2-9cef-4b66-a83d-2a26f8f0519e.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=0913dda2-9cef-4b66-a83d-2a26f8f0519e</wfw:commentRss>
      
      <title>The bossman blogeth</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,0913dda2-9cef-4b66-a83d-2a26f8f0519e.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/jnmz4y-XlV4/TheBossmanBlogeth.aspx</link>
      <pubDate>Fri, 13 Feb 2009 20:16:28 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
In the wake of our Silverlight presentations this week, &lt;a href="http://blogs.sftsrc.com/shaun/Default.aspx"&gt;Shaun&lt;/a&gt; (CTO&#xD;
of &lt;a href="http://www.sftsrc.com"&gt;SoftSource&lt;/a&gt;, and my boss) is going to be blogging&#xD;
on his &lt;a href="http://blogs.sftsrc.com/shaun/archive/2009/02/13/124.aspx"&gt;demos&lt;/a&gt;,&#xD;
starting with Silverlight/JavaScript interactivity.  His demos were pretty cool,&#xD;
so I’m looking forward to reading his commentary.  I might just follow suit with&#xD;
a few examples too…&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=IXgGSRXY"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=8tARZTjg"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=O8uLGz6M"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=ateUMmFi"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=D1joFJnk"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=D1joFJnk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=jaqURft4"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=jaqURft4" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,0913dda2-9cef-4b66-a83d-2a26f8f0519e.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/TheBossmanBlogeth.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=87ee751c-14dc-4b5c-a68a-60af3bcccfcf</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,87ee751c-14dc-4b5c-a68a-60af3bcccfcf.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,87ee751c-14dc-4b5c-a68a-60af3bcccfcf.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=87ee751c-14dc-4b5c-a68a-60af3bcccfcf</wfw:commentRss>
      
      <title>New courses in Portland</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,87ee751c-14dc-4b5c-a68a-60af3bcccfcf.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/DHspdifh1Rs/NewCoursesInPortland.aspx</link>
      <pubDate>Fri, 13 Feb 2009 18:17:36 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Check out &lt;a href="http://events.sftsrc.com/"&gt;http://events.sftsrc.com/&lt;/a&gt; for more&#xD;
new classes…&#xD;
&lt;/p&gt;&#xD;
        &lt;ul&gt;&#xD;
          &lt;li&gt;&#xD;
LINQ&lt;/li&gt;&#xD;
          &lt;ul&gt;&#xD;
            &lt;li&gt;&#xD;
2 days of LINQ to Objects, LINQ to XML, LINQ to SQL, LINQ to Entities and more&lt;/li&gt;&#xD;
          &lt;/ul&gt;&#xD;
          &lt;li&gt;&#xD;
ASP.NET&lt;/li&gt;&#xD;
          &lt;ul&gt;&#xD;
            &lt;li&gt;&#xD;
5 days of ASP.NET including some AJAX and a hint of Silverlight&lt;/li&gt;&#xD;
          &lt;/ul&gt;&#xD;
          &lt;li&gt;&#xD;
WPF&lt;/li&gt;&#xD;
          &lt;ul&gt;&#xD;
            &lt;li&gt;&#xD;
3 days of WPF goodness&lt;/li&gt;&#xD;
          &lt;/ul&gt;&#xD;
          &lt;li&gt;&#xD;
Silverlight &#xD;
&lt;/li&gt;&#xD;
          &lt;ul&gt;&#xD;
            &lt;li&gt;&#xD;
2 days for those with WPF experience or&lt;/li&gt;&#xD;
            &lt;li&gt;&#xD;
3 days for web developers&lt;/li&gt;&#xD;
          &lt;/ul&gt;&#xD;
          &lt;li&gt;&#xD;
C#  and the .NET Framework&lt;/li&gt;&#xD;
          &lt;ul&gt;&#xD;
            &lt;li&gt;&#xD;
5 days of C# 3.0 and the 3.5 framework, including LINQ, extension methods and the&#xD;
rest of the new language features&lt;/li&gt;&#xD;
          &lt;/ul&gt;&#xD;
        &lt;/ul&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=GcxAObuD"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=DnfgBXuY"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=80ZhYQXR"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=L4PoBY8d"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=NMLird19"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=NMLird19" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=1AHtRDUE"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=1AHtRDUE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,87ee751c-14dc-4b5c-a68a-60af3bcccfcf.aspx</comments>
      <category>Ajax;ASP.NET;Silverlight;training;Work</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/NewCoursesInPortland.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=fb099083-a75e-43d7-8f71-38d5de66b407</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,fb099083-a75e-43d7-8f71-38d5de66b407.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,fb099083-a75e-43d7-8f71-38d5de66b407.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=fb099083-a75e-43d7-8f71-38d5de66b407</wfw:commentRss>
      
      <title>LINQ to SQL and concurrency</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,fb099083-a75e-43d7-8f71-38d5de66b407.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/Tu1ohZdvO8E/LINQToSQLAndConcurrency.aspx</link>
      <pubDate>Fri, 06 Feb 2009 17:39:15 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Google is great at providing 20/20 hindsight.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The little &lt;a href="http://www.cauldwell.net/patrick/blog/LINQToSQLAmpInsertTriggersCanBeAnProblem.aspx"&gt;problem&lt;/a&gt; I&#xD;
was having with insert triggers is (unsurprisingly) not uncommon.  I googled&#xD;
a bit after a suggestion in a comment (thanks El Guapo) and found a great &lt;a href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/07/01/10557.aspx"&gt;explanation&lt;/a&gt; by &lt;a href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/default.aspx"&gt;Mike&#xD;
Taulty&lt;/a&gt; on how to deal with just such a concurrency problem.  He’s specifically&#xD;
dealing with a timestamp column, but the issue is essentially the same.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Good to know…&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=Da98dEq9"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=YTERHCqJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=Yrd8rwAq"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=0WhVBVL9"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=rHcLKziU"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=rHcLKziU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=QL7LXaQs"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=QL7LXaQs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,fb099083-a75e-43d7-8f71-38d5de66b407.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/LINQToSQLAndConcurrency.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=2281e349-bc30-47b1-b5fb-f6972914e988</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,2281e349-bc30-47b1-b5fb-f6972914e988.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,2281e349-bc30-47b1-b5fb-f6972914e988.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2281e349-bc30-47b1-b5fb-f6972914e988</wfw:commentRss>
      
      <title>Vegas, baby</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,2281e349-bc30-47b1-b5fb-f6972914e988.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/1lvZLW0wazo/VegasBaby.aspx</link>
      <pubDate>Thu, 05 Feb 2009 22:56:38 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://2009.visitmix.com"&gt;&#xD;
            &lt;img src="http://2009.visitmix.com/Images/BlogBling/All_Bling/Your_Web_Needs_You/MIX09_BlogBling_QuoteWebNeeds136x186.jpg"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I’ll be there, soaking up the Silverlight-y goodness.  &#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=48gjsNgt"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=rM9EFHpq"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=UMqqYN0p"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=wowBNx8m"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=NOtuzhyz"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=NOtuzhyz" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=PS5JwBMT"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=PS5JwBMT" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,2281e349-bc30-47b1-b5fb-f6972914e988.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/VegasBaby.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=a544191a-2d6a-4288-bae5-097f5e19a2c0</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,a544191a-2d6a-4288-bae5-097f5e19a2c0.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,a544191a-2d6a-4288-bae5-097f5e19a2c0.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=a544191a-2d6a-4288-bae5-097f5e19a2c0</wfw:commentRss>
      <slash:comments>2</slash:comments>
      
      <title>LINQ to SQL &amp;amp; insert triggers (can be an problem)</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,a544191a-2d6a-4288-bae5-097f5e19a2c0.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/bvu8MACJ3b4/LINQToSQLAmpInsertTriggersCanBeAnProblem.aspx</link>
      <pubDate>Thu, 05 Feb 2009 22:49:23 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Lets say I have a nice simple database (guess which one…)&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/LINQtoSQLinserttriggerscanbeanproblem_CF78/CropperCapture5.png"&gt;&#xD;
            &lt;img title="CropperCapture[5]" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="409" alt="CropperCapture[5]" src="http://www.cauldwell.net/patrick/blog/images/LINQtoSQLinserttriggerscanbeanproblem_CF78/CropperCapture5_thumb.png" width="448" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Now I want to insert a new Order into the Orders table&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
 &#xD;
&lt;/p&gt;&#xD;
        &lt;div style="font-size: 11pt; background: white; color: black; font-family: consolas"&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;NorthwindDataContext&lt;/span&gt; context&#xD;
= &lt;span style="color: blue"&gt;new&lt;/span&gt;&lt;span style="color: #2b91af"&gt;NorthwindDataContext&lt;/span&gt;())&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
{&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    &lt;span style="color: #2b91af"&gt;Order&lt;/span&gt; order = &lt;span style="color: blue"&gt;new&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;();&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    context.Orders.InsertOnSubmit(order);&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    context.SubmitChanges();&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
}&#xD;
&lt;/p&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
No problem.  Totally works like you’d think.  What happens if I make more&#xD;
changes after that and call SubmitChanges() again?&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="font-size: 11pt; background: white; color: black; font-family: consolas"&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;NorthwindDataContext&lt;/span&gt; context&#xD;
= &lt;span style="color: blue"&gt;new&lt;/span&gt;&lt;span style="color: #2b91af"&gt;NorthwindDataContext&lt;/span&gt;())&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
{&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    &lt;span style="color: #2b91af"&gt;Order&lt;/span&gt; order = &lt;span style="color: blue"&gt;new&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;();&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    context.Orders.InsertOnSubmit(order);&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    context.SubmitChanges();&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
 &#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    order.Freight = 98.77M;&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    order.ShipName = &lt;span style="color: #a31515"&gt;"Fred Jones"&lt;/span&gt;;&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
 &#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
    context.SubmitChanges();&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
}&#xD;
&lt;/p&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Still cool.  The problem comes in if I add an insert trigger.  Let’s say&#xD;
I add a trigger to set the OrderDate column of the order to make sure it’s always&#xD;
the right date…&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="font-size: 11pt; background: white; color: black; font-family: consolas"&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;ALTER TRIGGER &lt;/span&gt;Trigger1&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;ON &lt;/span&gt;dbo.Orders&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;FOR INSERT&lt;/span&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;AS&lt;/span&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;UPDATE &lt;/span&gt;Orders&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;SET &lt;/span&gt;OrderDate = &lt;span style="color: blue"&gt;GETDATE&lt;/span&gt;()&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;FROM &lt;/span&gt;Orders &lt;span style="color: blue"&gt;INNER JOIN &lt;/span&gt;inserted &lt;span style="color: blue"&gt;ON &lt;/span&gt;Orders.OrderID&#xD;
= inserted.OrderID&#xD;
&lt;/p&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Whether or not that’s a good idea is a whole ‘nother topic.  Seemed like the&#xD;
thing to do at the time…  However, now there’s a problem.  The first SubmitChanges()&#xD;
works fine, but the second one fails with an update conflict.  WTF?  After&#xD;
I stopped to think about it (and talked to &lt;a href="http://blogs.sftsrc.com/stuart/Default.aspx"&gt;Stuart&lt;/a&gt;)&#xD;
I realized that that makes perfect sense.  The copy of Order that I have in memory&#xD;
doesn’t know anything about the result of the insert trigger, and so the record is&#xD;
out of date, hence the conflict.  In this particular case it wasn’t a problem&#xD;
because it wasn’t too much work to just take out the trigger and set the date in the&#xD;
code.  I had been hoping that I wouldn’t have to redeploy the web app, hence&#xD;
the trigger.  Best laid plans…&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Anyway, it turns out that something similar came up on another project, so it is something&#xD;
to be aware of.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=f61TO4iw"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=ki4F1QYD"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=uqrqJryC"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=vvcVYuRN"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=OgyL4kHz"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=OgyL4kHz" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=waaasi5M"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=waaasi5M" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,a544191a-2d6a-4288-bae5-097f5e19a2c0.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/LINQToSQLAmpInsertTriggersCanBeAnProblem.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=901e6b12-1d2b-42a1-9142-5e67582cec9b</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,901e6b12-1d2b-42a1-9142-5e67582cec9b.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,901e6b12-1d2b-42a1-9142-5e67582cec9b.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=901e6b12-1d2b-42a1-9142-5e67582cec9b</wfw:commentRss>
      
      <title>Joining the conversation</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,901e6b12-1d2b-42a1-9142-5e67582cec9b.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/L3ldrP98H9Y/JoiningTheConversation.aspx</link>
      <pubDate>Thu, 05 Feb 2009 21:04:23 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
After reading Scott’s latest &lt;a href="http://www.hanselman.com/blog/HowToTwitterFirstStepsAndATwitterGlossary.aspx"&gt;missive&lt;/a&gt;,&#xD;
I finally gave in and joined the Tweeple.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.twitter.com/pcauldwell"&gt;@pcauldwell&lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=PsdPVIhV"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=zw0TLBIa"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=ekNxPkJQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=s9yXGdEC"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=dJqL1UgM"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=dJqL1UgM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=w6jAOTuz"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=w6jAOTuz" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,901e6b12-1d2b-42a1-9142-5e67582cec9b.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/JoiningTheConversation.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=249a7dd9-f6a6-42d1-ba5f-ddb073a9ffca</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,249a7dd9-f6a6-42d1-ba5f-ddb073a9ffca.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,249a7dd9-f6a6-42d1-ba5f-ddb073a9ffca.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=249a7dd9-f6a6-42d1-ba5f-ddb073a9ffca</wfw:commentRss>
      
      <title>Databinding to a UserControl in Silverlight</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,249a7dd9-f6a6-42d1-ba5f-ddb073a9ffca.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/ALXMUaN-oSE/DatabindingToAUserControlInSilverlight.aspx</link>
      <pubDate>Thu, 22 Jan 2009 20:54:28 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;Yesterday I posted a bit about a dynamic&#xD;
survey in Silverlight, and today I wanted to start delving into a few details. &#xD;
First of all, databinding to a user control… &#xD;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;&#xD;
I wanted my datagrid to show a series of radio buttons representing a “rating” from&#xD;
1-5, where that rating corresponds to an enum value in C# and an integer in SQL.  &#xD;
&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cauldwell.net/patrick/blog/images/DatabindingtoaUserControlinSilverlight_8693/CropperCapture4.png"&gt;&lt;img title="CropperCapture[4]" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="52" alt="CropperCapture[4]" src="http://www.cauldwell.net/patrick/blog/images/DatabindingtoaUserControlinSilverlight_8693/CropperCapture4_thumb.png" width="449" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&#xD;
For databinding to work the way I’d want, I need to bind the one value in the source&#xD;
to the set of radio buttons in the target.  The easiest way I could think of&#xD;
(and there may be a better way I haven’t thought of) was to make the radio buttons&#xD;
into a user control, and expose a single value.  In the XAML for the datagrid,&#xD;
it looks like&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;data&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataGridTemplateColumn.CellTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;t&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Rating&lt;/span&gt;&lt;span style="color: red"&gt; UserRating&lt;/span&gt;&lt;span style="color: blue"&gt;="{&lt;/span&gt;&lt;span style="color: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="color: red"&gt; Path&lt;/span&gt;&lt;span style="color: blue"&gt;=Answer,&lt;/span&gt;&lt;span style="color: red"&gt; Mode&lt;/span&gt;&lt;span style="color: blue"&gt;=TwoWay}"&#xD;
/&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;data&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataGridTemplateColumn.CellTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&#xD;
The CellTemplate contains just the user control, and binds its UserRating property&#xD;
to the Answer property in the source.&#xD;
&lt;/p&gt;&lt;p&gt;&#xD;
The XAML for the UserControl is simple&#xD;
&lt;/p&gt;&lt;div style="font-size: 11pt; background: white; color: black; font-family: consolas"&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;UserControl&lt;/span&gt;&lt;span style="color: red"&gt; x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Class&lt;/span&gt;&lt;span style="color: blue"&gt;="Evaluation.Rating"&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
   &lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
   &lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&#xD;
&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackPanel&lt;/span&gt;&lt;span style="color: red"&gt; Orientation&lt;/span&gt;&lt;span style="color: blue"&gt;="Horizontal"&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RadioButton&lt;/span&gt;&lt;span style="color: red"&gt; Content&lt;/span&gt;&lt;span style="color: blue"&gt;="Excellent&#xD;
(5)"&lt;/span&gt;&lt;span style="color: red"&gt; x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;="excellent"&lt;/span&gt;&lt;span style="color: red"&gt; Checked&lt;/span&gt;&lt;span style="color: blue"&gt;="excellent_Checked"/&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RadioButton&lt;/span&gt;&lt;span style="color: red"&gt; Content&lt;/span&gt;&lt;span style="color: blue"&gt;="Good"&lt;/span&gt;&lt;span style="color: red"&gt; x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;="good"&lt;/span&gt;&lt;span style="color: red"&gt; Checked&lt;/span&gt;&lt;span style="color: blue"&gt;="good_Checked"/&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RadioButton&lt;/span&gt;&lt;span style="color: red"&gt; Content&lt;/span&gt;&lt;span style="color: blue"&gt;="Neutral"&lt;/span&gt;&lt;span style="color: red"&gt; x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;="neutral"&lt;/span&gt;&lt;span style="color: red"&gt; Checked&lt;/span&gt;&lt;span style="color: blue"&gt;="neutral_Checked"/&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RadioButton&lt;/span&gt;&lt;span style="color: red"&gt; Content&lt;/span&gt;&lt;span style="color: blue"&gt;="Adequate"&lt;/span&gt;&lt;span style="color: red"&gt; x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;="adequate"&lt;/span&gt;&lt;span style="color: red"&gt; Checked&lt;/span&gt;&lt;span style="color: blue"&gt;="adequate_Checked"/&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RadioButton&lt;/span&gt;&lt;span style="color: red"&gt; Content&lt;/span&gt;&lt;span style="color: blue"&gt;="Poor&#xD;
(1)"&lt;/span&gt;&lt;span style="color: red"&gt; x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;="poor"&lt;/span&gt;&lt;span style="color: red"&gt; Checked&lt;/span&gt;&lt;span style="color: blue"&gt;="poor_Checked"/&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: #a31515"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackPanel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;UserControl&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&#xD;
In order to get two-way databinding notifications to work properly both ways, the&#xD;
UserRating property of the control is implemented as a DependencyProperty…&#xD;
&lt;/p&gt;&lt;div style="font-size: 11pt; background: white; color: black; font-family: consolas"&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt;&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt; UserRating&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
{&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    &lt;span style="color: blue"&gt;get&lt;/span&gt; { &lt;span style="color: blue"&gt;return&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;)GetValue(UserRatingProperty);&#xD;
}&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    &lt;span style="color: blue"&gt;set&lt;/span&gt; { SetValue(UserRatingProperty, &lt;span style="color: blue"&gt;value&lt;/span&gt;);&#xD;
}&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
}&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
 &#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: green"&gt;// Using a DependencyProperty as the backing store for&#xD;
UserRating.  This enables animation, styling, binding, etc...&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt;&lt;span style="color: blue"&gt;static&lt;/span&gt;&lt;span style="color: blue"&gt;readonly&lt;/span&gt;&lt;span style="color: #2b91af"&gt;DependencyProperty&lt;/span&gt; UserRatingProperty&#xD;
=&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    &lt;span style="color: #2b91af"&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style="color: #a31515"&gt;"UserRating"&lt;/span&gt;, &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;), &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Rating&lt;/span&gt;), &lt;span style="color: blue"&gt;new&lt;/span&gt;&lt;span style="color: #2b91af"&gt;PropertyMetadata&lt;/span&gt;(&lt;span style="color: blue"&gt;new&lt;/span&gt;&lt;span style="color: #2b91af"&gt;PropertyChangedCallback&lt;/span&gt;(RatingChangedCallback)));&#xD;
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&#xD;
Note the callback registered for the PropertyChanged event of the dependency property. &#xD;
If databinding changes the value of the dependency property, we still need to update&#xD;
the UI to check the right radio button.&#xD;
&lt;/p&gt;&lt;div style="font-size: 11pt; background: white; color: black; font-family: consolas"&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;private&lt;/span&gt;&lt;span style="color: blue"&gt;static&lt;/span&gt;&lt;span style="color: blue"&gt;void&lt;/span&gt; RatingChangedCallback(&lt;span style="color: #2b91af"&gt;DependencyObject&lt;/span&gt; d, &lt;span style="color: #2b91af"&gt;DependencyPropertyChangedEventArgs&lt;/span&gt; e)&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
{&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    &lt;span style="color: #2b91af"&gt;Rating&lt;/span&gt; r = d &lt;span style="color: blue"&gt;as&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Rating&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    r.updateUi((&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;)e.NewValue);&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
 &#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
}&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
 &#xD;
&lt;/p&gt;&lt;/div&gt;&lt;div style="font-size: 11pt; background: white; color: black; font-family: consolas"&gt;&lt;p style="margin: 0px"&gt;&lt;span style="color: blue"&gt;private&lt;/span&gt;&lt;span style="color: blue"&gt;void&lt;/span&gt; updateUi(&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt; rating)&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
{&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    &lt;span style="color: blue"&gt;switch&lt;/span&gt; (rating)&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    {&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
        &lt;span style="color: blue"&gt;case&lt;/span&gt;&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;.Excellent:&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            excellent.IsChecked&#xD;
= &lt;span style="color: blue"&gt;true&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;break&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
        &lt;span style="color: blue"&gt;case&lt;/span&gt;&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;.Good:&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            good.IsChecked&#xD;
= &lt;span style="color: blue"&gt;true&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;break&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
        &lt;span style="color: blue"&gt;case&lt;/span&gt;&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;.Neutral:&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            neutral.IsChecked&#xD;
= &lt;span style="color: blue"&gt;true&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;break&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
        &lt;span style="color: blue"&gt;case&lt;/span&gt;&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;.Adequate:&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            adequate.IsChecked&#xD;
= &lt;span style="color: blue"&gt;true&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;break&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
        &lt;span style="color: blue"&gt;case&lt;/span&gt;&lt;span style="color: #2b91af"&gt;ScaledAnswer&lt;/span&gt;.Poor:&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            poor.IsChecked&#xD;
= &lt;span style="color: blue"&gt;true&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
            &lt;span style="color: blue"&gt;break&lt;/span&gt;;&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
    }&#xD;
&lt;/p&gt;&lt;p style="margin: 0px"&gt;&#xD;
}&#xD;
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&#xD;
Finally, the user control handles all the radio button “Checked” events and sets the&#xD;
value of the DependencyProperty to the correct value.&#xD;
&lt;/p&gt;&lt;p&gt;&#xD;
The UserControl provided a fairly smooth way of handling the databinding without having&#xD;
to implement a custom control, and could be reused in other contexts.  There’s&#xD;
probably a way to make it a bit more dynamic to handle more radio buttons, etc. but&#xD;
this worked for my particular case.&#xD;
&lt;/p&gt;&lt;br&gt;&lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=EN1hLTNL"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=aKbEyUko"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=yD1KIwrF"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=9DtoO82z"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=M144gbNb"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=M144gbNb" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=AZ3BrZwd"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=AZ3BrZwd" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,249a7dd9-f6a6-42d1-ba5f-ddb073a9ffca.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/DatabindingToAUserControlInSilverlight.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=82e5e9fc-a4a5-474e-88fe-30b6327d1513</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,82e5e9fc-a4a5-474e-88fe-30b6327d1513.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,82e5e9fc-a4a5-474e-88fe-30b6327d1513.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=82e5e9fc-a4a5-474e-88fe-30b6327d1513</wfw:commentRss>
      
      <title>A data-driven survey in Silverlight</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,82e5e9fc-a4a5-474e-88fe-30b6327d1513.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/xgGzK2m58Dk/ADatadrivenSurveyInSilverlight.aspx</link>
      <pubDate>Wed, 21 Jan 2009 18:23:06 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
I needed to build a survey (a course evaluation in this case, but name-your-survey…)&#xD;
and I wanted to be able to add new questions and question categories to the database&#xD;
without having to touch my (Silverlight) survey app.  I wanted the basic layout&#xD;
to look like this…&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/AdatadrivensurveyinSilverlight_90B1/CropperCapture2.png"&gt;&#xD;
            &lt;img title="CropperCapture[2]" style="border-width: 0px; display: inline;" alt="CropperCapture[2]" src="http://www.cauldwell.net/patrick/blog/images/AdatadrivensurveyinSilverlight_90B1/CropperCapture2_thumb.png" border="0" height="133" width="474"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
It took a little experimentation, and I’m sure there are other ways to make this work,&#xD;
but here’s what worked for me:&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The questions and categories live in the database, like so&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.cauldwell.net/patrick/blog/images/AdatadrivensurveyinSilverlight_90B1/CropperCapture3.png"&gt;&#xD;
            &lt;img title="CropperCapture[3]" style="border-width: 0px; display: inline;" alt="CropperCapture[3]" src="http://www.cauldwell.net/patrick/blog/images/AdatadrivensurveyinSilverlight_90B1/CropperCapture3_thumb.png" border="0" height="296" width="412"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Categories contain questions, questions have text, and what we store when the survey&#xD;
is complete are the answers to the questions.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
In the XAML, first there is an ItemsControl to deal with the categories, so that each&#xD;
category will have it’s own DataGrid.  The ItemsControl has a DataTemplate that&#xD;
defines what each category name and data grid of questions will look like (some formatting&#xD;
details removed for clarity)&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="background: white none repeat scroll 0% 0%; font-size: 11pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: consolas;"&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;ItemsControl&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; x&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt;Name&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="dgPanel"&#xD;
&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;    &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;ItemsControl.ItemTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;        &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;            &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;StackPanel&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Orientation&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="Vertical"&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;TextBlock&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Text&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="{&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;Binding&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; CategoryName&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;}"&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGrid&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; x&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt;Name&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="dgOverall" &lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: red;"&gt;ItemsSource&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="{&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;Binding&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Questions&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;}"&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGrid.Columns&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                    &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGridTextColumn&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt;Header&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="Question"&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;                   &lt;span style="color: red;"&gt;Binding&lt;/span&gt;&lt;span style="color: blue;"&gt;="{&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;Binding&lt;/span&gt;&lt;span style="color: red;"&gt; Text&lt;/span&gt;&lt;span style="color: blue;"&gt;}"&lt;/span&gt;&lt;span style="color: red;"&gt; IsReadOnly&lt;/span&gt;&lt;span style="color: blue;"&gt;="True"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                    &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGridTemplateColumn&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Header&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="Rating"&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                        &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGridTemplateColumn.CellTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                            &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                                &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;t&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;Rating&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; UserRating&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="{&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;Binding&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Path&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;=Answer,&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Mode&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;=TwoWay}"&#xD;
/&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                            &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                        &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGridTemplateColumn.CellTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                        &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGridTemplateColumn.CellEditingTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                            &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                                &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;t&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;Rating&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; UserRating&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;="{&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;Binding&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Path&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;=Answer,&lt;/span&gt;&#xD;
              &lt;span style="color: red;"&gt; Mode&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;=TwoWay}"/&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                            &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                        &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGridTemplateColumn.CellEditingTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                    &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGridTemplateColumn&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;                &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGrid.Columns&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt; &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;            &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;data&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;:&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataGrid&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;            &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;StackPanel&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;        &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;DataTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;    &lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;ItemsControl.ItemTemplate&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;font size="2"&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&#xD;
              &lt;span style="color: rgb(163, 21, 21);"&gt;ItemsControl&lt;/span&gt;&#xD;
              &lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;/font&gt;&#xD;
          &lt;/p&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The questions come from a WCF call, and get bound in the form load&#xD;
&lt;/p&gt;&#xD;
        &lt;div style="background: white none repeat scroll 0% 0%; font-size: 11pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: consolas;"&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
            &lt;span style="color: blue;"&gt;void&lt;/span&gt; client_GetQuestionsCompleted(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43, 145, 175);"&gt;GetQuestionsCompletedEventArgs&lt;/span&gt; e)&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
{&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
    dgPanel.ItemsSource = e.Result;&#xD;
&lt;/p&gt;&#xD;
          &lt;p style="margin: 0px;"&gt;&#xD;
}&#xD;
&lt;/p&gt;&#xD;
        &lt;/div&gt;&#xD;
        &lt;p&gt;&#xD;
Each row that comes back has the category header text and a collection of questions,&#xD;
so that for each item in the ItemsControl, the text is bound to the header, and the&#xD;
questions are bound to the datagrid.  The DataGridTemplateColumn stuff above&#xD;
maps the Answer property of each question to a UserControl called Rating that contains&#xD;
the radio buttons.  Depending on which radio button gets checked, the value of&#xD;
the user control represents an enum value with their answer.  Because the data&#xD;
binding is defined as TwoWay, the user’s answers are updating in the in-memory copy&#xD;
of the questions, and when the user eventually hits the “Submit” button, the collection&#xD;
of questions (and answers) is sent back to the web service.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Now I can add new questions to the database and have those questions show up in the&#xD;
survey, and previously submitted evaluations will only have answers for the questions&#xD;
that were present at the time the survey was submitted.  There’s still some work&#xD;
to do here, like setting up groups of questions so that different sets of questions&#xD;
could be used for different circumstances, etc, but this is a decent start.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=5tvB4sMm"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=yTxdZiaS"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=tAWekNeu"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=Ar8GX47b"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=l7Gd2KQd"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=l7Gd2KQd" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=uGyLvXQM"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=uGyLvXQM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,82e5e9fc-a4a5-474e-88fe-30b6327d1513.aspx</comments>
      <category>Work;Silverlight</category>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/ADatadrivenSurveyInSilverlight.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=d5f57990-f616-4c24-b7d3-3972237cc2ca</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,d5f57990-f616-4c24-b7d3-3972237cc2ca.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,d5f57990-f616-4c24-b7d3-3972237cc2ca.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d5f57990-f616-4c24-b7d3-3972237cc2ca</wfw:commentRss>
      
      <title>Practical Silverlight: More than just Flash</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,d5f57990-f616-4c24-b7d3-3972237cc2ca.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/fg-QCJFn05o/PracticalSilverlightMoreThanJustFlash.aspx</link>
      <pubDate>Thu, 15 Jan 2009 22:30:33 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Shaun (my boss) and I are going to be doing a one-day, technically intensive Silverlight&#xD;
event in both Portland (2/12) and Seattle(2/10) next month.  This will be a full&#xD;
day (plus lunch) of in depth, 300-400 level Silverlight content.  Check out our &lt;a href="https://registration.sftsrc.com"&gt;registration&#xD;
site&lt;/a&gt; for full session abstracts and time/place details.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;em&gt;From the event copy…&lt;/em&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;blockquote&gt;&#xD;
          &lt;p&gt;&#xD;
Look past the glitzy, media rich Silverlight demos, to the reality of writing browser-hosted,&#xD;
business-oriented applications. Learn how to leverage your .NET expertise and see&#xD;
how Silverlight can provide your organization with a powerful platform for building&#xD;
web-delivered solutions.&#xD;
&lt;/p&gt;&#xD;
        &lt;/blockquote&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=FCjG6B6V"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=PFeVQHum"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=U4s9FcLh"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=XrT4LmVQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=ZhmyNjPq"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=ZhmyNjPq" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=HXE5i57u"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=HXE5i57u" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,d5f57990-f616-4c24-b7d3-3972237cc2ca.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/PracticalSilverlightMoreThanJustFlash.aspx</feedburner:origLink></item>
    <item>
      <trackback:ping>http://www.cauldwell.net/patrick/blog/Trackback.aspx?guid=afad6c31-2670-4363-bdd5-5524662bc9fd</trackback:ping>
      <pingback:server>http://www.cauldwell.net/patrick/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.cauldwell.net/patrick/blog/PermaLink,guid,afad6c31-2670-4363-bdd5-5524662bc9fd.aspx</pingback:target>
      <dc:creator>Patrick Cauldwell</dc:creator>
      <wfw:comment>http://www.cauldwell.net/patrick/blog/CommentView,guid,afad6c31-2670-4363-bdd5-5524662bc9fd.aspx</wfw:comment>
      <wfw:commentRss>http://www.cauldwell.net/patrick/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=afad6c31-2670-4363-bdd5-5524662bc9fd</wfw:commentRss>
      
      <title>Upcoming classes</title>
      <guid isPermaLink="false">http://www.cauldwell.net/patrick/blog/PermaLink,guid,afad6c31-2670-4363-bdd5-5524662bc9fd.aspx</guid>
      <link>http://feedproxy.google.com/~r/PatrickCauldwellsBlog/~3/bRBK5fMv-LQ/UpcomingClasses.aspx</link>
      <pubDate>Tue, 06 Jan 2009 00:18:30 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
We’ll be teaching several classes on the West side in the next few months, including&#xD;
C#/.NET and Practical .NET Debugging.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The C#/.NET class covers the new features in VS 2008/C# 3.0, including LINQ, automatic&#xD;
properties, the new initializer syntax and the &lt;em&gt;var&lt;/em&gt; type, as well as the rest&#xD;
of C# and a solid foundation in .NET 3.5 including XML processing, threading, App&#xD;
Domains, etc.  &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The Practical .NET Debugging class covers real-world debugging techniques for .NET&#xD;
including the VS 2008 debugger and using WinDbg on .NET code from a practical perspective.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
For scheduling details or to register, see our &lt;a href="http://www.sftsrc.com/SoftSource_Training.aspx"&gt;training&lt;/a&gt; site.&#xD;
&lt;/p&gt;&#xD;
        &lt;br&gt;&#xD;
        &lt;hr&gt;&lt;/hr&gt;&#xD;
The posts on this weblog are provided AS IS with no warranties, and confer no rights.&#xD;
The opinions expressed herein are my own personal opinions and do not represent my&#xD;
employer's view in any way.&lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=N6gAff9E"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=iL24IA1H"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=YJoNFvf5"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=45" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=S2bpwnSF"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?d=42" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=RhzkTd2F"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=RhzkTd2F" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?a=Z2yMXX1W"&gt;&lt;img src="http://feeds.feedburner.com/~f/PatrickCauldwellsBlog?i=Z2yMXX1W" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.cauldwell.net/patrick/blog/CommentView,guid,afad6c31-2670-4363-bdd5-5524662bc9fd.aspx</comments>
    <feedburner:origLink>http://www.cauldwell.net/patrick/blog/UpcomingClasses.aspx</feedburner:origLink></item>
  </channel>
</rss>
