<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;CEQNQng5eCp7ImA9WxNUGEQ.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789</id><updated>2009-11-10T14:33:13.620-08:00</updated><title>Confessions of a Would-Be Theologian</title><subtitle type="html">Musings on theology, technology, family and whatever strikes my interest, from a onetime theologian and occasional CTO.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>233</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/ConfessionsOfAWould-beTheologian" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;D0AMQno8fCp7ImA9WxNUF0k.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-46067780650097642</id><published>2009-11-08T21:48:00.001-08:00</published><updated>2009-11-08T21:49:43.474-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-08T21:49:43.474-08:00</app:edited><title>Bedtime Routine</title><content type="html">&lt;p&gt;Back at the beginning of September, Caedmon finally figured out how to climb out of his crib, and how to turn the light on in his room.&amp;#160; We tried very hard for several nights to get him to stay in bed on his own, but we eventually gave up.&amp;#160; Ever since, every night, our routine has been like this: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Give him a bath and brush his teeth.&lt;/li&gt;    &lt;li&gt;Read three stories together.&lt;/li&gt;    &lt;li&gt;Give him half an hour to play quietly in his room.&lt;/li&gt;    &lt;li&gt;Tuck him in, pray together, and turn off the light.&lt;/li&gt;    &lt;li&gt;Wait outside the room (at most 30 seconds) before he's up and turning on the light or opening the door.&lt;/li&gt;    &lt;li&gt;Remove the lightbulb, and lock his door.&lt;/li&gt;    &lt;li&gt;Wait for the screaming to die down. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For the last week or so, we've been talking about trying something different – partly because we're tired of the fight, but also because we don't like having to resort to a physical restraint, like a lock.&amp;#160; We'd rather that he be able to control himself, well, by himself. &lt;/p&gt;  &lt;p&gt;So this afternoon, we explained to Caedmon that we'd be doing something different tonight.&amp;#160; We had four new bedtime rules: (1) Stay in bed; (2) close your eyes; (3) stay quiet; (4) put your head on your pillow.&amp;#160; We gave him hand motions for each of the rules, and rehearsed them with him repeatedly throughout the afternoon and evening.&amp;#160; We also explained that if he got up out of bed, we would immediately put him back to bed, without looking at him, and without saying anything. &lt;/p&gt;  &lt;p&gt;So Galena drew the short straw tonight.&amp;#160; Everything went well, up to the point where she turned off the light, left the room and closed the door.&amp;#160; &lt;/p&gt;  &lt;p&gt;At about the half hour mark, I came up to see how things were going.&amp;#160; She was standing outside the door with her teeth clenched.&amp;#160; In-between missions, she said, “Thirty-three.”&amp;#160; The door opened again, she disappeared inside, then re-emerged.&amp;#160; “Thirty-four.” The door opened again, and she disappeared once more. “Thirty-five,” she said when she came out. &lt;/p&gt;  &lt;p&gt;I came back about half an hour later.&amp;#160; She was still standing outside the door, teeth still clenched, but she had removed her sweater and her arms were bare.&amp;#160; “One hundred thirty.”&amp;#160; “One hundred thirty-one.”&amp;#160; “One hundred thirty-two.” &lt;/p&gt;  &lt;p&gt;Somewhere around 150, I could hear Caedmon's giggles switch to crying. &lt;/p&gt;  &lt;p&gt;I popped my head into the hallway a bit later.&amp;#160; “One hundred sixty-two,” she said, but there was triumph in her eyes.&amp;#160; From within his room, I could hear Caedmon screaming, “No, Mom! No! Go away! Daddy! Daaaaddy!&amp;quot;&amp;#160; The door opened again, and in she went.&lt;/p&gt;  &lt;p&gt;Caedmon is now asleep.&amp;#160; Galena had to put him back in bed 169 times before he finally stayed. &lt;/p&gt;  &lt;p&gt;It's my night tomorrow.&amp;#160; Pray for me.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-46067780650097642?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/46067780650097642/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=46067780650097642" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/46067780650097642?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/46067780650097642?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/11/bedtime-routine.html" title="Bedtime Routine" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkAEQ3k6fyp7ImA9WxNXFE8.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-8991200005402823497</id><published>2009-10-01T11:11:00.001-07:00</published><updated>2009-10-01T11:11:42.717-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-01T11:11:42.717-07:00</app:edited><title>Really Missing Serialization Callbacks</title><content type="html">&lt;p&gt;I just ran into another feature whose absence from Silverlight is sorely missed.&lt;/p&gt;  &lt;p&gt;I’m using the WCF generated proxy classes as the basis for binding to some UI objects.&amp;#160; If you’re using a full MVVM pattern, the way that you’d normally do this is wrap the proxy-generated classes with a ViewModel, so that instead of binding to, say, the User class generated by “Add Service Reference”, you’d bind to a UserViewModel class that acts as a facade for the User class.&amp;#160; So far, I haven’t been willing to go that route.&amp;#160; The only point to having a ViewModel is if you’re making extensive use of databinding, and databinding happens to be my &lt;a href="http://blog.wouldbetheologian.com/2009/07/why-wpf-databinding-is-awful-technology.html"&gt;least favorite&lt;/a&gt; Silverlight technology, for reasons that I’ve explained &lt;a href="http://blog.wouldbetheologian.com/2009/09/mixed-feelings-about-silverlight.html"&gt;elsewhere&lt;/a&gt;.&amp;#160; And if I’m only doing databinding occasionally, it seems like a lot of more-or-less pointless work to recreate a facade for my complete object model on the client, and then keep it synchronized with the classes that the Entity Framework has already helpfully generated for me.&amp;#160; So I’ve been making do with partial classes to add any additional properties or methods that seem appropriate.&lt;/p&gt;  &lt;p&gt;But as I said, I ran into a problem today.&amp;#160; One of my classes, SharedFile, has a bindable property called StatusText whose value depends on a complicated graph of other object properties; and to get them all working, I’ve had to string together an unpleasant chain of INotifyPropertyChanged notifications, sorta like so (this is just one of numerous chained handlers):&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.1%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; height: 127px; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; uploadCommand_PropertyChanged(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, System.ComponentModel.PropertyChangedEventArgs e)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (e.PropertyName == &lt;span style="color: #006080"&gt;&amp;quot;State&amp;quot;&lt;/span&gt;)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         UpdateStatusText();&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;OK, so far so good – but I have to wire up these event handlers somewhere.&amp;#160; Since the definition of SharedFile in reference.cs didn’t define a default constructor, I thought it would be simple to create one in my partial class, and that would be the end of it:&lt;/p&gt;

&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.31%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; height: 90px; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; SharedFile()&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.PropertyChanged += SharedFile_PropertyChanged;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;But although the objects get created, that constructor never gets called.&amp;#160; WTF?&amp;#160; Well, it turns out that when Silverlight deserializes the XML from my WCF service, it uses &lt;a href="http://stackoverflow.com/questions/178645/how-does-wcf-deserialization-instantiate-objects-without-calling-a-constructor"&gt;FormatterServices.GetUninitializedObject&lt;/a&gt; to create the object, which skips calling the constructor.&amp;#160; I guess that makes a certain sort of sense – the WCF service is handing you an object that, in theory, is already constructed, so you shouldn’t need to call the constructor again.&amp;#160; I get that.&amp;#160; But then where do I put this code?&lt;/p&gt;

&lt;p&gt;OK, I know, I can put that code in a method that I tag with the [&lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializedattribute.aspx"&gt;OnDeserialized&lt;/a&gt;] attribute.&amp;#160; That’s the normal way of doing it, right?&amp;#160; Oh – except Silverlight doesn’t support &lt;a href="http://msdn.microsoft.com/en-us/library/dd470110(VS.95).aspx"&gt;serialization callbacks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Huh?&lt;/p&gt;

&lt;p&gt;I get that some features need to be left out of Silverlight.&amp;#160; But this seems like a really odd one.&amp;#160; Serializing and deserializing objects is what you do in Silverlight.&amp;#160; You can write real-world WPF or WinForm or ASP.NET applications all day long and never once have to deal with object serialization and deserialization.&amp;#160; But you can’t use Silverlight for five minutes without needing to touch an object that’s just been deserialized from some web service.&amp;#160; So why choose that particular set of features to cut?&amp;#160; It sure seems like a bizarre design choice.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;At any rate, my choices were either to implement a full-blown ViewModel layer, which I really don’t want to do, or write a hack of some sort to initialize the event handlers manually.&amp;#160; Uggh.&lt;/p&gt;

&lt;p&gt;What I’ve done for now is to throw an Initialize() method on the containing object (User), which in turn initializes any object that gets added to its SharedFiles ObservableCollection:&lt;/p&gt;

&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.29%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; height: 386px; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// This is necessary because Silverlight doesn't call a constructor when deserializing classes,&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;// and also doesn't support on the [OnDeserialized] attribute.  Damn annoying.&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Initialize()&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     InitializeSharedFileList(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.SharedFiles);&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     SharedFiles.CollectionChanged += SharedFiles_CollectionChanged;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SharedFiles_CollectionChanged(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (e.Action == NotifyCollectionChangedAction.Add)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         InitializeSharedFileList(e.NewItems);&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; InitializeSharedFileList(IList sharedFileList)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (SharedFile sharedFile &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; sharedFileList)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         sharedFile.Initialize();&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;     }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;And then I call User.Initialize() when I first retrieve it from the web service:&lt;/p&gt;

&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 400px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; User user;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; User User&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     get&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; user;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     set&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;.ReferenceEquals(user, &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;))&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;             user = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (user != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;             {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;                 &lt;font color="#ff0000"&gt;user.Initialize();&lt;/font&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;                 UserId = user.UserId;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;             }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;             {&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;                 UserId = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;             }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     }&lt;/pre&gt;
&lt;!--CRLF--&gt;

    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Like I said, uggh.&amp;#160; But it works.&amp;#160; I just wish that MS had thought through their deserialization scenarios a little better.&amp;#160; I don’t like being forced into creating another abstraction layer if I don’t have to.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-8991200005402823497?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/8991200005402823497/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=8991200005402823497" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8991200005402823497?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8991200005402823497?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/10/really-missing-serialization-callbacks.html" title="Really Missing Serialization Callbacks" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUYDSH4yeyp7ImA9WxNQGEs.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-5304013166589370020</id><published>2009-09-25T01:19:00.000-07:00</published><updated>2009-09-25T01:26:19.093-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-25T01:26:19.093-07:00</app:edited><title>Silverlight duplex client limitation</title><content type="html">I ran into an interesting (and largely irrelevant) limitation today on Silverlight's&amp;nbsp;implementation of duplex web services.&lt;br /&gt;
&lt;br /&gt;
I'd been using Jeff Wilcox's handy&amp;nbsp;&lt;a href="http://code.msdn.microsoft.com/silverlightut/"&gt;Silverlight Unit Test Framework&lt;/a&gt; to test the data access piece of my current 
Silverlight project. However, I was running into a nasty problem that was driving&amp;nbsp;me nuts. Part way through every test run, my unit tests would start failing. I could&amp;nbsp;usually get through something like 10 or so tests before every new WCF call would&amp;nbsp;return "Not Found" (which is not really the most helpful error message Microsoft
ever came up with). It didn't have anything to do with the individual tests themselves,&amp;nbsp;because the error would show up after 10 tests, no matter which 10 tests they were. &amp;nbsp;I'd been working through this error for some time before I realized that the "10"&amp;nbsp;number was undoubtedly significant, since that seems to be the default number of&amp;nbsp;connections that WCF allows, unless you go in and bump it higher. (Now of course,&amp;nbsp;IMO, that's a pretty dumb default: the obvious purpose for leaving it that low is&amp;nbsp;to prevent DOS attacks -- but the net result is that instead of needing some 10,000&amp;nbsp;connections to DOS your server, you only need 10. Sigh.)&lt;br /&gt;
&lt;br /&gt;
This made me think that I might be leaking a connection somewhere. In theory, I&amp;nbsp;was closing all my connections in one test before moving on to another, but we all&amp;nbsp;know how well that works :-).&amp;nbsp; Since I was opening and closing all my connections&amp;nbsp;through the same static class, I wrote up some quick instrumentation, and saw that&amp;nbsp;yeah, one connection was staying open after every test.&amp;nbsp; Some additional poking&amp;nbsp;around, and I found a method that was opening a new connection and failing to close&amp;nbsp;it.&amp;nbsp; Easily fixed.&amp;nbsp; Instead of this final line in my method:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;EnqueueTestComplete();&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
I just made it do this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;EnqueueCallback(() =&amp;gt; DataConnectionManager.TryClientClose(client,
            error =&amp;gt; EnqueueTestComplete()));&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
And TryClientClose() looks something like this:&lt;br /&gt;
&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;        public static void TryClientClose(RoomServiceClient client, OperationCallback callback)
        {
            if (client != null &amp;amp;&amp;amp; client.State == CommunicationState.Opened)
            {
                client.CloseCompleted += (sender, e) =&amp;gt;
                {
                    ClientsClosed++;
                    ClientsOpen--;
                    if (e.Error != null)
                    {
                        client.Abort();
                    }
                    if (callback != null)
                    {
                        callback(e.Error);
                    }
                };
                client.CloseAsync();
            }
            else
            {
                if (callback != null)
                {
                    callback(null);
                }
            }
        }
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Close enough.  But why was I running into this error in the first place?&amp;nbsp; Truth be told, I don't completely know.&amp;nbsp; But my best guess is that the Silverlight client (or maybe the browser that's hosting it) has a limitation on how many duplex callback sessions it can support.&amp;nbsp; And so far as I'm aware, there's no way to increase this number.&amp;nbsp; At least, I've poked around in all the relevant blogs, and looked through the appropriate docs, and can't find anything obvious.&amp;nbsp; But the net result is that you don't want to have more than 10 duplex clients open at the same time on any given Silverlight application.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-5304013166589370020?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/5304013166589370020/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=5304013166589370020" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/5304013166589370020?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/5304013166589370020?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/09/silverlight-duplex-client-limitation.html" title="Silverlight duplex client limitation" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CU8DSXcyfyp7ImA9WxNQFE0.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-5778978909900983925</id><published>2009-09-19T16:37:00.001-07:00</published><updated>2009-09-19T16:44:38.997-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-19T16:44:38.997-07:00</app:edited><title>And Three More Silverlight Complaints</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;&lt;strong&gt;Unhelpful error messages&lt;/strong&gt; rank high on my list of complaints about Silverlight and WPF.  Take this particular error message: AG_E_PARSER_BAD_TYPE.  I get it pretty regularly, but this particular instance started showing up about 15 minutes ago.  The location that it points to (presumably in App.xaml? – it doesn't actually say) has nothing to do with the error in question.  
&lt;/p&gt;&lt;p&gt;&lt;img alt='' src='http://wouldbetheologian.com/images/091909_2337_AndThreeMor1.png'/&gt;
			&lt;/p&gt;&lt;p&gt;The error is presumably triggered by some XAML I screwed up somewhere in one of the 50+ different XAML files in my solution.  I have no idea which file (I just did a big search-and-replace as part of a codebase-wide refactor).  So first of all: AG_E_PARSER_BAD_TYPE?  Since when does that qualify as an error message?  We're not doing sockets programming here, folks.  The CLR allows for an incredibly rich set of exceptions.  So why the incomprehensible error message?  But more to the point, why am I being pointed to the wrong location?  One of the things that makes the Silverlight tools for Visual Studio feel so frustrating is that &lt;em&gt;they know which file is problematic, and they know precisely what the problem is, and they refuse to tell me.&lt;/em&gt;  Yes, I know my reaction makes Silverlight a little more anthropomorphic than necessary.  But it sure as heck feels like the Microsoft tools are out to get me sometimes.  (For what it's worth, after an hour of troubleshooting, I opened the solution in Blend, and for once, Blend gave me what I needed to know, and immediately highlighted the problematic file.)
&lt;/p&gt;&lt;p&gt;My second complaint is &lt;strong&gt;bogus error messages&lt;/strong&gt;, i.e., error messages when there's no error.  Again, to take one example of many, in one particular form in my project, Visual Studio lists 27 different errors, all having to do with certain local controls not being found.
&lt;/p&gt;&lt;p&gt;&lt;img alt='' src='http://wouldbetheologian.com/images/091909_2337_AndThreeMor2.png'/&gt;
			&lt;/p&gt;&lt;p&gt;The assembly in question (SlideLinc.Client.dll) and the associated namespace (SlideLinc.Client) are registered correctly in the form, and indeed, the form loads and executes correctly at runtime.  For once, Blend recognizes this, and doesn't raise any errors.  In other words, there's no problem.  But I've tried six ways from Sunday to make those errors go away in Visual Studio, and nothing has been successful.  In this particular case, it's generally not that problematic – except when it comes time to track down a real error, and you have to fight your way through dozens of bogus error messages to find the right one.  (It's at least a tad ironic that these bogus error messages at least show up at the right time, i.e., when the app is compiling, and are able to point me to exactly the place where they – incorrectly – think the error is occurring.  In contrast, the quite real AG_E_PARSER_BAD_TYPE error that I ran into above showed up way too late, at runtime, and wouldn't even tell me which file it was occurring in.  It's this kind of stuff that makes you pull your hair out – and which has cost me at least a month of troubleshooting on my current project.)
&lt;/p&gt;&lt;p&gt;My third complaint is more specific, and has to do with the &lt;strong&gt;Add Service Reference&lt;/strong&gt; feature in Visual Studio.  Specifically, I run into two reoccurring, distinct, but possibly related bugs when I try to update my service references.  Neither of these occurred with the March 2009 SL3 CTP, and both started showing up immediately after I upgraded to SL3 RTW.
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Periodically (about a third of the time), when I pull open the "Configure Service Reference" dialog box, the "ObservableCollection" option for collection types isn't available; instead, there's something listed called "(Custom)", which is apparently interpreted as "Array[]".  So when it generates your proxy references, it generates any list of values as an array, rather than an ObservableCollection.  This breaks all your existing code, which of course was written to expect an ObservableCollection in those instances.  What usually fixes it for me is simply restarting Visual Studio.  Nothing else seems to work.  &lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;The second problem is that periodically the Reference.cs file fails to generate – which of course also breaks all your existing code.  I ran into a tip from someone, somewhere, who recommended deselecting the option "Reuse types in specified referenced assemblies", and then select only "System.Core".  When I do this, and then I update my service reference, it seems to fix this pretty reliably.  Sometimes it happens anyway, at which point in time I simply change which referenced assemblies it should try to reuse, and then immediately everything works again.
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;On this last point, I should note that lots of other folks besides me have been running into these issues.  Indeed, I don't know anybody who regularly works with Silverlight and WCF who &lt;em&gt;hasn't&lt;/em&gt; run into them.  It's also been quite well-documented on the &lt;a href='http://forums.silverlight.net/forums/p/91817/288677.aspx'&gt;forums&lt;/a&gt;.  I've tried to report these bugs on the &lt;a href='https://connect.microsoft.com/directory/'&gt;MS Connect&lt;/a&gt; website, but I can't figure out how: I don't seem to have that option.
&lt;/p&gt;&lt;p&gt;I should note that the Silverlight runtime itself seems to be pretty darned stable, all things considered.  I've beat the thing to death with stress tests, and haven't run across any bugs worth mentioning that weren't my own damned fault.  All the real problems seem to show up in the various tools you use to &lt;em&gt;build&lt;/em&gt; Silverlight applications.
&lt;/p&gt;&lt;p&gt;It seems to me that there are going to be some massive improvements to the .NET platform coming with the impending .NET 4.0 / Visual Studio 2010 release.  I keep hoping that the reason these bugs haven't been fixed out in the wild is that MS is working so hard to improve the quality of that upcoming release. 
&lt;/p&gt;&lt;p&gt;I can hope, can't I?&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-5778978909900983925?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/5778978909900983925/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=5778978909900983925" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/5778978909900983925?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/5778978909900983925?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/09/and-three-more-silverlight-complaints.html" title="And Three More Silverlight Complaints" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEUGQn47cSp7ImA9WxNQE04.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-8638041734373203632</id><published>2009-09-18T12:05:00.001-07:00</published><updated>2009-09-18T20:50:23.009-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-18T20:50:23.009-07:00</app:edited><title>Mixed Feelings about Silverlight</title><content type="html">&lt;span xmlns=""&gt;&lt;p&gt;I spent all day yesterday at the Microsoft Silverlight FireStarter event.  (You can see the decks &lt;a href="http://blogs.msdn.com/mithund/archive/2009/09/17/silverlight-3-firestarter-slides.aspx"&gt;here&lt;/a&gt;, and the recordings will be up shortly.)  It was an appropriate place for me to be hanging out, since Alanta, my current startup, is working to build a web conferencing system on Silverlight.  I came away from the day with a variety of mixed feelings.
&lt;/p&gt;&lt;p&gt;First, I realized that not only do I have a lot to learn, but what I don't know is hurting me.  If I knew the tools and frameworks better, I could make a &lt;em&gt;lot&lt;/em&gt; faster progress on our product, and the resulting code would be better architected and more maintainable.  The &lt;a href="http://www.slideshare.net/mithund/4silverlight-firestarterexpressionblendadamkinney"&gt;demo&lt;/a&gt; that &lt;a href="http://www.adamkinney.com/"&gt;Adam Kinney&lt;/a&gt; did on Blend made me realize just how crappy my own Blend skills are, and how I could be a ton more productive if I knew Blend better.  Similarly, the stuff that &lt;a href="http://blogs.msdn.com/matos/"&gt;Marco Matos&lt;/a&gt; did with the &lt;a href="http://www.slideshare.net/mithund/7silverlightfirestartertoolkit-and-controls-marco-matos"&gt;Silverlight Toolkit&lt;/a&gt;, and &lt;a href="http://karlshifflett.wordpress.com/"&gt;Karl Shifflet's&lt;/a&gt; &lt;a href="http://www.slideshare.net/mithund/silverlightfirestarterxaml-power-toys-v5karlshifflett"&gt;demo&lt;/a&gt; of his XAML PowerToys.
&lt;/p&gt;&lt;p&gt;I also felt grateful to Microsoft (in general) and to the people who put on the event (very specifically).  They've pretty much dedicated their lives to creating tools and frameworks and platforms for the rest of us to use, to make our lives easier or better in some way.  And when, like me, you spend more than half your waking hours working with those particular tools and frameworks and platforms, that's not something you can just take for granted.  It's something to be thankful for.
&lt;/p&gt;&lt;p&gt;At the same time, I think I spent more time at the event feeling frustrated than anything else.  I've said before that you know a product is succeeding when people start complaining about it; and by that standard, Silverlight is a very successful product.  Here are my top three complaints about the current state of Silverlight and its tools:
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Silverlight databinding is a mess&lt;/strong&gt;.  This is partly due to the fact that it is missing many of the features of its more powerful cousin, WPF databinding.  But databinding in both Silverlight and WPF suffer from the same underlying problem: it's incredibly difficult to get right, very easy to get wrong, and MS provides provides no troubleshooting help at all.  As I've said elsewhere (&lt;a href="http://blog.wouldbetheologian.com/2009/07/why-wpf-databinding-is-awful-technology.html"&gt;here&lt;/a&gt; and &lt;a href="http://stackoverflow.com/questions/1197054/strongly-typed-databinding-in-wpf-silverlight-xaml/1218347"&gt;here&lt;/a&gt;), I think the biggest underlying problem with the current databinding implementation is that it's untyped, i.e., you never specify the type of the DataContext your XAML is expecting.  As a result, there's no Intellisense to help you when you define your bindings, and no design-time or compile-time checking to make sure you got them right.  I could probably live with this limitation if Microsoft provided better tools and frameworks for runtime troubleshooting.  But at runtime, any binding errors get swallowed entirely and completely.  A very few of them will show up in the Visual Studio debug window, but you have absolutely no insight into the vast majority of things that might go wrong.  Even if MS thought that it was too big of a switch to move to a strongly-typed DataContext, they should at the very least, for the sake of all that is holy, have their controls raise an event when something goes wrong, so that you have some opportunity to see and respond to what might be happening.  I can't express strongly enough how absolutely insane it is that we're about to see version 4 of Silverlight, and Microsoft still hasn't fixed this basic, fundamental problem.  I spend enormous amounts of time troubleshooting databindings, and it's the primary reason why we've only partially adopted an MVVM architecture for Alanta.  I spend enough of my time troubleshooting WCF, which is complicated and annoying, but at least it provides real errors.  There's not enough time in the day to guess (and guess and guess and guess again) what might be going wrong with my databindings.

    &lt;br /&gt;
    &lt;br /&gt;
    I should note that &lt;a href="http://timheuer.com/blog/"&gt;Tim Heuer&lt;/a&gt;, frequently the face of Silverlight to the world, was able to sympathize with these problems yesterday.  He pointed me &lt;a href="http://karlshifflett.wordpress.com/2009/06/08/glimpse-for-silverlight-viewing-exceptions-and-binding-errors/"&gt;Glimpse&lt;/a&gt;, a recent tool from Karl Shifflett, that provides some insight into what's happening under the hood with databinding errors.  I haven't had the chance to try it out yet, but it seems like a step in the right direction.  Still, "not sucking quite so horribly" doesn't equal "sufficient", least of all "good".

    &lt;br /&gt;
    &lt;br /&gt;
        Microsoft and the rest of the community is making a huge push towards MVVM as the standard development model for Silverlight and WPF.  That makes sense: but its adoption by average, everyday developers will remain limited until MS is able to fix their databinding experience.
    &lt;br /&gt;
    &lt;br /&gt;

   &lt;/li&gt;
&lt;li&gt;&lt;div&gt;&lt;strong&gt;Blend is a mess&lt;/strong&gt;.  Yes, it's incredibly powerful.  And yes, V3 is much, much better than V2.  And it goes without saying that it's better than Visual Studio for UI design.  But as the premiere MS tool for designing great user experiences, it shows an astonishing lack of appreciation of what makes for a great user experience.  To take just a couple examples:

    &lt;br /&gt;

    &lt;/div&gt;&lt;ol&gt;&lt;li&gt;In the picture below, try to guess which of the two tabs ("FileRowControl" or "FileManagerControl") is selected.  Is it the one on the left whose bold, dark color seems to flow uninterrupted into the workspace?  Or is it the one on the right whose light gray color, everywhere else in the Windows UI, indicates "disabled"?  Astonishingly, it's the tab on the right that's selected.  I've been working with Blend for months now, and every time I have to look at the open file tabs, I have to stop and think which one is actually selected.  That's inexcusable for a company with as many design resources as Microsoft.&lt;br /&gt;
&amp;nbsp;&lt;img alt="" src="http://wouldbetheologian.com/images/091809_1905_MixedFeelin1.png" /&gt;
        &lt;br /&gt;

     &lt;/li&gt;&lt;li&gt;Here's a fairly standard property panel in Blend:&lt;br /&gt;
&amp;nbsp;&lt;img alt="" src="http://wouldbetheologian.com/images/091809_1905_MixedFeelin2.png" /&gt;
            &lt;br /&gt;
Now, somewhere in this panel is a way to set these properties in an advanced fashion, i.e., through databinding or other similar techniques.  Care to hazard a guess as to how you do that?  Might one, perhaps, right-click and see some options for doing so?  Nope, no right-click menu is available.  Give up?  Well, I'm astonished that you missed the tiny little two-pixel squares to the right of every property.  It turns out that if you navigate your mouse over one, and after two or three tries manage to click on it successfully, it pops up this context menu:&lt;br /&gt;
&amp;nbsp;&lt;img alt="" src="http://wouldbetheologian.com/images/091809_1905_MixedFeelin3.png" /&gt;
            &lt;br /&gt;
This is such a non-standard user experience that there isn't even a name for it.  (Adam Kinney has suggested calling it a &lt;a href="http://www.adamkinney.com/Blog/What-do-you-call-that-small-white-square-icon-in-Expression-Blend"&gt;Property Peg&lt;/a&gt;.)  But there's a darned good reason there isn't a name for it.  It's because it's a bad idea!  It's a horrible UX design.  How more completely unintuitive and non-discoverable is it possible to get?  (That's apart from the fact that because the, umm, peg is so small, even once you figure out what it's there for, it's &lt;em&gt;still&lt;/em&gt; hard to use.)

            &lt;br /&gt;

            &lt;br /&gt;

     &lt;/li&gt;
&lt;li&gt;In every other Windows application, scrolling your mouse wheel moves the selected document up or down.  In Blend, scrolling your mouse wheel sets the zoom level on your current workspace.  That wouldn't be so bad if it made a better guess about where you were aiming.  For instance, here's what my screen looks like after I open up a specific user control I've been working on lately:&lt;br /&gt;
&amp;nbsp;&lt;img alt="" src="http://wouldbetheologian.com/images/091809_1905_MixedFeelin4.png" /&gt;

    &lt;br /&gt;

And here's my screen after four "zoom in" mouse-wheel movements:&lt;br /&gt;
    &lt;br /&gt;
&amp;nbsp;&lt;img alt="" src="http://wouldbetheologian.com/images/091809_1905_MixedFeelin5.png" /&gt;

    &lt;br /&gt;

Rather than zooming in on anything that I might be interested in (say, the selected object), Blend has helpfully chosen to move my control entirely off the screen.  And what's worse, it seems bloody well determined to be random about the direction it moves it.  Sometimes it moves it off my screen up and to the right, sometimes down and to the left, and occasionally, very occasionally, it decides to actually zoom in on the thing I'm interested in.  Taken all together, though, it's as if Blend is determined to take my mouse wheel, one of the very best usability inventions ever, and make it entirely useless.

    &lt;br /&gt;
    &lt;br /&gt;
    I could go on for quite a while about Blend's failings: these are only a couple of random examples.  But they should be sufficient to demonstrate that Blend desperately needs some UX TLC.
    &lt;br /&gt;
    &lt;br /&gt;

     &lt;/li&gt;
    &lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;Silverlight is still missing some very basic features.  The one that's usually brought up is the lack of printing support, which is laughable, if you think about it very long at all.  Given the project I'm currently working on (web conferencing), the feature that I miss the most is obviously web camera and microphone support.  Flash has supported web cameras and microphones for years, so it was very disappointing to me that this feature got cut from Silverlight 3.  From the knowing and slightly embarrassed looks that I see on Microsoft faces whenever the subject gets brought up, I'm pretty sure that it'll make it into Silverlight 4.  But still.  Of the six months that I've spent working on Alanta, at least a month out of that time has gone to troubleshooting the &lt;a href="http://michaelsync.net/2008/07/25/silverlight-and-flash-interoperability-using-html-bridge-and-externalinterface-api-by-jonas-folles%C3%B8"&gt;clever but ultimately painful Flash hack&lt;/a&gt; that we're currently using.

        &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p&gt;
        I feel the need to repeat what I said earlier: you know a product is being successful
        when people start complaining about it. They complain – &lt;em&gt;I&lt;/em&gt; complain – because
        I can see the potential for the product, and get frustrated because it's not there
        yet. I'm also a developer, and know how hard it is to get these things right. The
        folks at MS are only human. But I also hope that they're listening.&lt;/p&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-8638041734373203632?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/8638041734373203632/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=8638041734373203632" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8638041734373203632?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8638041734373203632?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/09/mixed-feelings-about-silverlight.html" title="Mixed Feelings about Silverlight" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A04HQHsycCp7ImA9WxJaGUg.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-3766270372264900247</id><published>2009-08-10T20:05:00.001-07:00</published><updated>2009-08-10T20:05:31.598-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-10T20:05:31.598-07:00</app:edited><title>Clearing event handlers implemented with lambda expressions</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;One of the niceties included with C# 3.0 is lambda expressions, a concise syntax for implementing anonymous methods.  Lambda expressions can be over-used, but they're very handy for certain kinds of things, like defining how asynchronous callbacks should be handled, all within a single method.
&lt;/p&gt;&lt;p&gt;Lambda expressions are also very handy for implementing event handlers.  For instance, if you've got an AlarmClock class that looks like this:
&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:638px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;
										&lt;span style='color:blue'&gt;class&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt;
										&lt;br/&gt;    {&lt;br/&gt;
										&lt;span style='color:blue'&gt;public&lt;/span&gt;
										&lt;span style='color:blue'&gt;event&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;&amp;gt; Alarm;&lt;br/&gt;
										&lt;span style='color:blue'&gt;public&lt;/span&gt;
										&lt;span style='color:blue'&gt;void&lt;/span&gt; SoundAlarm()&lt;br/&gt;        {&lt;br/&gt;
										&lt;span style='color:blue'&gt;if&lt;/span&gt; (Alarm != &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br/&gt;            {&lt;br/&gt;                Alarm(&lt;span style='color:blue'&gt;this&lt;/span&gt;, &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;());&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt; You would normally assign and implement an event-handler like this, with a separate defined method:
&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:638px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;
										&lt;span style='color:blue'&gt;class&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;Program&lt;br/&gt;&lt;/span&gt;    {&lt;br/&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;void&lt;/span&gt; Main()&lt;br/&gt;        {&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt; clock = &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt;();&lt;br/&gt;
										&lt;strong&gt;clock.Alarm += &lt;span style='color:blue'&gt;new&lt;/span&gt;
											&lt;span style='color:#2b91af'&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;&amp;gt;(clock_Alarm);&lt;/strong&gt;&lt;br/&gt;            clock.SoundAlarm();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;
											&lt;span style='color:blue'&gt;static&lt;/span&gt;
											&lt;span style='color:blue'&gt;void&lt;/span&gt; clock_Alarm(&lt;span style='color:blue'&gt;object&lt;/span&gt; sender, &lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt; e)&lt;br/&gt;        {&lt;br/&gt;
											&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"The alarm went off at {0}."&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;DateTime&lt;/span&gt;.Now);&lt;br/&gt;        }&lt;/strong&gt;&lt;br/&gt;    }&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;But with lambda expressions, you can do it like this, all in one method:
&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:638px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;class&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;Program&lt;br/&gt;&lt;/span&gt;{&lt;br/&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;void&lt;/span&gt; Main()&lt;br/&gt;    {&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt; clock = &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt;();&lt;br/&gt;
										&lt;strong&gt;clock.Alarm += (s, e) =&amp;gt; &lt;br/&gt;
											&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"The alarm went off at {0}."&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;DateTime&lt;/span&gt;.Now);&lt;/strong&gt;&lt;br/&gt;        clock.SoundAlarm();&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Most folks would agree that this looks cleaner, and is easier to follow.  (At least, once you get the hang of lambda expressions, which admittedly have a rather odd syntax.)
&lt;/p&gt;&lt;p&gt;The one time this doesn't work is when you need to be able to clear event handlers as well as assign them.  The way that you normally do this is so:
&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:638px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&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;void&lt;/span&gt; Main()&lt;br/&gt;{&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt; clock = &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt;();&lt;br/&gt;    clock.Alarm += &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;&amp;gt;(clock_Alarm);&lt;br/&gt;    clock.SoundAlarm();&lt;br/&gt;
										&lt;strong&gt;clock.Alarm -= &lt;span style='color:blue'&gt;new&lt;/span&gt;
											&lt;span style='color:#2b91af'&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;&amp;gt;(clock_Alarm);&lt;/strong&gt;&lt;br/&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;But you can't do that with the lambda expression I used above, because you don't have any way to identify the lambda expression that you want to remove.  I've seen a variety of folks asking questions about how to clear event handlers implemented as lambda expressions for this very reason.  
&lt;/p&gt;&lt;p&gt;It turns out that there are (at least) two ways to do it.
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;If you've got access to the source code for the class in question, you can write a public ClearEventHandlers() method that works like so:
&lt;/li&gt;&lt;/ol&gt;&lt;div style='margin-left: 18pt'&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:614px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;
										&lt;span style='color:blue'&gt;class&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt;
										&lt;br/&gt;    {&lt;br/&gt;
										&lt;span style='color:blue'&gt;public&lt;/span&gt;
										&lt;span style='color:blue'&gt;event&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;&amp;gt; Alarm;&lt;br/&gt;
										&lt;span style='color:blue'&gt;public&lt;/span&gt;
										&lt;span style='color:blue'&gt;void&lt;/span&gt; SoundAlarm()&lt;br/&gt;        {&lt;br/&gt;
										&lt;span style='color:blue'&gt;if&lt;/span&gt; (Alarm != &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br/&gt;            {&lt;br/&gt;                Alarm(&lt;span style='color:blue'&gt;this&lt;/span&gt;, &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;());&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;strong&gt;
											&lt;span style='color:blue'&gt;public&lt;/span&gt;
											&lt;span style='color:blue'&gt;void&lt;/span&gt; ClearEventHandlers()&lt;br/&gt;        {&lt;br/&gt;            Alarm = &lt;span style='color:blue'&gt;null&lt;/span&gt;;&lt;br/&gt;        }&lt;/strong&gt;&lt;br/&gt;    }&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p style='margin-left: 18pt'&gt;
 &lt;/p&gt;&lt;ol&gt;&lt;li&gt;But if you need more granularity, or don't have access to the source, you can assign the lambda expression to a variable (e.g., "handleAlarm") before you assign it as an event-handler, like so:
&lt;/li&gt;&lt;/ol&gt;&lt;div style='margin-left: 36pt'&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:590px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&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;void&lt;/span&gt; Main()&lt;br/&gt;{&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt; clock = &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt;();&lt;br/&gt;&lt;strong&gt;
											&lt;span style='color:#2b91af'&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;&amp;gt; handleAlarm = &lt;span style='color:blue'&gt;null&lt;/span&gt;;&lt;br/&gt;    handleAlarm = (s, e) =&amp;gt;&lt;br/&gt;        {&lt;br/&gt;            clock.Alarm -= handleAlarm;&lt;br/&gt;
										&lt;/strong&gt;&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"The alarm went off at {0}."&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;DateTime&lt;/span&gt;.Now);&lt;strong&gt;&lt;br/&gt;        };&lt;br/&gt;    clock.Alarm += handleAlarm;&lt;/strong&gt;&lt;br/&gt;    clock.SoundAlarm();&lt;br/&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p style='margin-left: 36pt'&gt;&lt;br/&gt;Note that you need to assign the handleAlarm variable to &lt;span style='color:blue; font-family:Courier New; font-size:10pt'&gt;null&lt;/span&gt; first, because otherwise the compiler complains about the first line of the lambda expression: it thinks that you're trying to muck about with an uninitialized variable.  This is only sort of true, but to work around it, just assign the variable to &lt;span style='color:blue; font-family:Courier New; font-size:10pt'&gt;null&lt;/span&gt; when you declare it.
&lt;/p&gt;&lt;p&gt;The syntax for #2 is a bit unwieldy, but it can let you do things that would be difficult or complicated if you had to use a second method.  For instance, within lambda expressions you can use local variables declared at the level of the containing function:
&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:638px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&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;void&lt;/span&gt; Main()&lt;br/&gt;{&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt; clock = &lt;span style='color:blue'&gt;new&lt;/span&gt;
										&lt;span style='color:#2b91af'&gt;AlarmClock&lt;/span&gt;();&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;EventArgs&lt;/span&gt;&amp;gt; handleAlarm = &lt;span style='color:blue'&gt;null&lt;/span&gt;;&lt;br/&gt;
										&lt;strong&gt;&lt;span style='color:#2b91af'&gt;ManualResetEvent&lt;/span&gt; resetEvent = &lt;span style='color:blue'&gt;new&lt;/span&gt;
											&lt;span style='color:#2b91af'&gt;ManualResetEvent&lt;/span&gt;(&lt;span style='color:blue'&gt;false&lt;/span&gt;);&lt;br/&gt;
											&lt;span style='color:blue'&gt;bool&lt;/span&gt; alarmSounded = &lt;span style='color:blue'&gt;false&lt;/span&gt;;&lt;/strong&gt;&lt;br/&gt;    handleAlarm = (s, e) =&amp;gt;&lt;br/&gt;        {&lt;br/&gt;            clock.Alarm -= handleAlarm;&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"The alarm went off at {0}."&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;DateTime&lt;/span&gt;.Now);&lt;br/&gt;
										&lt;strong&gt;alarmSounded = &lt;span style='color:blue'&gt;true&lt;/span&gt;;&lt;br/&gt;            resetEvent.Set();&lt;/strong&gt;&lt;br/&gt;        };&lt;br/&gt;    clock.Alarm += handleAlarm;&lt;br/&gt;    clock.SoundAlarm();&lt;br/&gt;
										&lt;strong&gt;resetEvent.WaitOne(5000);&lt;br/&gt;&lt;/strong&gt;
										&lt;span style='color:blue'&gt;if&lt;/span&gt; (!&lt;strong&gt;alarmSounded&lt;/strong&gt;)&lt;br/&gt;    {&lt;br/&gt;
										&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"The alarm didn't sound within the timeout period."&lt;/span&gt;);&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt; 
 &lt;/p&gt;&lt;p&gt;To duplicate this without lambda expressions, you'd have to declare the &lt;span style='font-family:Courier New; font-size:10pt'&gt;resetEvent&lt;/span&gt; and &lt;span style='font-family:Courier New; font-size:10pt'&gt;alarmSounded&lt;/span&gt; variables at the class level, which isn't nearly as clean, and could lead to some odd bugs if other methods were trying to use those same variables simultaneously.
&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-3766270372264900247?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/3766270372264900247/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=3766270372264900247" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/3766270372264900247?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/3766270372264900247?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/08/clearing-event-handlers-implemented.html" title="Clearing event handlers implemented with lambda expressions" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUcAQ3k-fip7ImA9WxJaGU8.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-1759213853157154902</id><published>2009-08-10T09:49:00.001-07:00</published><updated>2009-08-10T10:57:22.756-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-10T10:57:22.756-07:00</app:edited><title>Windows 7: Not Terribly Impressed</title><content type="html">&lt;span xmlns=""&gt;&lt;p&gt;Windows Vista was never as bad as its &lt;a href="http://blog.wouldbetheologian.com/2007/08/again-missing-point-on-vista.html"&gt;reputation&lt;/a&gt;; and Windows 7 is not as good as everyone claims.  It's not bad, but it still needs some work.  And I dislike some of the design decisions.
&lt;/p&gt;&lt;p&gt;Here are a few snippets from my own experience:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Something is wrong with the graphics drivers or graphics subsystem.  Applications that worked fine under Vista keep "flickering" in Windows 7.  And my Chrome browser keeps displaying a weird sort of static when it opens a new page, sometimes just for a quarter-second, sometimes permanently.  Perhaps this is just a case of a bad video driver (I'm running an NVIDA GeForce 8800 GT), but I've installed the latest Windows 7-optimized driver, and it's still happening.

   &lt;/li&gt;&lt;li&gt;I've had two different blue-screens in my 48 hours of running Windows 7 RTM.  Not a reassuring way to start a new relationship.
   &lt;/li&gt;&lt;/ul&gt;&lt;div style="margin-left: 36pt"&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:590px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt"&gt;&lt;p&gt;&lt;span style="font-family:Segoe UI;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;The computer has rebooted from a bugcheck.  The bugcheck was: 0x0000001a (0x00001236, 0x878be008, 0x878be08c, 0x00070054). A dump was saved in: C:\Windows\MEMORY.DMP. Report Id: 081009-37970-01.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Segoe UI;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;The computer has rebooted from a bugcheck.  The bugcheck was: 0x0000008e (0xc0000005, 0x8c28b885, 0xb062b750, 0x00000000). A dump was saved in: C:\Windows\MEMORY.DMP. Report Id: 081009-30061-01.&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;If you turn off UAC (you pretty much have to, unless you're the sort of person who shops &lt;a href="https://www.bondage.com/bdn/splash.aspx"&gt;here&lt;/a&gt;), the UI gives you the impression that it's taken effect right away – and some parts of it have.  But you have to restart your machine to actually be able to launch everything as an Administrator.  This is no different from Vista, except that the UI is more honest in Vista, and tells you that you need to reboot.

   &lt;/li&gt;&lt;li&gt;I dislike the new metaphor for "pinning" applications to the taskbar.  Among other things, it means that if I have multiple instances of an application open, I have to click twice to switch to the right one, rather than just once.
&lt;img alt="" src="http://wouldbetheologian.com/images/081009_1649_Windows7Not1.png" /&gt;

It's also much more difficult and confusing to tell at a glance &lt;em&gt;if&lt;/em&gt; something is open.  I don't get why MS thought that clicking twice is better than clicking once.  Luckily, you can turn this behavior off; but it's still an odd default.

   &lt;/li&gt;&lt;li&gt;I don't get the new file manager.  It lists very prominently a whole bunch of shortcuts that I've never found useful, and hides the thing I actually &lt;em&gt;do&lt;/em&gt; want to use, a direct tree view into my file system.  On top of that, it doesn't synchronize the tree view with where I've navigated to in the file system.  So the tree view can be sitting at C:\, long after I've navigated to, say, C:\source\slidelinc\branches\98a_SlideLincClient_ken.  This last is a behavior that you can change if you know where to look, but it's a rather weird and unpleasant default.
&lt;img alt="" src="http://wouldbetheologian.com/images/081009_1649_Windows7Not2.png" /&gt;
   &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Again, none of these things are killers, and maybe some people will like the new UI and its associated defaults.  On the whole, Windows 7 is OK, though not terribly impressive.  It feels to me like a not-very-ambitious bug-fix to Vista.  I'll run it.  But I continue to wish that MS could be more successful at their core operating system business.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-1759213853157154902?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/1759213853157154902/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=1759213853157154902" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/1759213853157154902?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/1759213853157154902?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/08/windows-7-not-terribly-impressed.html" title="Windows 7: Not Terribly Impressed" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0UERHc8cCp7ImA9WxNVE04.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-6717650555355140819</id><published>2009-07-27T14:00:00.001-07:00</published><updated>2009-10-23T13:53:25.978-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-23T13:53:25.978-07:00</app:edited><title>Why WPF databinding is an awful technology</title><content type="html">[Edited 10/23/09: I wrote this blog post when I was in a pissy mood, because I'd just wasted a day trying to get some WPF databindings to work.  I still agree with my critiques of WPF/Silverlight databinding, and I think that MS really needs to rethink some aspects of their databinding implementation, especially their failure to implement a strongly typed DataContext. Still, if I were to write this post now, I'd be less inflammatory, especially in my opening paragraphs.  Just to put it in perspective.  But on to the original post . . . ]
&lt;br /&gt;
&lt;br /&gt;
I hate WPF databindings.  Let me say that again.  I &lt;em&gt;hate&lt;/em&gt; WPF databindings.  Of all the technologies to come out of Microsoft over the last five years, WPF (and Silverlight) databindings are easily the most awkward to configure, the least intuitive to use, the hardest to troubleshoot, and the easiest to get wrong.  XAML itself is an ugly, verbose language, but once you get used to it, it's at least possible to get  the UI pieces right with a little bit of troubleshooting.  But setting up bindings in XAML is a different world altogether.  
&lt;br /&gt;
&lt;br /&gt;
Microsoft claims, with some justice, that XAML/WPF/Silverlight provide for a very clean separation of concerns between the UI and the business logic, and this is true.  But the &lt;em&gt;reason&lt;/em&gt; to have a clean separation of concerns is to make things easier for the developer and the designer.  And any benefits that may accrue from this theoretical achievement are entirely wiped out by Microsoft's piss-poor, half-assed, god-awful implementation.  I've spent many painful hours troubleshooting WCF bindings, I've pored over bizarre Linq-to-Entity query side-effects until I couldn't see straight.  But my time has never been so fruitlessly spent as trying to get my databindings right in XAML.
&lt;br /&gt;
&lt;br /&gt;
I could give you an example from nearly every single WPF form I've ever tried to design, but let's just go with this one, taken straight from &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163299.aspx"&gt;this MSDN article&lt;/a&gt;.  Create a simple form that looks like this:
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;table border="0" style="border-collapse: collapse;"&gt;&lt;colgroup&gt;&lt;col style="width: 638px;"&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td style="border-bottom: solid black 0.5pt; border-left: solid black 0.5pt; border-right: solid black 0.5pt; border-top: solid black 0.5pt; padding-left: 7px; padding-right: 7px;"&gt;&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Window&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;="WpfDatabindingDemo.Window1"&lt;br /&gt;&lt;/span&gt;
          &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;="&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/a&gt;"&lt;br /&gt;&lt;/span&gt;
          &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;="&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/a&gt;"&lt;br /&gt;&lt;/span&gt;
          &lt;span style="color: red;"&gt; Title&lt;/span&gt;&lt;span style="color: blue;"&gt;="Window1"&lt;/span&gt;&lt;span style="color: red;"&gt; Height&lt;/span&gt;&lt;span style="color: blue;"&gt;="300"&lt;/span&gt;&lt;span style="color: red;"&gt; Width&lt;/span&gt;&lt;span style="color: blue;"&gt;="300"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Window.Resources&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XmlDataProvider&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;Key&lt;/span&gt;&lt;span style="color: blue;"&gt;="MoreColors"&lt;/span&gt;&lt;span style="color: red;"&gt; XPath&lt;/span&gt;&lt;span style="color: blue;"&gt;="/colors"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;x&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XData&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;colors&lt;/span&gt;&lt;span style="color: blue;"&gt; &amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="pink"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="white"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="black"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="cyan"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="gray"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="magenta"/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;colors&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;x&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XData&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XmlDataProvider&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Window.Resources&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Grid&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ListBox&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;="lbColor"&lt;/span&gt;&lt;span style="color: red;"&gt; Width&lt;/span&gt;&lt;span style="color: blue;"&gt;="248"&lt;/span&gt;&lt;span style="color: red;"&gt; Height&lt;/span&gt;&lt;span style="color: blue;"&gt;="200"&lt;/span&gt;
          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IsSynchronizedWithCurrentItem&lt;/span&gt;&lt;span style="color: blue;"&gt;="True"&lt;/span&gt;
          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ItemsSource&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; Source&lt;/span&gt;&lt;span style="color: blue;"&gt;={&lt;/span&gt;&lt;span style="color: #a31515;"&gt;StaticResource&lt;/span&gt;&lt;span style="color: red;"&gt; MoreColors&lt;/span&gt;&lt;span style="color: blue;"&gt;},&lt;/span&gt;
          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XPath&lt;/span&gt;&lt;span style="color: blue;"&gt;=color&lt;/span&gt;/@&lt;span style="color: blue;"&gt;name}"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ListBox&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Grid&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;br /&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Window&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
And note that in the Visual Studio form designer, you see the data, as you'd expect:
&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="" src="http://wouldbetheologian.com/images/072709_2059_WhyWPFdatab1.png" /&gt;
   &lt;br /&gt;
&lt;br /&gt;
But then try to run the application, and you'll note that the data doesn't show up.
&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="" src="http://wouldbetheologian.com/images/072709_2059_WhyWPFdatab2.png" /&gt;
   &lt;br /&gt;
&lt;br /&gt;
There's no explanation as to why the data doesn't show up.  There's no error in the Visual Studio debug output window.  There's no error anywhere.  The data simply isn't there.  And note that &lt;em&gt;this WPF binding error is taken straight from Microsoft's own documentation&lt;/em&gt;! But the biggest problem isn't that Microsoft's own proof-of-concept, easy-as-pie, this-is-how-you-learn-this sample code doesn't work: it's that your program fails silently, without an error, and without any debugging information.&lt;br /&gt;
&lt;br /&gt;
If you want to know why it doesn't work, you have to add a short but ugly little piece of XAML to turn on extended diagnostics.  (By "ugly" I mean, "You'll never remember what to type unless either (a) you Google it and then cut-and-paste the example into your code; or (b) this is the 57&lt;sup&gt;th&lt;/sup&gt; time you've had to do this."  I'm quickly approaching (b).)  
&lt;br /&gt;
&lt;br /&gt;
First you have to register the diagnostics namespace:
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;table border="0" style="border-collapse: collapse;"&gt;&lt;colgroup&gt;&lt;col style="width: 638px;"&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td style="border-bottom: solid black 0.5pt; border-left: solid black 0.5pt; border-right: solid black 0.5pt; border-top: solid black 0.5pt; padding-left: 7px; padding-right: 7px;"&gt;&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Window&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;="WpfDatabindingDemo.Window1"&lt;br /&gt;&lt;/span&gt;
          &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;br /&gt;&lt;/span&gt;
          &lt;span style="color: red;"&gt; xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: red;"&gt;x&lt;/span&gt;&lt;span style="color: blue;"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;
          &lt;span style="color: red;"&gt;
           &lt;span style="background-color: yellow;"&gt;xmlns&lt;/span&gt;&lt;/span&gt;&lt;span style="background-color: yellow; color: blue;"&gt;:&lt;/span&gt;&lt;span style="background-color: yellow; color: red;"&gt;diagnostics&lt;/span&gt;&lt;span style="color: blue;"&gt;&lt;span style="background-color: yellow;"&gt;="clr-namespace:System.Diagnostics;assembly=WindowsBase"&lt;/span&gt;
          &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;
          &lt;span style="color: red;"&gt; Title&lt;/span&gt;&lt;span style="color: blue;"&gt;="Window1"&lt;/span&gt;&lt;span style="color: red;"&gt; Height&lt;/span&gt;&lt;span style="color: blue;"&gt;="300"&lt;/span&gt;&lt;span style="color: red;"&gt; Width&lt;/span&gt;&lt;span style="color: blue;"&gt;="300"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
And then you have to turn the trace level on to "High".
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;table border="0" style="border-collapse: collapse;"&gt;&lt;colgroup&gt;&lt;col style="width: 638px;"&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td style="border-bottom: solid black 0.5pt; border-left: solid black 0.5pt; border-right: solid black 0.5pt; border-top: solid black 0.5pt; padding-left: 7px; padding-right: 7px;"&gt;&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ListBox&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;="lbColor"&lt;/span&gt;&lt;span style="color: red;"&gt; Width&lt;/span&gt;&lt;span style="color: blue;"&gt;="248"&lt;/span&gt;&lt;span style="color: red;"&gt; Height&lt;/span&gt;&lt;span style="color: blue;"&gt;="200"&lt;/span&gt;
         &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: red;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IsSynchronizedWithCurrentItem&lt;/span&gt;&lt;span style="color: blue;"&gt;="True"&lt;/span&gt;
         &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: red;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ItemsSource&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; Source&lt;/span&gt;&lt;span style="color: blue;"&gt;={&lt;/span&gt;&lt;span style="color: #a31515;"&gt;StaticResource&lt;/span&gt;&lt;span style="color: red;"&gt; MoreColors&lt;/span&gt;&lt;span style="color: blue;"&gt;},&lt;/span&gt;
         &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: red;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XPath&lt;/span&gt;&lt;span style="color: blue;"&gt;=color&lt;/span&gt;/@&lt;span style="color: blue;"&gt;name,
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: red;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="background-color: yellow;"&gt;diagnostics&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;&lt;span style="background-color: yellow;"&gt;:PresentationTraceSources.TraceLevel=High}&lt;/span&gt;"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
And then when you run your app, you finally see this error in the Visual Studio output window:
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 8pt;"&gt;System.Windows.Data Error: 47 : XmlDataProvider has inline XML that does not explicitly set its XmlNamespace (xmlns="").
&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Another hour or so of poking around on Google, and you realize that you have to add the blank namespace to your XML data, like so:
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;table border="0" style="border-collapse: collapse;"&gt;&lt;colgroup&gt;&lt;col style="width: 638px;"&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td style="border-bottom: solid black 0.5pt; border-left: solid black 0.5pt; border-right: solid black 0.5pt; border-top: solid black 0.5pt; padding-left: 7px; padding-right: 7px;"&gt;&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XmlDataProvider&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;Key&lt;/span&gt;&lt;span style="color: blue;"&gt;="MoreColors"&lt;/span&gt;&lt;span style="color: red;"&gt; XPath&lt;/span&gt;&lt;span style="color: blue;"&gt;="/colors"&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;x&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XData&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;colors&lt;/span&gt;&lt;span style="color: red;"&gt;
           &lt;span style="background-color: yellow;"&gt;xmlns&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;&lt;span style="background-color: yellow;"&gt;=""&lt;/span&gt; &amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="pink"/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="white"/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="black"/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="cyan"/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="gray"/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;color&lt;/span&gt;&lt;span style="color: red;"&gt; name&lt;/span&gt;&lt;span style="color: blue;"&gt;="magenta"/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;colors&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;x&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XData&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;XmlDataProvider&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
And after only two or three hours of troubleshooting (if you're lucky), you've fixed your problem.  But my point is that this isn't something that you should have had to troubleshoot.  This is something that either (a) should have worked out of the box, as the MS sample code led you to believe, or (b) should have thrown a simple and explanatory runtime error, or (c) even better, should have been caught at compile-time, since everything that the compiler needed to know to realize that this wouldn't work is already there in the source code.  Any of those three options would have been fine.  But it's simply not acceptable to fail silently, without even a hint about what's going wrong.
&lt;br /&gt;
&lt;br /&gt;
This is just one example, of course. &amp;nbsp;I could produce plenty of others, but then this post would get even more boring and repetitive than it is.&lt;br /&gt;
&lt;br /&gt;
The fundamental problem with Microsoft's data binding implementation is that it's a significant step backwards in terms of computer language theory.  Folks have known for years that strongly typed languages help you write better code. It's better to catch an error when you're writing your code than to catch it at compile-time; &amp;nbsp;it's better to catch an error when you compile your code than to catch it at run-time; if the compile doesn't catch it, at least your automated tests should be able to; and &lt;em&gt;of course&lt;/em&gt; it's better to throw an error (even at runtime) than to fail silently.  But the way that MS has implemented bindings, there's no way to catch errors at any of these steps: neither when you're designing your form, nor when you're compiling your app, nor when you're running your tests, and most inexplicably, not even when you're running your application.  The minute you type "{Binding…}", you're working without a net.
&lt;br /&gt;
&lt;br /&gt;
For instance, MS could have implemented the XmlDataProvider in such a way as to allow (or even require) you to specify an XSD file as a parameter. &amp;nbsp;If they had, not only could you get Intellisense when typing in your bindings, but you could also receive a helpful compiler error if it sees, say, that you've bound your ListBox ItemsSource to an element or an attribute that doesn't exist.  Similarly, if you're using an object data source, you should be allowed to declare the type up-front, and then only bind to properties available in that type.  And if the binding fails at run-time, e.g., the object isn't available, or doesn't have the properties available that you're trying to access, you should get exactly the same sort of error that you'd get in C# if you tried to access a non-existent property on a class from a third-party DLL.  In other words, it should not only fail (which it does now), but it &lt;em&gt;should tell you why it's failing&lt;/em&gt;, and it &lt;em&gt;should tell you this before you ever run your application&lt;/em&gt;.
&lt;br /&gt;
&lt;br /&gt;
In other words, MS should have made the DataContext property strongly typed.  It would allow the Visual Studio tools to do in milliseconds what you can only do now through hours of futile Googling and days of pointless troubleshooting.  Microsoft decided that they wanted the extra flexibility that comes from not having any type safety, and I agree that there are scenarios where this flexibility is helpful.  But there's a reason nobody writes enterprise applications in VBScript: type safety is orders of magnitude more important than flexibility when working with complex systems.  And I would willingly, in a heartbeat, give up some extra flexibility, in exchange for knowing immediately &lt;em&gt;why&lt;/em&gt; my bindings won't work, instead of waiting until I run the app to find out &lt;em&gt;that&lt;/em&gt; they don't work and not having a clue as to why.
&lt;br /&gt;
&lt;br /&gt;
Undoubtedly this would require a pretty significant rethinking of how data binding works with XAML.  Neither WPF nor Silverlight would look the same when they were done.  But that may be exactly my point.  MS had the chance to get WPF right; and they missed a huge opportunity.  And until they fix this, their databinding implementation will remain a significant drag on the adoption of WPF and Silverlight.  Without strong typing, WPF databinding is just too difficult to use.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-6717650555355140819?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/6717650555355140819/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=6717650555355140819" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/6717650555355140819?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/6717650555355140819?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/07/why-wpf-databinding-is-awful-technology.html" title="Why WPF databinding is an awful technology" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0YESHY8fCp7ImA9WxJVGU4.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-8654318404601955845</id><published>2009-07-06T20:58:00.001-07:00</published><updated>2009-07-06T20:58:29.874-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-06T20:58:29.874-07:00</app:edited><title>No Comment Necessary</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;I got this dialog box today:
&lt;/p&gt;&lt;p&gt;&lt;img alt='' src='http://wouldbetheologian.com/images/070709_0358_NoCommentNe1.png'/&gt;
			&lt;/p&gt;&lt;p&gt;I guess it's sort of self-explanatory.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-8654318404601955845?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/8654318404601955845/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=8654318404601955845" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8654318404601955845?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8654318404601955845?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/07/no-comment-necessary.html" title="No Comment Necessary" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DEIEQn85eCp7ImA9WxJRGUo.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-1691661421509666322</id><published>2009-05-22T00:15:00.001-07:00</published><updated>2009-05-22T00:15:03.120-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-22T00:15:03.120-07:00</app:edited><title>Pair Programming</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;I've recently found myself a new late-night programming buddy.
&lt;/p&gt;&lt;p&gt;&lt;img alt='' src='http://wouldbetheologian.com/images/052209_0714_PairProgram1.jpg'/&gt;
			&lt;/p&gt;&lt;p&gt;He generally hangs out in a chair next to my desk, a vantage point which allows him to make frequent comments on the quality of my work.
&lt;/p&gt;&lt;p&gt;&lt;img alt='' src='http://wouldbetheologian.com/images/052209_0714_PairProgram2.jpg'/&gt;
			&lt;/p&gt;&lt;p&gt;His name is Brendan Javier Michael Smith, and he joined our family last Wednesday.  He's about as cute as they come, even if he's not (yet) much of a coder.
&lt;/p&gt;&lt;p&gt;See &lt;a href='http://picasaweb.google.com/smithkl42/BrendanSBirth'&gt;here&lt;/a&gt; and &lt;a href='http://picasaweb.google.com/smithkl42/BrendanAtHome'&gt;here&lt;/a&gt; for more pictures.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-1691661421509666322?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/1691661421509666322/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=1691661421509666322" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/1691661421509666322?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/1691661421509666322?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/05/pair-programming.html" title="Pair Programming" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DE4GRno4cCp7ImA9WxJSF0o.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-8701140845143253099</id><published>2009-05-08T02:54:00.001-07:00</published><updated>2009-05-08T03:02:07.438-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-08T03:02:07.438-07:00</app:edited><title>Asynchronous WCF Methods in Silverlight</title><content type="html">&lt;span xmlns=""&gt;&lt;p&gt;I'm not sure whether I should love or hate a language that lets me write code like this:
&lt;/p&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;   private void InitData()
    {
        RoomServiceClient rc = new RoomServiceClient(wsBinding, roomServiceEndpoint);
        rc.GetUserCompleted +=
            delegate(object sender, GetUserCompletedEventArgs e)
            {
                user = e.Result;
                rc.JoinRoomAsync(App.OwnerUserID, App.RoomName, App.UserID);
            };
        rc.JoinRoomCompleted +=
            delegate(object sender, AsyncCompletedEventArgs e)
            {
                rc.GetRoomAsync(App.OwnerUserID, App.RoomName);
            };
        rc.GetRoomCompleted += 
            delegate(object sender, GetRoomCompletedEventArgs e)
            {
                UpdateLocalState(e.Result);
            };
        rc.GetUserAsync(App.UserID);
    }

&lt;/code&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-8701140845143253099?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/8701140845143253099/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=8701140845143253099" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8701140845143253099?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8701140845143253099?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/05/asynchronous-wcf-methods-in-silverlight.html" title="Asynchronous WCF Methods in Silverlight" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkIDSHo8fCp7ImA9WxJTGEw.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-8047944086977124236</id><published>2009-04-26T22:33:00.001-07:00</published><updated>2009-04-26T22:36:19.474-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-26T22:36:19.474-07:00</app:edited><title>Blinkx Acquired 100% of Zango’s Assets</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;I've seen a number of online articles (&lt;a href='http://seattletimes.nwsource.com/html/technologybrierdudleysblog/2009109821_zango_goes_bango_ceo_bankrupt.html'&gt;here&lt;/a&gt; and &lt;a href='http://www.theregister.co.uk/2009/04/21/zango/'&gt;here&lt;/a&gt;, for instance), which say that Blinkx has acquired only "ten percent" of Zango's assets.  This wouldn't be the first time that a corporate spokesman has honestly misunderstood the actual state of affairs, or has been badly misunderstood by the reporters to whom he was speaking.  So I don't want to jump to any conclusions.  But I should be clear that Blinkx acquired fully 100% of Zango's assets.  As a Zango shareholder, I now own a percentage of precisely nothing, and the banks have nothing left of Zango's which they can sell.  Blinkx owns it all.
&lt;/p&gt;&lt;p&gt;In addition, there have been postings on various &lt;a href='http://forums.digitalpoint.com/showthread.php?p=11227314'&gt;forums&lt;/a&gt; which indicate that Zango's assets were purchased by a company called "&lt;a href='http://forums.digitalpoint.com/showthread.php?p=11255378'&gt;Pinball&lt;/a&gt;".  In this case, not being a Blinkx insider, I'm not entirely sure of the relationship between Pinball and Blinkx: Pinball may be a subsidiary of Blinkx, a DBA, or something else.  But Zango's assets were acquired by Blinkx, not some hitherto unknown company, so it's clear that the corporate "thing" that is Pinball is not appreciably different from the corporate "thing" that is Blinkx.  
&lt;/p&gt;&lt;p&gt;I should note that Zango itself had a variety of subsidiaries and brands, such as Hotbar, SmartShopper, Platrium, and so forth, so there's nothing necessarily nefarious in Blinkx doing this – unless, of course, they're trying to obfuscate or deny their involvement.  But that would sure seem like a foolish thing for a public company to do. &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-8047944086977124236?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/8047944086977124236/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=8047944086977124236" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8047944086977124236?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8047944086977124236?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/04/blinkx-acquired-100-of-zangos-assets.html" title="Blinkx Acquired 100% of Zango’s Assets" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DkAGRn84fSp7ImA9WxJTF0s.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-6280828691083425802</id><published>2009-04-26T09:49:00.001-07:00</published><updated>2009-04-26T09:52:07.135-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-26T09:52:07.135-07:00</app:edited><title>Backyard Coyote</title><content type="html">&lt;span xmlns=""&gt;&lt;p&gt;One of the coyotes that frequent our neighborhood showed up in our backyard today – but unlike most of the numerous times we've spotted coyotes, he stuck around just long for me to get a few (slightly blurry) pictures.
&lt;/p&gt;
&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/F7xJniSlzm1w2uXxo0m1hg?authkey=Gv1sRgCO3ro4SWpcuKogE&amp;feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_aPSeEEHW7sM/SfSP2G58_eI/AAAAAAAAPu8/ljpC5W8VAf0/s800/IMGP4745.JPG" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="http://picasaweb.google.com/smithkl42/20090426Coyote?authkey=Gv1sRgCO3ro4SWpcuKogE&amp;feat=embedwebsite"&gt;2009-04-26 Coyote&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/PQLdh42Uw22rH4ZHbP84ow?authkey=Gv1sRgCO3ro4SWpcuKogE&amp;feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_aPSeEEHW7sM/SfSP2rMYOXI/AAAAAAAAPvI/EpARqb4Ebq4/s800/IMGP4746.JPG" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="http://picasaweb.google.com/smithkl42/20090426Coyote?authkey=Gv1sRgCO3ro4SWpcuKogE&amp;feat=embedwebsite"&gt;2009-04-26 Coyote&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/ZLbn9ELcSfDJPni5mBg24A?authkey=Gv1sRgCO3ro4SWpcuKogE&amp;feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_aPSeEEHW7sM/SfSP3D3JHZI/AAAAAAAAPvg/UUGX95ljMfU/s800/IMGP4748.JPG" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="http://picasaweb.google.com/smithkl42/20090426Coyote?authkey=Gv1sRgCO3ro4SWpcuKogE&amp;feat=embedwebsite"&gt;2009-04-26 Coyote&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-6280828691083425802?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/6280828691083425802/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=6280828691083425802" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/6280828691083425802?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/6280828691083425802?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/04/backyard-coyote.html" title="Backyard Coyote" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_aPSeEEHW7sM/SfSP2G58_eI/AAAAAAAAPu8/ljpC5W8VAf0/s72-c/IMGP4745.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;Ck4EQHkzcSp7ImA9WxJTFk0.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-2211821318929396</id><published>2009-04-24T12:21:00.001-07:00</published><updated>2009-04-24T12:21:41.789-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-24T12:21:41.789-07:00</app:edited><title>Excerpts from Some Old Zango Emails</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;In reading through the comments on my last several posts, I get the impression that a lot of people think that Zango winked at the silent and/or inappropriate installs perpetrated by its distribution network.  I can assure everyone that was not the case.  I first found credible evidence of silent installs happening in mid 2004, and the emails that I sent on the topic for the next year or more were not exactly models of tact and discretion.    But they also show the dawning awareness that our distribution model was broken, and badly needed to be revamped from the ground-up.  A few examples out of many emails on the topic that I personally sent.
&lt;/p&gt;&lt;p&gt;Sent on 11/8/2004, after one of my developers noticed a silent install taking place through a sub-affiliate of LoudMarketing, our largest distributor (and the company that eventually became ZangoCash):
&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;It looks like 2229 is from Loud, which is &lt;em&gt;not&lt;/em&gt; a good thing.  They need a good swift kick in the balls for pulling shit like this.  Tell them in no uncertain terms: THIS IS FUCKING UNACCEPTABLE.
&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;We need to get this taken care of, and ASAP.  This is absolutely intolerable.  We can't have folks going around giving us this reputation.
&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;We'll be able to detect this in a more automated fashion once we get the CET running – but for now, we'll have to put up with ad hoc information like this.
&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Sent on 12/2/2004, after I found Zango being installed through a security hole by a company called CrazyWinnings (or one of its sub-affiliates):
&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;And these guys are definitely bundling a Trojan.  No doubt about it.  After I uninstalled everything that I could find to uninstall, AdAware still found hundreds of entries – and so far as I can tell, at least four different pieces of spyware.  And no matter how many times I ran AdAware, they still came back.  These guys are a bunch of frigging bastards.
&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;I can't say too much that we HAVE to completely and permanently distance ourselves from players like this.  If we are ever going to build trust as a brand, we need to never, ever be associated with guys like CrazyWinnings.  I would strongly encourage us not to wait until tomorrow at 3:00, but just drop them now.  We will never, ever be able to trust them.  They're slimy, and they're associated with guys that are even slimier.  
&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;Zango will never get any traction – and 180solutions will never be able to build a legitimate, long-term business – if assholes like these guys are still dragging 180solutions' name through the mud.  Fuck 'em.  Get rid of them now, and sue their asses.
&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Sent 4/11/2005, after I found Zango being installed on a page that was using an exploit to install other software:
&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Although they [IST] don't install the slotchbar AX without asking, my own testing actually indicates that they are using an IE security hole to install some stuff &lt;em&gt;besides&lt;/em&gt; the slotchbar.  And although a number of the things that get installed from that page have uninstalls, a number of the uninstalls don't work (including IST's).  After I finished uninstalling everything that could be uninstalled, and rebooted, MS AntiSpyware still found four separate and working installations of various spyware applications.  And yes, they install us (through the slotchbar, not through the security hole, but given that it all happens at the same page, and given that the slotchbar uninstalls don't work, that's not relevant).
&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;This is a big, big problem.  This is a clear violation of our code of conduct.  We can't have ourselves out there associated with this kind of stuff.  Ken M., it seems to me that legal action is clearly warranted here.  What's your take on this?
&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;And it's another problem that I'm the one finding this.  We clearly need to do our testing better.  I'd like to call a meeting to discuss how we handle testing applications like this, to figure out why my own testing was able to find such a clear violation of our COC, and our formal testing didn't.  Who all should be there at that meeting?
&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Diplomacy has never been my strong suit as an executive.
&lt;/p&gt;&lt;p&gt;I should also note that although I was probably the most vocal, my concerns were taken very seriously by the folks in charge of our distribution relationships.  Not only did they work very hard to address these issues with the distributors in question, they also proposed the strategy which eventually fixed the problem, namely, to acquire our largest distributor, and clean up their network.
&lt;/p&gt;&lt;p&gt;Should we have been associated with guys like IST, Aztec and CrazyWinnings in the first place?  In hindsight, of course not.  But we honestly didn't know the extent of the problem, and even when it became clear, it took real time, effort and work to fix it. And ultimately, and regrettably, my predictions came true: they dragged our name through the mud, we were unable to build trust as a brand, and we were never able to build a legitimate, long-term business.  Zango had other problems besides this one, but this was the largest.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-2211821318929396?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/2211821318929396/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=2211821318929396" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/2211821318929396?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/2211821318929396?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/04/excerpts-from-some-old-zango-emails.html" title="Excerpts from Some Old Zango Emails" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0YBQn8_eSp7ImA9WxJTE04.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-7203499653497830038</id><published>2009-04-21T02:05:00.001-07:00</published><updated>2009-04-21T11:39:13.141-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T11:39:13.141-07:00</app:edited><title>What Zango Got Right</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;I suspect that there will be two sorts of reactions to this post.  If you worked at Zango, or even if you knew people who did, your response may be to wonder why such obvious things needed to be said at all.   But if, like most people, you never worked at Zango, and your only acquaintance with Zango as a company was through the various things that got reported about us in the media, you may find most of what I say to be strange or even unbelievable.  But it's precisely because many people will have this reaction that I think these things need to be said.
&lt;/p&gt;&lt;p&gt;In my last blog post, I talked at some length about what Zango got wrong: and because Zango was ultimately acquired for fire-sale prices, it might seem like what we got wrong is the largest part of the story. But in the end, I don't think it is.  What Zango did right was fairly impressive, and is worth talking about publically.  I'm well aware that not everyone will agree or even believe me: and maybe some of those folks will even be former Zango employees.  But I'm writing this post, not because I think it will meet with universal agreement, but because I believe it to be true.
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Zango had a great culture.&lt;/strong&gt;  OK, yes, in the end, work is work: it's never interesting all the time, and even in the best job or at the best company it's sometimes plain drudgery.  But most of the time, work at Zango was exciting and engaging.  Zango was possessed of an exuberant and vibrant corporate culture which valued its employees, encouraged friendships, never took itself too seriously, and had a whole lot of fun.  Dan Todd, one of Zango's co-founders and its president for many years, did a phenomenal job of fostering an almost "summer camp" atmosphere.  I could go on for quite some time listing the great things that he introduced: semi-annual dodgeball tournaments, a weekly morning basketball game, free lunches, "Beer Friday" (later neutered to "Friday at Five"), and on and on.  It was a hoot to work at Zango, and I'd venture to say that nearly all its employees counted themselves fortunate to be able to do so.&lt;strong&gt;&lt;br/&gt;
					&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Zango had great employees.&lt;/strong&gt;  Some years ago, when our VP of HR, Ring Nishioka, was trying to clarify what sort of employees I was looking for, I said I had two requirements: (1) They had to be scary smart, and (2) they couldn't be an asshole.  Appropriately neutered by HR ("looking for people who are scary smart, but also really cool"), this became our hiring slogan and the criteria by which we measured every potential employee.  (It also became a famous internal poster, when &lt;span style='text-decoration:line-through'&gt;some anonymous graphic artist&lt;/span&gt; John Mitchell added a rather frightening picture of Jeff Malek, our VP of Engineering, and the words "Two out of three ain't bad.")  Not everybody we hired was scary smart, and a few failed the asshole test badly.  Sometimes I failed it too.  But that's just life.  On the whole, Zango was composed of the smartest, kindest, and most ego-free people I've ever worked with.  And I would work with them again in a heartbeat.  (Blinkx, be warned that you should treat your new employees well.  I'm working on another startup, and I've never signed a no-poaching agreement with you.  Expect me to come after your people as soon as I can.)&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Zango developed a unique and innovative business model&lt;/strong&gt;.  OK, yes, I can hear the snickers from the peanut gallery already.  (Hi, Paperghost!)  But it's true.  On the advertising side, Zango introduced the idea of "CPV", "Cost Per Visitor".  From one perspective, CPV is just CPM / 1000.  But from another, it's a radically different animal, because rather than displaying an &lt;em&gt;ad&lt;/em&gt;, Zango displayed a &lt;em&gt;page&lt;/em&gt;.  This removed the first click from the advertising funnel, which was a significant innovation, and accounts for much of the effectiveness of Zango's advertising.  On the distribution side, Zango is one of the most effective monetization vehicles for long-tail websites.  There are webmasters in their mom's basements who make six figure incomes because of Zango.   As I explained in my last post, using time-shifted contextual advertising to sponsor online content was a great idea when Zango introduced it, and it remains a great idea today.  It just needs a company better positioned to execute on it than Zango could.  For the sake of its newest employees, I really hope that blinkx is that company.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Zango made some great acquisitions&lt;/strong&gt;.  Between 2004 and 2007, Zango acquired five different companies, of varying size and significance.  Two of them, EasyMessenger and Full Armor Studios, were small, and were mostly about beefing up our content library.  (We later discovered we could do this more effectively through licensing than through acquisition.)  But the other three, LoudCash, Hotbar, and SmartShopper, were substantial and critical.  They not only brought some really great people onto the Zango team (Benoit Aubuchon, Mathieu St. Denis, Moti Ankonina, Meir Uziel, Ziv Gonen, and lots of others), but they also helped to fill significant holes in Zango's business and technical portfolios.  &lt;br/&gt;&lt;br/&gt;The acquisition of LoudCash in 2005 was the first major step in solving our distribution nightmare, as it brought our largest and most important distributor in-house.  For the next four years, the ZangoCash platform (as we renamed it) remained our most efficient and cost-effective distribution channel.  York Baur deserves special credit for recognizing the strategic importance of this deal, and for pushing it through substantial opposition (much of which came from yours truly).&lt;br/&gt;&lt;br/&gt;In 2006, Zango acquired Hotbar, a competitor based in Tel Aviv.  At one level, it was probably the best acquisition Zango ever made.  Within hours after the papers were signed, Zango set to work to add a reskinned Hotbar toolbar to its own brands, and to replace Hotbar's popup engine with Zango's.  When we finished the integration two months later, we had effectively doubled the size of Zango's audience, and had increased pro-forma per-user revenue by nearly 50%.  Unfortunately, several factors conspired to make this deal less successful than it should have been.  It started when scanning applications, many of which had ignored Hotbar, suddenly began scanning Hotbar's application off the desktop simply because it was now associated with Zango.  This was especially frustrating to watch, because the new application's behavior was, by any conceivable standard, safer and less intrusive than before.  Then, again simply because of Zango's reputation, Yahoo stopped allowing the Hotbar toolbar to use its search feed, which made the toolbar itself much less profitable.  And finally, it turns out that the Hotbar content (primarily emoticons and anti-spam software) was already fading in popularity, and acquiring users through these channels became more and more expensive.  These three setbacks, which we could perhaps have foreseen but were otherwise outside our control, were compounded by a mistake that was well within our control, namely, choosing to finance the deal primarily with debt rather than equity.  If our models had been accurate, we would have had no problem in paying off this debt, and quickly: but because our users were suddenly more expensive to acquire, more difficult to retain, and less profitable each day they stuck around, we found ourselves forced to cut our user acquisition budget to make the debt payments.  Predictably, we watched in horror as our audience shrank, month after month, and the debt payments became ever more difficult to make.&lt;br/&gt;&lt;br/&gt;Our 2007 acquisition of SmartShopper, Hotbar's sister company, almost allowed us to pull out of this spiral.  With SmartShopper, for the first time we had a technology that would allow us to fully replace our admittedly annoying popups with a less intrusive, more helpful form factor that nevertheless had a similar monetization profile.  We immediately set to work on the product that eventually became known as Platrium.  Platrium was designed to fix the two major problems we had identified in our business: (1) It would have a clear and easily branded value proposition; and (2) it wouldn't have popups.  Our hope was that these two changes would finally convince the scanning apps to leave us alone, would persuade users of our value relative to the ads, and would allow us to partner with companies that had hitherto remained out of our reach.  It was the SmartShopper acquisition which allowed us to make this move, and I really think that it might yet work.  Unfortunately for Zango, the change in product focus came too late.  After our June 2008 layoffs (which is also when I chose to leave), Zango didn't really have the staffing needed to move Platrium forward without sacrificing our existing revenues: every resource allocation Keith made was going to starve either the Platrium or the legacy lines of business.  There were no more good choices.
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I want to end this post on a couple of more positive and personal notes.  
&lt;/p&gt;&lt;p&gt;First, the decade I spent with Zango was the best of my entire life.  I'll always be grateful for that day in 1999 when Keith called me in a panic because his new website was down.  I learned more, grew more, worked with better people, and had more fun than in anything else I've ever done.  Yes, parts of it were frustrating, but even our defeats were instructive, and some of them were glorious.
&lt;/p&gt;&lt;p&gt;Second, I want to say that it was a privilege beyond my expectations to have spent so much time in Tel Aviv, working with that strangely obstreperous and beautiful animal, the modern Israeli.  To everyone from Hotbar and SmartShopper, I'm very sorry that things wound up the way they did.  Even though I was no longer with Zango when it was announced, it was a blow to me that we had to close our Tel Aviv office.  I hope that everyone lands quickly on their feet; and I continue to hope that my connections with Israel are not yet at a close.
&lt;/p&gt;&lt;p&gt;And finally, and again, I can't say enough good about the people at Zango.  Doug, Jeff, Val, Bill, Cris, Murph, Madhuri, Galina, Danny, Benoit, Moti, Meir, Nick, Willie, Lance, Jesse, Rob, Robert, Rich, Andrew, Yuval, Tommy, Heather, Ayelet, Rinat . . . and many, many more.  I'm proud to have worked with you and honored to have served next to you.  And if it's ever possible, I'd like to do so again.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-7203499653497830038?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/7203499653497830038/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=7203499653497830038" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/7203499653497830038?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/7203499653497830038?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/04/what-zango-got-right.html" title="What Zango Got Right" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DEIGR3oyfCp7ImA9WxJTEU8.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-8144393991109814914</id><published>2009-04-19T00:35:00.001-07:00</published><updated>2009-04-19T00:35:26.494-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-19T00:35:26.494-07:00</app:edited><title>What Zango Got Wrong</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;When the six original Zango founders gathered at the &lt;a href='http://www.mcmenamins.com/index.php?loc=58&amp;amp;id=135'&gt;Centralia McMenamins&lt;/a&gt; pub in July 1999, we really had no idea what we were getting into.  None of us besides Keith had ever started a company before: all we knew is that everyone around us was starting one, and we had to be in on the goldrush.  Our original idea – "pay people to surf the Internet" – was laughable in hindsight, but back in 1999, even the stupidest ideas made a certain kind of sense.  And even in that silly idea there was the germ of something that still has the potential to make someone a lot of money.
&lt;/p&gt;&lt;p&gt;The idea that still makes sense is something we called "time shifting", or in a slightly more verbose formulation, "online content sponsored by time-shifted contextual advertising".   For background, start with &lt;a href='http://www.businessinsider.com/is-youtube-doomed-2009-4'&gt;this article&lt;/a&gt; from Business Insider about Google's YouTube division.  Google is, of course, insanely profitable, largely on the basis of its AdWords and AdSense products: but it's losing nearly half a billion dollars annually (around $1.3MM each day) on YouTube.  Google acquired YouTube for way too much money on the assumption that they could apply AdWords economics to an entertainment site.  And of course, the economics simply don't apply.  When I go to &lt;a href='http://google.com/'&gt;google.com&lt;/a&gt;, I &lt;em&gt;want&lt;/em&gt; to be taken away from the site: that's the whole genius of it.  So a well-targeted ad is, for all practical purposes, precisely what I'm looking for.  But when I'm on YouTube (or Hulu, or any of the other video sites), I'm going there to be entertained: and the last thing I want is to click on an ad that at best distracts from the experience, and at worst interrupts it entirely.  It doesn't matter how well you target the ads: they will always return dramatically lower CPM's than an ad on Google's home page.
&lt;/p&gt;&lt;p&gt;Zango's answer to this problem really was genius: keep the content free, and sponsor it with ads, but &lt;em&gt;don't&lt;/em&gt; display the ad to the user when they're consuming the content.  Rather, show it to them later, when they're doing something which indicates they're potentially in mood to act on the advertisement.  The CPM's tell the story: over the last several years, Zango's average CPM was somewhere around $25, which is phenomenal.  And it would have been higher, indeed, &lt;em&gt;much&lt;/em&gt; higher, if it weren't for several other factors that I'll go into shortly.
&lt;/p&gt;&lt;p&gt;In other words, Zango's business proposition was more-or-less unique, and solved perhaps the most significant problem facing the current Web 2.0 generation of companies.  So why did Zango ultimately fail?  (Because yes, that's what the acquisition by blinkx represents, even if blinkx keeps the brand and systems going and retains some of the employees.)  From the perspective of nearly a decade at Zango, and a little less than a year watching from the sidelines, I think that of the numerous contributing factors, the following five were most significant.  Not everybody at Zango would agree as to which ones were most important, but pretty much everyone would agree that they all played a significant role.
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Zango screwed up its distribution.&lt;/strong&gt;  Back in 2003-2005, we partnered with some people that we should never have partnered with.  We almost completely outsourced our distribution to them, and we let them promote and install our software without adequate oversight or supervision.  During that time period, my best estimate is that something like 4% of our installs during that time period were completely silent, i.e., were the result of affiliates using browser security holes to install Zango's software with no knowledge or consent by the user.  The bigger problem, however, is that the vast majority of our installs received &lt;em&gt;inadequate &lt;/em&gt;consent, i.e., the user technically had an opportunity to decline the install, but wasn't presented with enough information to make an informed choice.  &lt;br/&gt;&lt;br/&gt;We acknowledged this problem a long time ago, and well before the FTC ever came knocking on our door, we were working our asses off to fix it.  And eventually we did.  It's been years since the last inappropriate Zango install, and Zango's notification and consent is by any reasonable standard better than Yahoo's, better than Microsoft's, and better than Google's.  But it was too late: the damage had been done.  Zango's reputation was never able to recover.  And having a bad reputation as an Internet company is somewhat worse than having a bad reputation in high school.  Instead of not getting invited to the cool parties, you find yourself unable to close deals with strategic partners, which is a &lt;em&gt;lot&lt;/em&gt; worse.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The desktop advertising industry screwed up even worse&lt;/strong&gt;, and took Zango down with it.  It's significant that of all the major desktop advertising players (the others being Claria, WhenU and DirectRevenue), Zango was the last one standing.  Partly this is because we made some strategic product and acquisition decisions the others didn't, partly it's because our major sins were sins of omission rather than commission.  But in the end, it wasn't enough.  Back in 2003, &lt;em&gt;spyware&lt;/em&gt; meant "a program that your wife puts on your computer to track what you're doing."  By 2005, it was synonymous with "adware", which was an awkward if reasonable description of Zango's business model.  How did this happen?  &lt;br/&gt;&lt;br/&gt;Well, folks like DirectRevenue, IST, MindSet, and others of that ilk didn't just miss that bad installs were happening: over the years we saw plenty of evidence that they actively encouraged it.  And when they found a security hole, they would typically install dozens of different pay-per-install applications.  And very few of those programs had any sort of notice, QA, or presence in Add/Remove Programs: in contrast, Zango had all of those things.  So all the user noticed was that their machine had suddenly slowed to a crawl, and they find this "Zango" program on their PC.  It wasn't Zango that was slowing their machine down, but how could they know that?  &lt;br/&gt;&lt;br/&gt;Keith dubbed this the "tallest midget" problem: we were the tallest midget, so we were the ones that got noticed.  I remember one incident very well: an AIM worm making the rounds was installing both Zango and WhenU (among others).  When the worm attempted to deliver its payload, Zango automatically popped up a notification to make sure the user was appropriately informed, and to give them the opportunity to cancel it if necessary; WhenU, in contrast, installed silently.  But precisely because Zango was trying to do the right thing, all the &lt;a href='http://blogs.zdnet.com/Spyware/?p=743'&gt;news articles&lt;/a&gt; mentioned Zango, and precisely none of them mentioned WhenU.  That was &lt;em&gt;very&lt;/em&gt; frustrating.&lt;br/&gt;&lt;br/&gt;The result is that a cottage industry (and eventually a mansion industry) grew up around adware/spyware removal.  Sometimes those programs were well-designed and helpful, sometimes they were worse than the spyware they proposed to remove.  But either way, it meant that the average lifespan for a desktop advertising install decreased dramatically.  Over the years, we negotiated extensively with these companies to understand and address their concerns, and some of them were willing to work with us, but many simply refused to talk to us.  After all, they were in it to make a buck as well: and from their perspective, nothing good could happen from not aggressively removing us.&lt;br/&gt;&lt;br/&gt;Even more damaging, many advertisers began to institute "no popup" or "no adware" policies.  Almost none of our largest advertisers in 2005 were with us by the end of 2006.  The few content partners who would talk to us were &lt;a href='http://www.washingtonpost.com/wp-dyn/content/article/2006/07/27/AR2006072701620.html'&gt;extremely skittish&lt;/a&gt;.  Google, Microsoft, Yahoo and AOL all refused to give us their search feeds, nor would they permit us to advertise Zango on their properties or through their networks.  It's frankly impressive that Zango was able to stay in business as long as it did, when we couldn't even do business with the majority of the Internet.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;&lt;strong&gt;We failed to deliver adequate value in exchange for the advertisements&lt;/strong&gt;.  Let's face it: it's a fairly aggressive tactic to pop an ad unexpectedly over somebody's browser session, no matter how targeted.  If you're going to get away with it, you need to offer a pretty good value proposition in return.  With a few exceptions, Zango was never able to do so.  Zango has hundreds of thousands of pieces of content in its content catalog, but users generally conclude (and fairly quickly) that the tradeoff isn't worth it.  As one Zango manager put it, "We're trying to sell people a Yugo for a Mercedes Benz price." &lt;br/&gt;&lt;br/&gt;There were many reasons Zango wasn't able to fix this.  A major one is that the folks who owned the compelling content, and could have benefitted from our monetization, didn't want to work with us (see points #1 and #2).  But probably the biggest is that we were brain-dead, and didn't recognize this problem until too late.  We focused on optimizing our sales workflow, our ad targeting mechanism, our BI systems, and our installation process: but we spent precious little time improving our content.  This was an institutional and cultural problem at Zango for far too long.  Periodically, someone would come along and talk as if the consumer experience mattered, but it rarely got beyond words and speeches until late 2007.  (To Keith's credit, he &lt;em&gt;did&lt;/em&gt; ultimately declare this emergency, and the result was &lt;a href='http://games.platrium.com/'&gt;Platrium&lt;/a&gt;, which does a much better job of balancing the cost-benefit equation: but it was too little, too late.)&lt;br/&gt;&lt;br/&gt;On a side note, this is also the problem that I personally take most responsibility for.  As the CTO, I was ultimately responsible for the product that we delivered.  If I knew then what I realize now, I would have made dramatically different product choices, would have fought a very different set of internal battles, and most importantly, would have brought somebody like Val Sanford on board much, much sooner.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Zango was unfairly charged with affiliate commission stealing&lt;/strong&gt;.  This is a complicated story, and I'll forgive anyone who doesn't want to read through the gory details.  Back in 2004-2005, Commission Junction and LinkShare were two of Zango's largest advertisers, and we were one of their largest publishers.  We displayed targeted ads promoting their advertisers' products, took a share of the proceeds when a user bought something, and pretty much everybody was happy.  Initially, we sometimes used the advertiser's home page as a targeting mechanism, and I'll have to confess, this never struck me as particularly fair to the advertiser.  (If the user is already sitting on eBay's site, why should &lt;em&gt;we&lt;/em&gt; get a commission if the user happens to make their purchase through our ad rather than their original browser instance?)  There are some instances when home page targeting is justified: if Alaska doesn't want Southwest's ad to show up when someone visits their website, they should pay for the privilege.  (You'll note whose ad shows up when you google "&lt;a href='http://www.google.com/search?rlz=1C1GGLS_enUS291US304&amp;amp;aq=f&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=dell'&gt;Dell&lt;/a&gt;", and that doesn't happen for free.)  But most of the time, I think the advertisers who complained about it had a reasonable point.  However, as soon as LinkShare and CJ asked us to stop this practice, we did so.  We even implemented a number of fairly complicated and expensive features to ensure that we wouldn't inadvertently display ads that would violate their terms of service.  (In fact, &lt;a href='http://www.benedelman.org/spyware/180-affiliates/'&gt;Ben Edelman&lt;/a&gt; once badly misinterpreted a packet sniff to imply that we were being particularly nefarious, when what it actually showed was us trying desperately not to step on somebody's home page, and going through some admittedly strange gyrations to refrain from doing so.)&lt;br/&gt;&lt;br/&gt;But here's the frustrating part.  Imagine the following scenario.  A user with Zango's software visits a CJ publisher who is promoting some eBay products.  That publisher sets a cookie on the user's machine that says, in effect, "If this user buys something from eBay, I get the commission."  But then, before the user visits the eBay site, but after the first cookie was set, Zango happens to pop an ad that sets a different cookie, this one claiming the eBay commission for Zango.  Given this scenario, I'm perfectly willing to grant that Zango should &lt;em&gt;not &lt;/em&gt;get the commission, and the original publisher &lt;em&gt;should&lt;/em&gt;.  &lt;br/&gt;&lt;br/&gt;So the question is: how do you make sure that the first publisher gets it, and Zango doesn't?  For a variety of reasons, this was a difficult scenario to prevent from Zango's side.  (Among other things, how are we to know that the site in question belongs to a CJ affiliate?)  This is a very simple problem to prevent, however, if you are Commission Junction or LinkShare.  Your script should just place different cookies for each publisher, and you should give the commission to the owner of the cookie with the earliest timestamp rather than the latest.  But for reasons that I don't understand, neither CJ nor LinkShare would agree to make this simple change: and eventually, under pressure from their other publishers, they stopped doing business with us altogether, to nobody's benefit.&lt;br/&gt;&lt;br/&gt;I should note that this is made a little more complicated by the fact that some of the folks who advertised through Zango &lt;em&gt;did&lt;/em&gt; in fact engage in nefarious cookie stuffing and commission stealing.  The way that Zango's advertising system worked, an advertiser could make the link they insert do pretty much anything allowed by the browser sandbox.  And some of our advertisers did engage in commission stealing.  It was never possible to catch every instance of this, but we did our darned best, and implemented a number of processes, systems and features to catch folks who were trying to do so.  In the end, the extent of such third-party advertiser fraud was minimal.&lt;br/&gt;&lt;br/&gt;There's been a lot written about Zango "&lt;a href='http://blogs.zdnet.com/Spyware/?p=856'&gt;cookie stuffing&lt;/a&gt;", but I should say very clearly: Zango does not stuff cookies, has no interest in stealing somebody else's commission, and did everything it could to prevent this from happening.  Yes, Zango did display targeted ads, and would have liked to display ads from affiliate networks: but those ads introduced an ambiguity into the process which the affiliate networks refused to resolve.  The net result was that Zango was shut out from what once had been, and should have remained, a mutually beneficial and profitable advertising channel.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Zango financed its acquisitions with too much debt&lt;/strong&gt;, and not enough equity.  If you ask Keith what went wrong, this is what he'll tell you.  And while I don't believe it's the whole answer, he's got a point.  Zango was trying to fight a four-front war, keeping advertisers, publishers, content providers and users all happy simultaneously.  To do this requires a certain economy of scale.  And those economies of scale required a significant investment in user acquisition to maintain an adequate audience.  Unfortunately, because we financed our acquisitions primarily with debt rather than equity, we had to spend almost all our spare cash on servicing the debt, and were unable to adequately finance our publisher channels and direct-to-consumer advertising.  Due to this lack of investment, Zango's audience continued to shrink, which meant that we had more difficulty servicing the debt, which meant that we had even less to spend on user acquisition.  You see where I'm going with this.  If we had been willing to dilute ourselves more, we would have had smaller debt payments to make, which would have allowed us to continue investing in our audience.  It's all very simple once you point it out. 
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;If I get a chance and feel like it, I'll post another set of thoughts on what Zango did right: because while we ultimately weren't successful, we made a hell of a good run at it, and did a lot of impressive stuff along the way.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-8144393991109814914?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/8144393991109814914/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=8144393991109814914" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8144393991109814914?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/8144393991109814914?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/04/what-zango-got-wrong.html" title="What Zango Got Wrong" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;AkENQ3Y9cCp7ImA9WxJTEE4.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-417673307098417171</id><published>2009-04-18T00:11:00.001-07:00</published><updated>2009-04-18T00:11:32.868-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-18T00:11:32.868-07:00</app:edited><title>How Not to Acquire a Company</title><content type="html">&lt;span xmlns=''&gt;&lt;ol&gt;&lt;li&gt;String the banks and management team along for months.  Change the deal terms twenty times.
&lt;/li&gt;&lt;li&gt;Show up unannounced with a huge team 15 minutes after funding, when the CEO and former owner is out of the office.
&lt;/li&gt;&lt;li&gt;Immediately lock out everybody's email and network account.
&lt;/li&gt;&lt;li&gt;Post armed guards at every door.
&lt;/li&gt;&lt;li&gt;Break your word about how many people will be laid off and under what circumstances.
&lt;/li&gt;&lt;li&gt;Lay off nearly everybody, with a, ahem, promise that they might get hired back at some point.
&lt;/li&gt;&lt;li&gt;Try to run the remains of the company with approximately 20% of the people required to make it a success.
&lt;/li&gt;&lt;li&gt;Neglect to have an external communication plan in place to support existing customers and affiliates.
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Just in case you were wondering how it should be done.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-417673307098417171?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/417673307098417171/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=417673307098417171" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/417673307098417171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/417673307098417171?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/04/how-not-to-acquire-company.html" title="How Not to Acquire a Company" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUYHR38_fyp7ImA9WxVaEE4.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-367745158637490508</id><published>2009-04-06T08:52:00.001-07:00</published><updated>2009-04-06T08:52:16.147-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-06T08:52:16.147-07:00</app:edited><title>Things I Want to Do in Gmail and Can’t</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;On the whole, I like gmail.  I've almost entirely switched over to it, and the more I use it, the more I find that I like it.  (That's as opposed to some of my friends, who can't stand it.)  But there are several things that Google still needs to fix:
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;I can't change the subject line of a reply, even when the new topic is obviously unrelated to the original subject matter of the thread.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;I can't insert pictures into emails.  (I can &lt;em&gt;attach&lt;/em&gt; them, but that's not the same thing by a long shot.  Would Picasa or Flickr be as popular as they are if you had to download the pictures manually to see them?)&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;I can't get a horizontal line to show up between replies, a la Outlook.  This is probably just stylistic preference, but I like an &amp;lt;hr/&amp;gt; element to show up between replies in a thread, to make it easier to see where one reply leaves off and another starts.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;I can't easily delete a single email in a thread.  The vast majority of replies to a thread don't need to be saved, and just clutter things up if you don't get rid of them.  But it's a pain to select each individual response (the thread is initially collapsed, of course, so you can't easily distinguish between responses), and then with my mouse choose "Reply/Other Actions", "Delete", "Yes".  There should be a single keyboard shortcut for deleting the current message, just as there is for deleting the current thread.&lt;br/&gt;
				&lt;/li&gt;&lt;li&gt;I can't easily select multiple items to perform an action.  There are times when I want to select, say, 20 contiguous emails in a list.  This is easy in Outlook: select the first, press shift, and then select the last.  But in gmail you have to select all 20 individually, either with a mouse (uggh), or (slightly better) with the keyboard.
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Don't get me wrong: I'm very grateful that Google has at last added offline capabilities (which was a pretty neat trick for a webmail package), and the search is dramatically better than Outlook (or at least much faster).  And a whole new world opened up to me when I figured out that gmail had keyboard shortcuts.  (I should note, however, that gmail's keyboard shortcuts are of the utterly unintuitive, only-an-engineer-could-have-thought-of-this variety: how else do you explain "#" == "delete", "e" == "archive", and "u" == "return to inbox"?).  But now that they've got the big stuff nailed, they really need to finish their UI.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-367745158637490508?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/367745158637490508/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=367745158637490508" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/367745158637490508?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/367745158637490508?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/04/things-i-want-to-do-in-gmail-and-cant.html" title="Things I Want to Do in Gmail and Can’t" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0cCRH85cCp7ImA9WxVUE00.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-5637774987805151861</id><published>2009-03-17T09:57:00.001-07:00</published><updated>2009-03-17T09:57:45.128-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-17T09:57:45.128-07:00</app:edited><title>AIG and Congress</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;It's been amusing to watch the congressmen and women step all over themselves to condemn the $165MM in AIG executive bonuses.  Of course, it's silly and stupid for the AIG employees to expect these bonuses: were it not for the fact that taxpayers have stepped in, the traunche for their bonuses would fit somewhere behind the janitor's salary in AIG's bankruptcy proceedings.  If they get bonuses at all, it's from a sheer legal technicality.  
&lt;/p&gt;&lt;p&gt;But it's equally disingenuous for the members of our beloved Congress to insist, as I heard one member say, that "rewarding failure is not the American way."  As &lt;a href='http://www.msnbc.msn.com/id/29724816/'&gt;John Schoen&lt;/a&gt; of MSNBC has pointed out in a recent article, the various laws passed by Congress, or not passed by Congress, have contributed to this mess just as much as any extra-fancy financing from AIG's trading desk.  Most notably, in 2000, Congress (under Bill Clinton) passed the bi-partisan "&lt;a href='http://en.wikipedia.org/wiki/Commodity_Futures_Modernization_Act_of_2000'&gt;Commodity Futures Modernization Act&lt;/a&gt;", which, among other things, dramatically loosened regulations on derivative financial products, and created the multi-trillion dollar bubble which recently imploded under AIG.
&lt;/p&gt;&lt;p&gt;Chuck Grassley recently said that it would be the honorable thing for the AIG traders either to resign or commit suicide.  It would seem convenient to request that our congressional representatives uphold similar standards.  Unfortunately, we need them around, and for the same reason we need the AIG traders at their desks: the folks who got us into this mess are, regrettably, best positioned to get us out. &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-5637774987805151861?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/5637774987805151861/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=5637774987805151861" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/5637774987805151861?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/5637774987805151861?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/03/aig-and-congress.html" title="AIG and Congress" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;Dk8ASXo8eSp7ImA9WxVVEk0.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-3726822733608161551</id><published>2009-03-04T13:52:00.001-08:00</published><updated>2009-03-04T14:14:08.471-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-04T14:14:08.471-08:00</app:edited><title>Further Thoughts on WPF and XAML</title><content type="html">&lt;span xmlns=""&gt;&lt;p&gt;&lt;span xmlns=""&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span xmlns=""&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I started to play with WPF and XAML a couple weeks back, and wrote a &lt;a href="http://blog.wouldbetheologian.com/2009/02/initial-thoughts-on-wpf.html"&gt;post&lt;/a&gt; about my first thoughts.  Since then, I've been working through my first full-fledged WPF app, and I've figured out a ton more that I didn't understand at the time: both about the true strengths of WPF, and the things I still find really annoying.  So some more thoughts: &lt;/p&gt;&lt;li&gt;The ability to easily modify templated controls is amazing.  You can do things in minutes with a ListBox in XAML that would have taken months of tedious coding in WinForms.      &lt;/li&gt;&lt;li&gt;The WPF designer in Visual Studio sucks.  It gives you virtually no help in troubleshooting errors, it's slow, and among many other complaints, it is of no help whatsoever when you're trying to layout a DataTemplate.  I've been reduced to numerous long, painful cycles of, "change/compile/run/look/swear/change again".      &lt;/li&gt;&lt;li&gt;The WPF data-binding model is very powerful, but it's very subtle, difficult to get right, and very easy to get wrong.  If anyone at Microsoft actually believes the marketing-speak that it's "simple" in addition to powerful, they need to have their head examined.  For instance, I guess it's kinda cool that you can set bind properties on one control to another control, and can trigger behaviors when those properties change: but I can do this in a very straightforward way in C#, and in contrast, the XAML syntax for doing it is really annoying.  If you didn't know XAML pretty darned well, would you have any idea what the code below is doing?  (Hint: it displays a particular control when its parent ListBoxItem is selected.) &lt;/li&gt;&lt;div style="margin-left: 36pt"&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:590px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt"&gt;   &lt;p style="width: 723px"&gt;&lt;span style="font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;&lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;DataTrigger&lt;/span&gt;&lt;span style="color:red;"&gt; Binding&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; RelativeSource&lt;/span&gt;&lt;span style="color:blue;"&gt;={&lt;/span&gt;&lt;span style="color:#a31515;"&gt;RelativeSource&lt;/span&gt;&lt;span style="color:red;"&gt; Mode&lt;/span&gt;&lt;span style="color:blue;"&gt;=FindAncestor,&lt;/span&gt;&lt;span style="color:red;"&gt; AncestorType&lt;/span&gt;&lt;span style="color:blue;"&gt;={&lt;/span&gt;&lt;span style="color:#a31515;"&gt;x&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Type&lt;/span&gt;&lt;span style="color:red;"&gt; ListBoxItem&lt;/span&gt;&lt;span style="color:blue;"&gt;},&lt;/span&gt;&lt;span style="color:red;"&gt; AncestorLevel&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;1&lt;span style="color:blue;"&gt;},&lt;/span&gt;&lt;span style="color:red;"&gt; Path&lt;/span&gt;&lt;span style="color:blue;"&gt;=IsSelected}"&lt;/span&gt;&lt;span style="color:red;"&gt; Value&lt;/span&gt;&lt;span style="color:blue;"&gt;="True"&gt;    
    &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Setter&lt;/span&gt;&lt;span style="color:red;"&gt; Property&lt;/span&gt;&lt;span style="color:blue;"&gt;="Visibility"&lt;/span&gt;&lt;span style="color:red;"&gt; Value&lt;/span&gt;&lt;span style="color:blue;"&gt;="Visible"&lt;/span&gt;&lt;span style="color:red;"&gt; TargetName&lt;/span&gt;&lt;span style="color:blue;"&gt;="pledgeDetailsDockPanel" /&gt;    
   &lt;/span&gt;&lt;span style="color:#a31515;"&gt;DataTrigger&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;li&gt;XAML desperately needs some debugging aids.  Since it's a declarative and not a procedural language, it doesn't really make sense to "step through" code, but something like &lt;a href="http://getfirebug.com/"&gt;FireBug&lt;/a&gt; for XAML instead of HTML would make a ton of difference when you're trying to figure out why a particular {Binding} isn't working the way you expect.  (Which, in my limited experience, is fairly close to always.)      &lt;/li&gt;&lt;li&gt;Contrary to the raves I've read elsewhere, I'm convinced that XAML is an ugly, clunky language.  Granted, there are certain things that it allows you to express with great ease: instantiating a control, for instance, and setting its properties.  But if you have to interact with outside objects or even other controls in any but the most basic manner, things get ugly very quickly.  If you've ever worked with an ObjectDataSource, especially if you had to pass it dynamic method parameters, you know what I mean.  Compared to XAML in these instances, C++ is a model of clarity, and perl is a model of readability.  &lt;/li&gt;&lt;p&gt;Here's an example of what I mean on that last point.  Let's say that I've got a simple WPF app that converts Fahrenheit to Celsius, by calling the method ToCelsius() on a Fahrenheit class.  &lt;/p&gt;&lt;p&gt;In C# code-behind, I can get this to work with two lines of code: &lt;/p&gt;&lt;div style="margin-left: 18pt"&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:614px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;   &lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt" class="style1"&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;private&lt;/span&gt;           &lt;span style="color:blue;"&gt;void&lt;/span&gt; txtFahrenheit_TextChanged(&lt;span style="color:blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color:#2b91af;"&gt;TextChangedEventArgs&lt;/span&gt; e)     
    { &lt;span style="color:#2b91af;"&gt;     
    Fahrenheit&lt;/span&gt; temp = &lt;span style="color:blue;"&gt;new&lt;/span&gt;           &lt;span style="color:#2b91af;"&gt;Fahrenheit&lt;/span&gt;(txtFahrenheit.Text);     
       lblCelsius.Content = temp.ToCelsius();     
        }&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;Here's how you get those two lines of code to work in XAML (with all of the purely formatting attributes    and tags removed): &lt;/p&gt;&lt;div style="margin-left: 18pt"&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:614px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;   &lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt" class="style2"&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;&lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Grid.Resources&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
    &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ObjectDataProvider&lt;/span&gt;&lt;span style="color:red;"&gt; ObjectType&lt;/span&gt;&lt;span style="color:blue;"&gt;="{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;x&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Type&lt;/span&gt;&lt;span style="color:red;"&gt; local&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;Fahrenheit&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;:&lt;/span&gt;&lt;span style="color:red;"&gt;Key&lt;/span&gt;&lt;span style="color:blue;"&gt;="fahrenheit"&gt;     
        &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ObjectDataProvider.ConstructorParameters&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
            &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;system&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:#a31515;"&gt;String&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;system&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:#a31515;"&gt;String&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
        &lt;/span&gt;&lt;span style="color:#a31515;"&gt;ObjectDataProvider.ConstructorParameters&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
    &lt;/span&gt;&lt;span style="color:#a31515;"&gt;ObjectDataProvider&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
    &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ObjectDataProvider&lt;/span&gt;&lt;span style="color:red;"&gt; ObjectInstance&lt;/span&gt;&lt;span style="color:blue;"&gt;="{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;StaticResource&lt;/span&gt;&lt;span style="color:red;"&gt; fahrenheit&lt;/span&gt;&lt;span style="color:blue;"&gt;}"&lt;/span&gt;&lt;span style="color:red;"&gt; MethodName&lt;/span&gt;&lt;span style="color:blue;"&gt;="ToCelsius"&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;Key&lt;/span&gt;&lt;span style="color:blue;"&gt;="toCelsius" /&gt;     
    &lt;/span&gt;&lt;span style="color:#a31515;"&gt;Grid.Resources&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
    &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBox&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
    &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBox.Text&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
        &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding&lt;/span&gt;&lt;span style="color:red;"&gt; Source&lt;/span&gt;&lt;span style="color:blue;"&gt;="{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;StaticResource&lt;/span&gt;&lt;span style="color:red;"&gt; fahrenheit&lt;/span&gt;&lt;span style="color:blue;"&gt;}"&gt;     
            &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding.Path&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ConstructorParameters[0]&lt;/span&gt;&lt;span style="color:blue;"&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding.Path&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
            &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding.BindsDirectlyToSource&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;True&lt;/span&gt;&lt;span style="color:blue;"&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding.BindsDirectlyToSource&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;
            &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding.UpdateSourceTrigger&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;PropertyChanged&lt;/span&gt;&lt;span style="color:blue;"&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding.UpdateSourceTrigger&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;     
        &lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;           
                                 &lt;/span&gt;&lt;span style="color:blue;"&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBox.Text&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;          
         &lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBox&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;           
          &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Label&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;            
               &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Label.Content&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;             
                    &lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding&lt;/span&gt;&lt;span style="color:red;"&gt; Source&lt;/span&gt;&lt;span style="color:blue;"&gt;="{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;StaticResource&lt;/span&gt;&lt;span style="color:red;"&gt; toCelsius&lt;/span&gt;&lt;span style="color:blue;"&gt;}" /&gt;                
                   &lt;/span&gt;&lt;span style="color:#a31515;"&gt;Label.Content&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;                 
                &lt;/span&gt;&lt;span style="color:#a31515;"&gt;Label&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;      &lt;/td&gt;     &lt;/tr&gt;    &lt;/tbody&gt;   &lt;/table&gt;  &lt;/div&gt;  &lt;p&gt;   Those two lines of very simple, very comprehensible code have expanded into something   like 16 new lines of very dense, intricate, complicated XML. Oh, and have I mentioned that you &lt;em&gt;can't debug&lt;/em&gt;   those 16 lines of code? And if you look closely, you'll notice that there's a nice   ugly hack in there, where I do a sort of reverse-binding, with the Fahrenheit textbox   as the target of a binding to the first parameter in the Fahrenheit constructor.   You have to do this because the ObjectDataProvider is inexplicably not a DependencyObject, so you can't bind any of its properties to the properties of a control: you have to do it the other way around, and bind a control's properties to the ObjectDataProvider.&lt;/p&gt;  &lt;p&gt;Sigh.&lt;/p&gt;  &lt;p&gt;XAML and WPF still needs a bit of work.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-3726822733608161551?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/3726822733608161551/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=3726822733608161551" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/3726822733608161551?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/3726822733608161551?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/03/further-thoughts-on-wpf-and-xaml.html" title="Further Thoughts on WPF and XAML" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0YESHw5cSp7ImA9WxVVEU8.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-132674222613033443</id><published>2009-03-03T14:53:00.001-08:00</published><updated>2009-03-03T14:58:29.229-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-03T14:58:29.229-08:00</app:edited><title>The type initializer for ‘SomeClass’ threw an exception.</title><content type="html">&lt;span xmlns=""&gt;&lt;p&gt;&lt;span xmlns=""&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span xmlns=""&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I spent a good hour this afternoon troubleshooting a bizarre WPF designer error.  I've been working on an app for my church, and I was using an ObjectDataProvider in a particular page to return a "Donation" object from my data-layer with some appropriate defaults set. &lt;/p&gt;&lt;div&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:633px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt"&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;&lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ObjectDataProvider&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;Key&lt;/span&gt;&lt;span style="color:blue;"&gt;="defaultDonation"&lt;/span&gt;&lt;span style="color:red;"&gt; ObjectType&lt;/span&gt;&lt;span style="color:blue;"&gt;="{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;x&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Type&lt;/span&gt;&lt;span style="color:red;"&gt; classes&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;Data&lt;/span&gt;&lt;span style="color:blue;"&gt;}"&lt;/span&gt;&lt;span style="color:red;"&gt; MethodName&lt;/span&gt;&lt;span style="color:blue;"&gt;="GetNewDonation" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;This had been working fine for a while, but after I refactored a bit of the code in my data layer, the WPF designer stopped loading any form that touched this data layer.  It kept returning the error: &lt;/p&gt;&lt;div&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:638px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt"&gt;&lt;p&gt;The type initializer for 'WouldBeTheologian.PledgeManager.Classes.Data' threw an exception. &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;Interestingly enough, although the WPF forms wouldn't load, the project itself would run just fine; and specifically, the Data class would load and execute just fine.  But it's a pain and a half to lose IntelliSense, and to have no hint of what your XAML is gonna look like. &lt;/p&gt;&lt;p&gt;It took some work to figure out what was going on.  It turns out that after I refactored my Data class, I was instantiating a reference to my Entity Data Model during the class' constructor, like so: &lt;/p&gt;&lt;div&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:633px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt"&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;static&lt;/span&gt; Data()  
 {  
       pledgesEntities = &lt;span style="color:blue;"&gt;new&lt;/span&gt;           &lt;span style="color:#2b91af;"&gt;PledgesEntities&lt;/span&gt;();  
 }&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;But beneath the hood, when the EF tries to initialize its ObjectContext, it's doing so by reading the appropriate connection strings from the application's .config file.  That works fine when the "application" is, in fact, your own application.  But when it's called by the WPF designer, the "application" is Visual Studio, which (presumably) doesn't have the appropriate connection strings in its .config file; and hence the constructor throws an exception. &lt;/p&gt;&lt;p&gt;Once I figured this out, I fixed it by moving the instantiation of my Entity Data Model into a property, like so: &lt;/p&gt;&lt;div&gt;&lt;table border="0" style="border-collapse:collapse"&gt;&lt;colgroup&gt;&lt;col style="width:648px"&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td style="padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt"&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&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:#2b91af;"&gt;PledgesEntities&lt;/span&gt; pledgesEntities = &lt;span style="color:blue;"&gt;new&lt;/span&gt;           &lt;span style="color:#2b91af;"&gt;PledgesEntities&lt;/span&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:#2b91af;"&gt;PledgesEntities&lt;/span&gt; PledgesEntities  
 { &lt;span style="color:blue;"&gt;  
    get&lt;/span&gt;          
       { &lt;span style="color:blue;"&gt;  
        if&lt;/span&gt; (pledgesEntities == &lt;span style="color:blue;"&gt;null&lt;/span&gt;)  
               {  
                        pledgesEntities = &lt;span style="color:blue;"&gt;new&lt;/span&gt;           &lt;span style="color:#2b91af;"&gt;PledgesEntities&lt;/span&gt;();  
               } &lt;span style="color:blue;"&gt;  
        return&lt;/span&gt; pledgesEntities;  
       } &lt;span style="color:blue;"&gt;  
    set&lt;/span&gt; { pledgesEntities = &lt;span style="color:blue;"&gt;value&lt;/span&gt;; }  
 }&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;It's a bit uglier and infinitesimally slower, but it works. &lt;/p&gt;&lt;p&gt;Of course, I'm not the first person to figure out that the Visual Studio WPF designer &lt;em&gt;sucks&lt;/em&gt; at providing any help troubleshooting these errors.  Among many other things, there's no way to access the InnerException of the error in question, which is a serious limitation, and has bit me on several occasions.  Hopefully VS 2010 will fix this, though I haven't yet seen any firm indication that will be the case.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-132674222613033443?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/132674222613033443/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=132674222613033443" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/132674222613033443?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/132674222613033443?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/03/type-initializer-for-someclass-threw.html" title="The type initializer for ‘SomeClass’ threw an exception." /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkcBQ3Y6fSp7ImA9WxVWE0g.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-7187409031123979628</id><published>2009-02-22T16:38:00.000-08:00</published><updated>2009-02-22T16:47:32.815-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-22T16:47:32.815-08:00</app:edited><title>Ten Things Caedmon Learned Today</title><content type="html">&lt;ol&gt;&lt;li&gt;If you dig down under enough layers of leaves, you'll generally find dirt.&lt;/li&gt;&lt;li&gt;Dad can still shinny up some trees.&lt;/li&gt;&lt;li&gt;Dad can't shinny up other trees.&lt;/li&gt;&lt;li&gt;It's entertaining to watch Dad try to shinny up any tree.&lt;/li&gt;&lt;li&gt;Sometimes if you pull rotten logs apart, you can find a whole bunch of termites.&lt;/li&gt;&lt;li&gt;Termites squish when you poke them.&lt;/li&gt;&lt;li&gt;Dad will let you poke at coyote scat with a stick.&lt;/li&gt;&lt;li&gt;Dad won't let you pick coyote scat up in your hands.&lt;/li&gt;&lt;li&gt;The leaves sound funny when it rains.&lt;/li&gt;&lt;li&gt;If you get far enough out in the woods, Dad will let you beat on almost anything with a stick.
&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-7187409031123979628?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/7187409031123979628/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=7187409031123979628" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/7187409031123979628?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/7187409031123979628?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/02/ten-things-caedmon-learned-today.html" title="Ten Things Caedmon Learned Today" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DEECQX07fip7ImA9WxVXGE0.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-312197309543816032</id><published>2009-02-16T09:51:00.001-08:00</published><updated>2009-02-16T09:51:00.306-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-16T09:51:00.306-08:00</app:edited><title>More West Bank Settlements</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;&lt;a href='http://haaretz.com/hasen/spages/1064503.html'&gt;Haaretz&lt;/a&gt; is reporting that the Israeli Civil Administration has approved an additional 2500 acres worth of settlement expansion into the West Bank.  I'm a friend of Israel, make no mistake about it: but this is intolerable.  I simply don't understand how Israel can claim to take the peace process seriously when it continues to violate its own promises to the United States, to the Palestinians, and to the world.  This sort of behavior gives comfort and encouragement to the most radical of the Palestinian factions: it's what keeps Hamas and others of that ilk alive.  I simply don't understand why Israel doesn't get that this is dramatically counter to its own interests.
&lt;/p&gt;&lt;p&gt;Hopefully George Mitchell will deliver a loud and strong message to Israel that if Israel continues with these sorts of practices, they can expect much less cooperation and aid from the United States.  We've got a big lever here, and we need to help Israel even when Israel doesn't want to be helped.
&lt;/p&gt;&lt;p&gt;I've said before that Israel deals with the Palestinians like a chess player who can only think two moves ahead.  Peace won't come to the region until Israel learns to think five, 10 or 20 moves ahead.  (Lots of other things would also need to happen, like Hamas acknowledging Israel or being removed from power, but Israel learning to anticipate the consequences of its actions is a &lt;em&gt;sine qua non&lt;/em&gt;.)&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-312197309543816032?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/312197309543816032/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=312197309543816032" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/312197309543816032?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/312197309543816032?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/02/more-west-bank-settlements.html" title="More West Bank Settlements" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0AAQHw9cSp7ImA9WxJTEE4.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-6256623800441381831</id><published>2009-02-14T14:02:00.001-08:00</published><updated>2009-04-18T00:29:01.269-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-18T00:29:01.269-07:00</app:edited><title>My favorite gripes about .NET</title><content type="html">&lt;span xmlns=""&gt;&lt;p&gt;I've been coding primarily in .NET (VB.NET and C#) ever since it first came out, back in 2002, and on the whole, I think it's amazing.  Microsoft did a whole lot right when they created the .NET framework.
&lt;/p&gt;&lt;p&gt;I recently just took the .NET 3.5 certification exam, and studying for it, after a few years away from coding, gave me a chance to realize that MS also got a number of details wrong along the way.  Allow me to share my favorites:
&lt;/p&gt;&lt;h3&gt;Bizarre Side-effects
&lt;/h3&gt;&lt;p&gt;Much of the .NET framework was well-designed, with the poor coder who has to use it in mind.  But there are occasional pieces that make me shake my head.  For instance, imagine that you saw this code in someone's application: &lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span xmlns=""&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:#2b91af;"&gt;CspParameters&lt;/span&gt; cspParams = &lt;span style="color:blue;"&gt;new&lt;/span&gt;      &lt;span style="color:#2b91af;"&gt;CspParameters&lt;/span&gt;();
cspParams.KeyContainerName = &lt;span style="color:#a31515;"&gt;"MyKeyContainer"&lt;/span&gt;; &lt;span style="color:#2b91af;"&gt;
RSACryptoServiceProvider&lt;/span&gt; rsa = &lt;span style="color:blue;"&gt;new&lt;/span&gt;      &lt;span style="color:#2b91af;"&gt;RSACryptoServiceProvider&lt;/span&gt;(cspParams); &lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Unless you happened to know the CryptoAPI &lt;em&gt;very&lt;/em&gt; well, would you realize that this is how you create and store a key-pair?  In other words, creating and storing the key is a side-effect of calling the RSACryptoServiceProvider constructor, &lt;em&gt;if&lt;/em&gt; you happen to pass a CspParams object that &lt;em&gt;happens&lt;/em&gt; to have its KeyContainerName property set.&lt;/p&gt;&lt;p&gt;It should have been designed to work something like this, of course:&lt;/p&gt;&lt;p&gt;&lt;span class="Apple-style-span"    style="font-family:'Courier New';font-size:7;color:#2B91AF;"&gt;&lt;span class="Apple-style-span" style="font-size: 48px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span class="Apple-style-span"    style="font-family:'Courier New';font-size:7;color:#2B91AF;"&gt;&lt;p class="MsoNormal" style="margin-bottom:0in;margin-bottom:.0001pt;mso-layout-grid-align: none;text-autospace:none"&gt;&lt;span style="font-size:10.0pt;font-family:&amp;quot;Courier New&amp;quot;; color:#2B91AF;mso-no-proof:yes"&gt;RSACryptoServiceProvider&lt;/span&gt;&lt;span style="font-size:10.0pt;font-family:&amp;quot;Courier New&amp;quot;;mso-no-proof:yes"&gt; rsa = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2B91AF"&gt;RSACryptoServiceProvider&lt;/span&gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0in;margin-bottom:.0001pt;mso-layout-grid-align: none;text-autospace:none"&gt;&lt;span style="font-size:10.0pt;font-family:&amp;quot;Courier New&amp;quot;; mso-no-proof:yes"&gt;rsa.Key = &lt;span style="color:#2B91AF"&gt;RSACryptoServiceProvider&lt;/span&gt;.CreateKey();&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0in;margin-bottom:.0001pt;mso-layout-grid-align: none;text-autospace:none"&gt;&lt;span style="font-size:10.0pt;font-family:&amp;quot;Courier New&amp;quot;; mso-no-proof:yes"&gt;rsa.PersistKey(&lt;span style="color:#A31515"&gt;"MyKeyContainer"&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Bizarre Names
&lt;/h3&gt;&lt;p&gt;When you want to specify that it makes no sense for an assembly to run unless it has the permissions to open a file dialog box, you can flag that assembly with the following attribute:
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;[&lt;span style="color:blue;"&gt;assembly&lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;FileDialogPermission&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;SecurityAction&lt;/span&gt;.&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51);"&gt;RequestMinimum&lt;/span&gt;)]&lt;/span&gt;
 &lt;/p&gt;&lt;p&gt;And that makes some reasonable sense: you're saying that it needs, at a minimum, to be able to show the file dialog box.  Still, a better name would probably be something like "Require" than "RequestMinimum": it's less ambiguous.
&lt;/p&gt;&lt;p&gt;But if you want to step your security up a notch, and tell the runtime to automatically deny all permissions other than the ones you're listing, you use the enumeration SecurityAction.&lt;span style="background-;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51);"&gt;RequestOptional&lt;/span&gt;&lt;/span&gt;:
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;[&lt;span style="color:blue;"&gt;assembly&lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;FileDialogPermission&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;SecurityAction&lt;/span&gt;.&lt;span style="background-;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51);"&gt;RequestOptional&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51);"&gt;)]&lt;/span&gt;&lt;/span&gt;
 &lt;/p&gt;&lt;p&gt;To call required permissions "optional" makes absolutely no sense, and it makes it significantly more difficult for your average coder to figure out what's going on.  It would be much easier to understand if MS had chosen to call it something like "&lt;span style="background-;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51);"&gt;RefuseAllExcept&lt;/span&gt;&lt;/span&gt;":
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;[&lt;span style="color:blue;"&gt;assembly&lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;FileDialogPermission&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;SecurityAction&lt;/span&gt;.&lt;span style="background-;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51);"&gt;RefuseAllExcept&lt;/span&gt;&lt;/span&gt;)]&lt;/span&gt;
 &lt;/p&gt;&lt;p&gt;(For what it's worth, it's called "Optional" because whoever came up with the name was thinking from the perspective of the runtime: "Do I need to throw an exception if the assembly doesn't have this permission?  No?  OK, then it's an optional permission."  But you don't flag an assembly with this attribute because you're concerned to communicate that it might not need this permission: you add this attribute because you only get the permission you need, i.e., you want to make sure that the assembly is good and secure and only does things you're explicitly aware of, and that the runtime actively refuses to let it do anything you hadn't previously thought about.)
&lt;/p&gt;&lt;h3&gt;Screwy Parameter Orders
&lt;/h3&gt;&lt;p&gt;Certain methods and classes in the .NET framework typically take parameters in one order; but other methods and classes take them in a very different order.  There are numerous examples of this, but to take just one: if you want to format a string according to a specific culture using the String.Format() method, you pass parameters in the order "CultureInfo", "FormatString".
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:#2b91af;"&gt;String&lt;/span&gt;.Format(&lt;span style="color:blue;"&gt;new&lt;/span&gt;
   &lt;span style="color:#2b91af;"&gt;CultureInfo&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;"en-UK"&lt;/span&gt;), &lt;span style="color:#a31515;"&gt;"c"&lt;/span&gt;, 100)&lt;/span&gt;
 &lt;/p&gt;&lt;p&gt;But if you want to use the ToString() method of an object to format it, you pass them in the order "FormatString", "CultureInfo".
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;d.ToString(&lt;span style="color:#a31515;"&gt;"c"&lt;/span&gt;, &lt;span style="color:blue;"&gt;new&lt;/span&gt;
   &lt;span style="color:#2b91af;"&gt;CultureInfo&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;"en-UK"&lt;/span&gt;))
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Stupid things like that just make a framework harder to use than it needs to be: it's one more thing to remember in a world where I've already got too much going on.
&lt;/p&gt;&lt;h3&gt;Inconsistent Object Instantiation
&lt;/h3&gt;&lt;p&gt;In general, there are two different ways you can get an instance of a class: you can do it yourself, or you can get something else to do it for you.  Either one works fine, though there are &lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/instantiationFactory06232007153242PM/instantiationFactory.aspx"&gt;reasonably good arguments&lt;/a&gt; for preferring the second (known as a "Factory Pattern").  The problem is that the .NET framework is inconsistent throughout.  Some classes can only be instantiated with their own constructor:
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:#2b91af;"&gt;AppDomainSetup&lt;/span&gt; setup = &lt;span style="color:blue;"&gt;new&lt;/span&gt;
   &lt;span style="color:#2b91af;"&gt;AppDomainSetup&lt;/span&gt;();&lt;/span&gt;
 &lt;/p&gt;&lt;p&gt;Other closely related classes can only be instantiated through a static factory method:
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:#2b91af;"&gt;AppDomain&lt;/span&gt; domain = &lt;span style="color:#2b91af;"&gt;AppDomain&lt;/span&gt;.CreateDomain(&lt;span style="color:#a31515;"&gt;"My App Domain"&lt;/span&gt;);&lt;/span&gt;
 &lt;/p&gt;&lt;p&gt;And others can be instantiated either way:
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span xmlns=""&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:#2b91af;"&gt;Process&lt;/span&gt; process1 = &lt;span style="color:blue;"&gt;new&lt;/span&gt;      &lt;span style="color:#2b91af;"&gt;Process&lt;/span&gt;(); &lt;span style="color:#2b91af;"&gt;
Process&lt;/span&gt; process2 = &lt;span style="color:#2b91af;"&gt;Process&lt;/span&gt;.Start(&lt;span style="color:#a31515;"&gt;"cmd.exe"&lt;/span&gt;); &lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Frankly, I probably wouldn't care that much: it's mostly a stylistic difference, and the MS documentation is handy and usually pretty good.  But any number of questions in the 70-356 exam turn on knowing whether you use a static or an instance constructor, and remembering that you can only get an AppDomain object by calling a static constructor, but you can get a Process object either way, gets old after a while.
&lt;/p&gt;&lt;h3&gt;Event Handling in C#
&lt;/h3&gt;&lt;p&gt;I've been using VB since version 1.0, long before it was a commercially viable language, and long before it had anything like object-oriented features.  VB.NET is arguably a completely different language, but one of the things that remains very much the same, and very easy to do, is the handling of events.  The syntax for declaring them is simple and intuitive, and easy enough for nearly anyone to understand.  To handle an event in the most basic fashion, you have to specify four different "elements": you declare (1) the event and (2) the event handler, (3) you connect them by instantiating the event class using "WithEvents", and then (4) you raise the event.
&lt;/p&gt;&lt;p&gt;&lt;span xmlns=""&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;Class&lt;/span&gt; AlarmClock &lt;/span&gt;&lt;span class="Apple-style-span"   style="  ;font-family:'Courier New';font-size:13px;"&gt;  &lt;span style="color:blue;"&gt;
Public &lt;/span&gt;&lt;span style="color:blue;"&gt;Event&lt;/span&gt; Ring()&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;Sub&lt;/span&gt; MakeMeRing() &lt;/span&gt;&lt;span style=" ; margin-left: 40px;font-family:Courier New;font-size:10pt;"&gt;  &lt;span style="color:blue;"&gt;
    RaiseEvent&lt;/span&gt; Ring()&lt;/span&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;
End &lt;/span&gt;&lt;span style="color:blue;"&gt;Sub &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;End &lt;/span&gt;&lt;span style="color:blue;"&gt;Class &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;Class&lt;/span&gt; Sleeper &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;Public &lt;/span&gt;&lt;span style="color:blue;"&gt;WithEvents&lt;/span&gt; Alarm &lt;span style="color:blue;"&gt;As &lt;/span&gt;&lt;span style="color:blue;"&gt;New&lt;/span&gt; AlarmClock &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;      &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; WakeUp() &lt;span style="color:blue;"&gt;Handles&lt;/span&gt; Alarm.Ring
           Console.WriteLine(&lt;span style="color:#a31515;"&gt;"I'm awake, already."&lt;/span&gt;)&lt;span style="color:blue;"&gt;
End &lt;/span&gt;&lt;span style="color:blue;"&gt;Sub &lt;/span&gt; &lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;End &lt;/span&gt;&lt;span style="color:blue;"&gt;Class&lt;/span&gt;&lt;/span&gt;    &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;In contrast, in C#, for the most basic event, you have to follow seven steps.  You declare (1) the event (2) the event handler, and (3) instantiate the class holding the event.  You then wire up the event by (4) instantiating the delegate, and (5) adding it to the event.  You then raise the event by (6) checking if there are any handlers, and then finally (7) you raise the event.
&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:#2b91af;"&gt;&lt;span xmlns=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:#2b91af;"&gt;&lt;p&gt;&lt;span class="Apple-style-span"  style="color: rgb(0, 0, 255); font-size:13px;"&gt;&lt;span xmlns=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;AlarmClock
&lt;/span&gt;{
&lt;span style="color:blue;"&gt;    public &lt;/span&gt;&lt;span style="color:blue;"&gt;event E&lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ventHandler&lt;/span&gt; Ring;
&lt;span style="color:blue;"&gt;    public &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; MakeMeRing()
       { &lt;span style="color:blue;"&gt;
        if&lt;/span&gt; (Ring != &lt;span style="color:blue;"&gt;null&lt;/span&gt;)
               {
                       Ring(&lt;span style="color:blue;"&gt;this&lt;/span&gt;, &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;EventArgs&lt;/span&gt;());
               }
       }
} &lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;&lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Sleeper
&lt;/span&gt;{
&lt;span style="color:blue;"&gt;    public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;AlarmClock&lt;/span&gt; alarm = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;AlarmClock&lt;/span&gt;(); &lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 40px"&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;  &lt;span style="color:blue;"&gt;public&lt;/span&gt; Sleeper()
{
           alarm.Ring += &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;EventHandler&lt;/span&gt;(alarm_Ring);
} &lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=" ; margin-left: 40px;font-family:Courier New;font-size:10pt;"&gt;    &lt;span style="color:blue;"&gt;void&lt;/span&gt; alarm_Ring(&lt;span style="color:blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color:#2b91af;"&gt;EventArgs&lt;/span&gt; e) &lt;/span&gt;&lt;span style=" ;font-family:Courier New;font-size:10pt;"&gt;    
       { &lt;span style="color:#2b91af;"&gt;
        Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"I'm awake, already."&lt;/span&gt;);
       }
} &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;    &lt;/span&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;For only one of those steps (declaring the event) does the language itself provide any structure for you: you otherwise have to use other unrelated language elements, such as delegates, constructors, and operator overrides: and you have to understand each of these, and think about each of these, before you can raise and handle events.  In contrast, with VB, you only have to think about events, and not about three or four other unrelated language elements.
&lt;/p&gt;&lt;p&gt;I'll grant that the C# implementation is elegant and flexible: but if you want, you can do it the same way in VB.  VB just provides an alternate, much simpler way of handling simple events.  The C# team has implemented plenty of cool features like LINQ, anonymous methods, generics, extension methods, nullable value types, and all sorts of other cool things.  It's a shame that they haven't figured out a simpler way of raising and handling events.
ents.
&lt;/p&gt;&lt;p&gt;I've got more gripes – of course &lt;span style="font-family:Wingdings;"&gt;J&lt;/span&gt; – but the rest will have to wait.
&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-6256623800441381831?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/6256623800441381831/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=6256623800441381831" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/6256623800441381831?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/6256623800441381831?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/02/my-favorite-gripes-about-net.html" title="My favorite gripes about .NET" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DEANRXcyfCp7ImA9WxVXFkk.&quot;"><id>tag:blogger.com,1999:blog-4828094184184324789.post-4572645160953169756</id><published>2009-02-14T13:26:00.001-08:00</published><updated>2009-02-14T13:26:34.994-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-14T13:26:34.994-08:00</app:edited><title>Interesting Recommendation</title><content type="html">&lt;span xmlns=''&gt;&lt;p&gt;I received an email from Amazon today, with the following recommendation in it:
&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:638px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  solid black 0.5pt; border-left:  solid black 0.5pt; border-bottom:  solid black 0.5pt; border-right:  solid black 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Arial; font-size:7pt'&gt;Dear Amazon.com Customer,
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:black; font-family:Arial; font-size:7pt'&gt;We've noticed that customers who have purchased or rated books by &lt;span style='background-color:yellow'&gt;Aristotle&lt;/span&gt; have also purchased &lt;em&gt;If You Got It, A Truck Brought It: Our First Adventure&lt;/em&gt; by Robin Smith. For this reason, you might like to know that &lt;em&gt;If You Got It, A Truck Brought It: Our First Adventure&lt;/em&gt; is now available.  You can order yours for just $8.99 by following the link below.
&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:190px'/&gt;&lt;col style='width:434px'/&gt;&lt;col style='width:0px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-right: 4px' colspan='2'&gt;&lt;p&gt;&lt;a href='http://www.amazon.com/gp/r.html?R=A16W32VHWQFA&amp;amp;C=122TAF60VIYW9&amp;amp;H=kNrhLc71AQEPy5mbeurTAbUrYQoA&amp;amp;T=C&amp;amp;U=http%3A%2F%2Fwww.amazon.com%2Fgp%2Fproduct%2F1438939469%2Fref%3Dpe_5050_11287830_pe_snp_469'&gt;&lt;img border='0' alt='' src='http://wouldbetheologian.com/images/021409_2126_Interesting1.jpg'/&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='padding-left: 4px'&gt;&lt;p&gt;&lt;a target='_blank' href='http://www.amazon.com/gp/r.html?R=A16W32VHWQFA&amp;amp;C=122TAF60VIYW9&amp;amp;H=kNrhLc71AQEPy5mbeurTAbUrYQoA&amp;amp;T=C&amp;amp;U=http%3A%2F%2Fwww.amazon.com%2Fgp%2Fproduct%2F1438939469%2Fref%3Dpe_5050_11287830_pe_snp_469'&gt;&lt;span style='color:#1c51a8; font-family:Arial; font-size:12pt; text-decoration:underline'&gt;If You Got It, A Truck Brought It: Our First Adventure&lt;/span&gt;&lt;/a&gt;&lt;span style='font-family:Arial; font-size:12pt'&gt; &lt;br/&gt;Robin Smith 
&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:50px'/&gt;&lt;col style='width:45px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr&gt;&lt;td style='padding-top: 1px; padding-left: 1px; padding-bottom: 1px; padding-right: 1px' vAlign='middle'&gt;&lt;p style='text-align: right'&gt;&lt;span style='font-family:Arial; font-size:12pt'&gt;&lt;strong&gt;Price:&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='padding-top: 1px; padding-left: 1px; padding-bottom: 1px; padding-right: 1px' vAlign='middle'&gt;&lt;p&gt;&lt;span style='color:#990000; font-family:Arial; font-size:12pt'&gt;&lt;strong&gt;$8.99&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;span style='font-family:Arial; font-size:12pt'&gt;&lt;br/&gt;&lt;br/&gt;&lt;/span&gt; &lt;/p&gt;&lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;span style='color:black; font-family:Arial; font-size:7pt'&gt;&lt;strong&gt;Product Description&lt;/strong&gt;&lt;br/&gt;With bright colorful illustrations and adorable characters, Josie and her freewheeling friends take you on an adventure to learn how a book is made.Along the way we'll get a start on learning colors, numbers and the alphabet.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Notice the basis of the recommendation: because I'd purchased books by &lt;span style='background-color:yellow'&gt;Aristotle&lt;/span&gt;, they recommended a particular children's book.  I smell a statistical cluster in there somewhere.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4828094184184324789-4572645160953169756?l=blog.wouldbetheologian.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.wouldbetheologian.com/feeds/4572645160953169756/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4828094184184324789&amp;postID=4572645160953169756" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/4572645160953169756?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4828094184184324789/posts/default/4572645160953169756?v=2" /><link rel="alternate" type="text/html" href="http://blog.wouldbetheologian.com/2009/02/interesting-recommendation.html" title="Interesting Recommendation" /><author><name>Ken Smith</name><uri>http://www.blogger.com/profile/09031647503349727336</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="01126861345069534720" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
