﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>WPF Hackery!</title>
    <description>Anything software/technology related</description>
    <link>http://jmorrill.hjtcentral.com/Home/tabid/428/BlogId/14/Default.aspx</link>
    <language>en-US</language>
    <webMaster>jeremiah.morrill@gmail.com</webMaster>
    <pubDate>Fri, 12 Mar 2010 15:32:20 GMT</pubDate>
    <lastBuildDate>Fri, 12 Mar 2010 15:32:20 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.5.0.35082</generator>
    <item>
      <title>Silverlight 4 Hack:  Use Native/Desktop CLR Without COM Registration</title>
      <description>&lt;p&gt; &lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;WARNING&lt;/strong&gt;: Information and code here can easily be abused.  Please do not use it as a crutch in application planning, but more for utter despair or experimentation.  Thus I wrote this blog post from &lt;em&gt;that&lt;/em&gt; perspective.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Silverlight 4 + OOB + Elevated Trust gives us the ability to use COM.  That would be extremely useful (vs. really useful), except we cannot use just any COM class.  It has to support IDispatch (COM automation).  It also has to have a ProgID associated to it.  That leaves you still with quite a few built-in COM objects to work with, as &lt;a href="http://justinangel.net/#BlogPost=CuttingEdgeSilverlight4ComFeatures"&gt;Justin document's quite well here.&lt;/a&gt;  What about running our own native or .NET code?  One would have to register a COM object first, which requires administrator rights.  That’s no fun for an end user!  Optimally, it would be nice to be able to add your desktop CLR objects as resources to your XAP, and from Silverlight code, be able to instantiate and use your Desktop .NET classes.  This is a hack to do just that.&lt;/p&gt; &lt;h1&gt;Huh?  What does the hack do?&lt;/h1&gt; &lt;p&gt;Let me explain it in code.&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', 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: 'Courier New', 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: #008000"&gt;/* Create our Desktop .NET helper */&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;dynamic fullDotNetProxy = fullDotNetProxy = ComAutomationFactory.CreateObject(&lt;span style="color: #006080"&gt;"ClrProxy"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', 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: #008000"&gt;/* Have our .NET helper load up our .NET assembly we extracted from our SL app resources */&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;dynamic assembly = fullDotNetProxy.GetAssembly(m_assembliesPath + &lt;span style="color: #006080"&gt;"\\Inject.Test.dll"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', 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: #008000"&gt;/* Get our .NET Type */&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;dynamic testClassType = fullDotNetProxy.GetDotNetType(assembly, &lt;span style="color: #006080"&gt;" Inject.Test.TestClass"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', 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: #008000"&gt;/* Create an object instance of our .NET type */&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;m_testClass = fullDotNetProxy.CreateInstance(testClassType);&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', 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: #008000"&gt;/* Run our RunMe method on our .NET object */&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;m_testClass.RunMe();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Hold on a second!  Where did “ClrProxy” ProgID come from?  That’s not built in to Windows!  I thought we didn’t have to register anything?&lt;/h2&gt;
&lt;p&gt;That’s where it gets complicated.  Or hacky.  We actually use COM interop to inject a native DLL into the Silverlight process.  Once injected we override some native methods that Silverlight uses internally to instantiate COM.  Our hooked methods listens for when a ProgID of “ClrProxy” is requested and then goes into action.&lt;/p&gt;
&lt;h2&gt;Not bored yet.  Explain further.&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Use WScript.Shell's "Run" method to execute rundll32.exe&lt;/li&gt;
&lt;li&gt;Rundll32.exe executes my native.dll.&lt;/li&gt;
&lt;li&gt;My native.dll get's the process Id and hWnd of the process that started it up (The Silverlight OOB Process)&lt;/li&gt;
&lt;li&gt;The native.dll is injected into the Silverlight process's and hooks it's WndProc&lt;/li&gt;
&lt;li&gt;The Silverlight process the hooks two methods in ole32.dll used by all windows applications to create COM objects&lt;/li&gt;
&lt;li&gt;In Silverlight code, every time you call &lt;i&gt;ComAutomationFactory.CreateObject("&lt;b&gt;ClrProxy&lt;/b&gt;") &lt;/i&gt;my hook will detect it and return a .NET 2.0 CLR object.  The real CLR proxy class is very simple and I only expose some reflection routines so I can load up any .NET Dll.  Silverlight facing code still uses the dynamic keyword.  &lt;/li&gt;&lt;/ol&gt;
&lt;h2&gt;So where do I get the code and how do I run the demo?&lt;/h2&gt;
&lt;p&gt;How to run the demo:
&lt;ol&gt;
&lt;li&gt;Load up the project.  Set the Silverlight web app as start up.&lt;/li&gt;
&lt;li&gt;Run the project, and install the SL app OOB.&lt;/li&gt;
&lt;li&gt;Click the only button on the window and watch SL talk to a .NET class w/o any registration&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;I left all the compiled dlls in there in case you were having trouble compiling the C++.&lt;/p&gt;
&lt;p&gt;Here is the code:&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:b6f335df-0764-4e69-b4d8-d6bec8b83e49" class="wlWriterEditableSmartContent"&gt;&lt;p&gt;&lt;div&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/Silverlight4HackUseNativeDesktopCLRWitho_10EC4/Silverlight.Mainline.Example.zip" target="_self"&gt;Silverlight.Mainline.Example.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/div&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/442/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/442/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/442/Default.aspx</guid>
      <pubDate>Fri, 05 Feb 2010 03:18:05 GMT</pubDate>
      <slash:comments>18</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=442</trackback:ping>
    </item>
    <item>
      <title>Silverlight and Desktop .NET Integration</title>
      <description>&lt;p&gt;No matter how you feel about Silverlight 4’s COM interop, it does add an escape hatch out the sandbox when you are running an out-of-browser application.  I don’t see many .NET folks getting excited about having to wipe off the dust on their C++ compiler and learn COM all over again for the first time.&lt;/p&gt; &lt;p&gt;Here I want to show a way of making a COM object in pure desktop .NET and using it from Silverlight.  This stuff has been around since the dawn of .NET, but it may be a little more obscure to others who have never done it.&lt;/p&gt; &lt;h1&gt;Step 1:&lt;/h1&gt; &lt;p&gt;Create a new Silverlight 4 application and add a desktop .NET class library (show here as the “COMObject” project)&lt;/p&gt; &lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_thumb.png" width="269" height="414"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;h1&gt;Step 2:&lt;/h1&gt; &lt;p&gt;Setup your Silverlight application to support out-of-browser support AND don’t forget about the elevated trust!&lt;/p&gt; &lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_thumb_1.png" width="553" height="432"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;h1&gt;Step 3:&lt;/h1&gt; &lt;p&gt;Get your desktop .NET class library ready for COM.  In the project settings of the class library set your stuff up like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_thumb_2.png" width="277" height="294"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;This setting bellow is NOT required, but is there for convenience so you don’t have to manually run “regasm” to register your assembly. &lt;strong&gt;YOU MUST RUN VS2010 WITH ADMINISTRATOR RIGHTS IF YOU HAVE THIS OPTION!&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_8.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_thumb_3.png" width="431" height="152"&gt;&lt;/a&gt; &lt;/p&gt; &lt;h1&gt;Step 4:&lt;/h1&gt; &lt;p&gt;In your desktop .NET class library add a class like this:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;[ProgId(&lt;span style="color: #006080"&gt;"SilverlightCOM.Example"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;[ClassInterface(ClassInterfaceType.AutoDual)]&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;[Guid(&lt;span style="color: #006080"&gt;"5267F53A-0E5F-490A-A891-FFE8B3840D72"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ComClass&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    [ComVisible(&lt;span style="color: #0000ff"&gt;true&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RunMe()&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        System.Windows.Forms.MessageBox.Show(&lt;span style="color: #006080"&gt;"Hello from .NET via COM!"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;strong&gt;Make sure to give it your own GUID and ProgId!&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;
&lt;h1&gt;Step 5&lt;/h1&gt;
&lt;p&gt;In your Silverlight project add some code like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;dynamic comClass = ComAutomationFactory.CreateObject(&lt;span style="color: #006080"&gt;"SilverlightCOM.Example"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;comClass.RunMe();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h1&gt;Step 6:&lt;/h1&gt;
&lt;p&gt;Run your Silverlight application and install it out-of-browser and you are done!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_10.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/image_thumb_4.png" width="328" height="338"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1&gt;Conclusion:&lt;/h1&gt;
&lt;p&gt;Yeah its that easy.  If you need to manually register your assembly manually, use regasm!&lt;/p&gt;
&lt;h1&gt;The source code&lt;/h1&gt;&lt;strong&gt;&lt;/strong&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:d42efd13-0440-4fd4-9ee4-278ebb79b8e1" class="wlWriterEditableSmartContent"&gt;&lt;p&gt;&lt;div&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/SilverlightandDesktop.NETIntegration_13DAF/SilverlightCOM.zip" target="_self"&gt;SilverlightCOM.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/div&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/441/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/441/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/441/Default.aspx</guid>
      <pubDate>Wed, 13 Jan 2010 06:38:03 GMT</pubDate>
      <slash:comments>14</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=441</trackback:ping>
    </item>
    <item>
      <title>Render Silverlight in WPF – WPF SilverlightViewport</title>
      <description>&lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/RenderSilverlightinWPF_12BF2/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/RenderSilverlightinWPF_12BF2/image_thumb.png" width="446" height="297"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;A hobby project I have been working on, to clear my mind of the daily grind, is a Control that lets a developer host a Silverlight application to WPF.&lt;/p&gt; &lt;p&gt;A good kept secret is there is complete &lt;a href="http://msdn.microsoft.com/en-us/library/cc296246(VS.95).aspx"&gt;COM API for hosting Silverlight&lt;/a&gt; outside the browser.  There is even &lt;a href="http://code.msdn.microsoft.com/silverlightalthost"&gt;sample C++ code here&lt;/a&gt;.  The problem I found with all of these was everything assumed you are rendering to Win32/Windowed.  This is not the kind of thing we want in a WPF application.  Airspace restrictions are for weenies.  &lt;/p&gt; &lt;p&gt;I had remembered that Silverlight DOES infact support windowless.  That given, I wrote a host in C# to load Silverlight windowless and had it render to my own GDI bitmap, instead of the screen.  That worked well, but CPU usage was high and I didn’t get any alpha transparency.  After some more research I found that the native SDK supports rendering to an ARGB buffer!  After some more nasty, dirty native interop, I got it working with alpha transparency…and performance was much better.&lt;/p&gt; &lt;p&gt;I did start out using the WriteableBitmap, but eventually moved over to use InteropBitmap and performance got even better!&lt;/p&gt; &lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/RenderSilverlightinWPF_12BF2/image_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/RenderSilverlightinWPF_12BF2/image_thumb_1.png" width="384" height="307"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Anyways, there’s still a lot of work to be done, but I’m excited enough about it to show it off now.&lt;/p&gt; &lt;p&gt;Try it out at: &lt;a href="http://silverlightviewport.codeplex.com"&gt;http://silverlightviewport.codeplex.com&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Update:  I also want to thank Koen Zwikstra, for &lt;a href="http://silverlightspy.com/blog/hosting-silverlight-outside-the-browser-sourcecode/"&gt;his project helped&lt;/a&gt; me prototype the original code.  I’ve since rewrote everything, but you may find some things similar.  This is why ;)  &lt;/p&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/439/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/439/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/439/Default.aspx</guid>
      <pubDate>Mon, 21 Dec 2009 03:06:07 GMT</pubDate>
      <slash:comments>11</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=439</trackback:ping>
    </item>
    <item>
      <title>How to get access to WPF’s internal Direct3D guts</title>
      <description>&lt;p&gt;This one isn’t for the faint of heart, but if you are a Direct3D guru and always wanted some more low level access…here is a good start.  This hack does a overwrites IDirect3DSwapChain9::Present method in memory to hook into the call WPF makes.  In that hook, I also pull out the IDirect3DDevice9 pointer.&lt;/p&gt; &lt;p&gt;What can we do with this?  Well for one, it would be possible to render WPF to a texture in a Direct3D scene.  You can also fiddle with the WPF rendering process.  And if you are really tricky, you can probably even do something even more amazing.&lt;/p&gt; &lt;p&gt;Given the time, I’d like to make a few examples, but for now, here is what I got.&lt;/p&gt; &lt;p&gt;You need the DX and Winders SDKs&lt;/p&gt; &lt;p&gt; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:5c7d3e18-ff1c-4da4-84d1-3918e7683777" class="wlWriterEditableSmartContent"&gt;&lt;p&gt;&lt;div&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/HowtogetaccesstoWPFsinternalDirect3Dguts_496/WPFD3Dhack.zip" target="_self"&gt;WPFD3Dhack.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/div&gt;&lt;/p&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/438/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/438/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/438/Default.aspx</guid>
      <pubDate>Sun, 06 Dec 2009 08:21:15 GMT</pubDate>
      <slash:comments>10</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=438</trackback:ping>
    </item>
    <item>
      <title>Direct3D 10/11 &amp; Direct2D in WPF</title>
      <description>&lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/Direct3D1011Direct2DinWPF_D01E/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/Direct3D1011Direct2DinWPF_D01E/image_thumb.png" width="277" height="331"&gt;&lt;/a&gt;For a while, I’ve wanted to tackle getting the newest Direct3D technologies to interop with WPF.  Direct3D 10/11 and Direct2D all have very cool usage scenarios that are just impossible with the WPF API.&lt;/p&gt; &lt;p&gt;So far the only solutions I have seen to interop WPF and it’s cousin D3D technologies was to use hWnd interop.  If you gotta have airspace restrictions, why even bother?  Nobody really &lt;em&gt;wants&lt;/em&gt; a hot, steamy, always-on-top hWnd hovering over their super cool WPF interface.&lt;/p&gt; &lt;p&gt;So how do we render D3D10/11 and D2D into WPF w/o airspace issues?  We only have a D3DImage class that supports Direct3D9.  Well the fine people of the WPF team informed me that a IDirect3DDevice9Ex, which is the recommended device to use with D3DImage in Vista/7, supports sharing resources between devices (and processes too if you care).  We can create a shared render target on Direct3D10/11, then pull it in via an intermediate IDirect3DDevice9Ex device.  No copying required!  This resource we pull into 9Ex, can then be sent to the D3DImage for high performance rendering.  I have not benchmarked anything, but just eyeing CPU performance, it does not seem to have any extra overhead in sharing the resources.  Performance seems to be similar (if not the same) to using D3DImage with 9Ex and unshared surfaces.&lt;/p&gt; &lt;p&gt;I’ve created a D3DImage subclass to add support for D3D 10/11 render targets (Texture2D).  Usage is simple:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', 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: 'Courier New', 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;/* Set the back buffer, which is a ID3D10Texture2D pointer */&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: 'Courier New', 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; m_d3DImageEx.SetBackBufferEx(D3DResourceTypeEx.ID3D10Texture2D, pRenderTarget);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;One caveat is the D3D 10/11 render targets must be created as  D3D10_RESOURCE_MISC_SHARED.  The other caveat is I don’t handle lost devices (which only happens in a few situations with 9Ex, like driver being upgraded) just yet so I don’t recommend using this in production at the moment.&lt;/p&gt;
&lt;p&gt;Also the D3D10 scene code is very sloppy and was pieced together from other samples.  It’s also in C++, but I’ll do some managed examples later on.&lt;/p&gt;
&lt;p&gt;To compile make sure you have the latest &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b66e14b8-8505-4b17-bf80-edb2df5abad4&amp;displaylang=en"&gt;DirectX SDK&lt;/a&gt; and &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&amp;displaylang=en"&gt;Windows SDK&lt;/a&gt;!&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:9f8d27ee-376c-4c57-ab8e-bcd7bf82dbca" class="wlWriterEditableSmartContent"&gt;&lt;p&gt;&lt;div&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/Direct3D1011Direct2DinWPF_D01E/Interop.D3DImageEx.zip" target="_self"&gt;Interop.D3DImageEx.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/div&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/437/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/437/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/437/Default.aspx</guid>
      <pubDate>Fri, 27 Nov 2009 19:22:19 GMT</pubDate>
      <slash:comments>24</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=437</trackback:ping>
    </item>
    <item>
      <title>Channel 9 Interview</title>
      <description>&lt;p&gt;&lt;a href="http://channel9.msdn.com/shows/Coding4FunTV/The-Coding4Fun-Show-WPF-MediaKit-with-Jeremiah-Morrill/"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/Channel9Interview_D230/image_3.png" width="378" height="242"&gt;&lt;/a&gt;About a month or so ago, I did an interview with &lt;a href="http://brianpeek.com/blog/"&gt;Brian Peek&lt;/a&gt; (of much fame, ie WiiRemote .NET lib) to show off my WPF MediaKit project.  Today it &lt;a href="http://channel9.msdn.com/shows/Coding4FunTV/The-Coding4Fun-Show-WPF-MediaKit-with-Jeremiah-Morrill/"&gt;went live&lt;/a&gt;!  This is my very first interview…on camera or otherwise.&lt;/p&gt; &lt;p&gt;Mad props to Brian for having me!  And many thanks to the Coding4Fun team!&lt;/p&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/434/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/434/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/434/Default.aspx</guid>
      <pubDate>Mon, 19 Oct 2009 21:57:43 GMT</pubDate>
      <slash:comments>12</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=434</trackback:ping>
    </item>
    <item>
      <title>Anatomy of an MVVM Application *or* How Tards Like Me Make MVVM Apps</title>
      <description>&lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_thumb.png" width="266" height="317"&gt;&lt;/a&gt;This article is a continuation of my &lt;a href="http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/MVVM-for-Tarded-Folks-Like-Me-or-MVVM-and-What-it-Means-to-Me.aspx"&gt;“MVVM for Tarded Folks Like Me”.&lt;/a&gt;  The aim here is not to teach the basics.  There’s plenty of information on that out there.  Even a tard should be able use &lt;em&gt;the&lt;/em&gt; Google.   My general intention is to give some guidance on &lt;strong&gt;hurdles&lt;/strong&gt; that any developer who &lt;em&gt;doesn’t&lt;/em&gt; have 1500ccs of brain matter might come across while learning how to develop an MVVM application.  &lt;/p&gt; &lt;p&gt;I believe bullshit information to be a major hurdle in making well designed MVVM applications.  So I wanted to kick this one off with my favorite myth…&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;:  &lt;em&gt;I’m going to speak mostly in the context of Silverlight from here on.  Why?  I want to talk least common denominator.  There’s just so many ways to do things in WPF, I can’t and won’t cover them all.  In any case, all concepts here are transferable to WPF.  This is also where I get into style and opinion, so it’s going to be quite subjective.  It may even piss some people off.  Great!&lt;/em&gt;&lt;/p&gt; &lt;h1&gt;“MVVM is an Overcomplicated Turd”&lt;/h1&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;No, &lt;strong&gt;your &lt;/strong&gt;code is.  I can make this counter-claim with a level of certainty.  Because I’m a pompous, MVVM-advocating prick?  I don’t &lt;em&gt;think&lt;/em&gt; I am, but that’s not really for &lt;em&gt;me&lt;/em&gt; to say.  In my previous article, I break MVVM down to what it is [for WPF/SL] at the core.  It’s binding to a class that &lt;u&gt;specifically deals with data for the UI&lt;/u&gt;.  If that’s too complicated, research it some more.  You are of reasonable intelligence.  I believe in &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Where MVVM starts to get complicated, is when you start using other &lt;em&gt;patterns&lt;/em&gt; to help out with your MVVM-fu.  This is when you feel the need to pass some event or data across the View/ViewModel barrier.  It gets “complex” when you want one ViewModel to communicate with another, &lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_thumb_2.png" width="240" height="188"&gt;&lt;/a&gt;even though your VMs don’t have direct reference.  One accepted practice is to use commanding for your View to talk to your ViewModel.  Use a mediator to get your ViewModels to talk in a loosely coupled manner.  If you want to see how to use commanding and a mediator, check out &lt;a href="http://www.galasoft.ch/mvvm/getstarted/"&gt;Laurent Bugnion’s MVVM Light library&lt;/a&gt;.  He’s got implementations of both.  To better illustrate my point, lets look at how many &lt;a href="http://msdn.microsoft.com/en-us/library/dd458924.aspx"&gt;patterns are supported under Prism&lt;/a&gt;.  There are at least 13 other patterns NOT MVVM dependant.  That’s quite a bit of non-MVVM for what some folks label as an “MVVM Framework”.&lt;/p&gt; &lt;p&gt;There is a &lt;a href="http://forums.silverlight.net/forums/t/127825.aspx"&gt;great post on Silverlight.net&lt;/a&gt; that I recognize as the epitome of MVVM gone &lt;em&gt;bad&lt;/em&gt;.  It’s MVVM perversion.  It’s quite long, so I understand not reading all the way though, so I’ll paraphrase.  &lt;/p&gt; &lt;p&gt;JFalcon is &lt;em&gt;not&lt;/em&gt; happy and we end up sympathizing with him.  We feel bad for his situation.  He’s a &lt;em&gt;victim&lt;/em&gt;.  His architect, who does sound like an MVVM-&lt;strong&gt;purist &lt;/strong&gt;prick, has him developing a numeric spinner control.  His requirements were to create a view-model for this control and implement commands to handle the up/down clicks for the spinner.  &lt;/p&gt; &lt;p&gt;If that last sentence didn’t raise any flags for you, well don’t worry because it certainly would not have when I started MVVM.  “Isn’t this how you do MVVM apps?”, the green-eared, tarded developer might say.  &lt;em&gt;HELL &lt;/em&gt;NO! Let me explain further…&lt;/p&gt; &lt;h1&gt;A View is a Control, a &lt;em&gt;Control&lt;/em&gt; is a Control.  A Control is Not a View? |or| Yet Another Stupid Programming Analogy&lt;/h1&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_10.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_thumb_4.png" width="451" height="244"&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Let’s define what a view is.  It’s your “Presentation”, what you “see”, right?  Yes!  So a&lt;strong&gt; Button&lt;/strong&gt; is something I can see.  That’s a view too!  &lt;strong&gt;No!&lt;/strong&gt;  That’s a &lt;em&gt;control&lt;/em&gt;.  Before I confuse you (and myself) any more, lets make a real-world analogy.  One of those contrived comparisons that fall apart if you look too deep.  Maybe something about a car…or a mammal…or…I know!&lt;/p&gt; &lt;p&gt;You’ve all had to sit through a play before, right?  Maybe it was Nutcracker or Phantom of the Opera, Lion King on Ice…doesn’t matter.  If the answer is “yes”,  well I’m sorry, I hate the theater too.  But at least you may get where I’m going with this.  The point is you have a script, a stage and some actors and props.  The actors, they perform on the stage.  They perform based off a common script.&lt;/p&gt; &lt;p&gt;Lets bring it back to that analogy I was promising.  A view is like a stage.  It brings all the actors, or CONTROLS, together.  The controls perform based off a script or &lt;em&gt;ViewModel&lt;/em&gt;. &lt;/p&gt; &lt;p&gt;Can I have another view within my view, side-by-side with the actors/controls?  &lt;strong&gt;Yes!&lt;/strong&gt;  But I didn’t want to confuse my theater comparison &lt;em&gt;just&lt;/em&gt; yet.  But do realize that a view inside a View is ultimately how a non trivial application is composed, but for the concepts I’m dropping, a view should see any contained view as a Control.&lt;/p&gt; &lt;p&gt;Here are some ground rules that I use when deciding if I need a control or a view.  I am no authority on any of this, and even though I talk about my &lt;em&gt;rules&lt;/em&gt;…I have broken them all in my applications.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;You want to make a control (actor) when:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Anytime you need to use the VSM or animations.  I don’t believe you should ever directly use the VSM (ie give your View visual states) or animations in the View.  This sounds extreme.  I know.  I thought so too at first.  My reasoning is a View’s purpose in life is to give the controls a place to perform, and provide a script (ViewModel/Data).  It should not be concerned with a Visual State [Manager].  You should not have to build extra infrastructure for you VM to tell your View to change states, nor should you be required to have a direct event handler in your code-behind to change states of your View.  “&lt;em&gt;But I want to animate my controls on my view.  The VSM works so well and it’s not a big deal having some code-behind.”&lt;/em&gt;  I can’t argue there, and&lt;u&gt; this is not a hard line rule I’m proposing&lt;/u&gt;.  This is more of a rule I’m suggesting.  I handle the “animation” problem with either creating a control, a panel, etc, that handles the animation.  Take a look at the &lt;a href="http://silverlight.codeplex.com/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;ANCHOR#TransitioningContentControl"&gt;TransitioningContentControl&lt;/a&gt;.  This is a great example of a control that you can style, use the VSM on, include it in your view.  &lt;li&gt;When the data required for the actor to operate is not domain specific.  Think about a &lt;ListBox&gt;.  It takes a collection of data.  It doesn’t care if the data is a list of monkies.  If we need to format our UI based on domain specific data (monkies), create a copy of the control’s style, maybe inside your view, and format away.  &lt;li&gt;You need to make a wrapper for other controls &lt;li&gt;It’s so atomic and simple, you have no choice but to make it a control.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;You want to make a View (stage) when:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;You need some controls working in concert and you need a way to delegate domain specific data to them.  &lt;li&gt;You need to take user input and send it to code for processing against your application’s domain logic.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In summary, I treat the view as a UI mediator (and layout provider, style setter and maybe resource holder) between data and &lt;strong&gt;other&lt;/strong&gt; UI.   “Other UI” being controls.  Got it?&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;h1&gt;Getting the Most Out of a Control&lt;/h1&gt; &lt;p&gt;I just talked a butt load about controls.  I wanted to cover them a little more in detail.  One of the things that really changed my XAML life was the concept of &lt;em&gt;lookless&lt;/em&gt; controls.  It is one of the most powerful parts of WPF/SL, but yet the MOST unused features by folks new to WPF/SL.  You create a control that has &lt;strong&gt;no XAML&lt;/strong&gt; associated to it.  You define “PARTS”, which are sort of like defining a contract between your lookless control code and it’s style.  When a style is applied to your control, you pull reference to the specific elements you want to manipulate in code and/or hook into events on these elements.  Generally when creating a lookless control, we create a default generic template.  In my practice, this default template is made for the designer of Blend.  So they have a literal and visual understanding of what my control is and does.  This generic template exists in a special place in your project.  &lt;em&gt;Themes\generic.xaml&lt;/em&gt;, which is just a ResourceDictionary.&lt;/p&gt; &lt;p&gt;A &lt;Button&gt; is a great example of a lookless control with a default template.  We’ve all (I hope at least) created a Button in Blend, edited a copy of the template, then made the button into a 3D, glowing, pulsating, gaudy looking thing.  When we ran it, we clicked on our styled button and well, it still threw a Click event, just as we expect from a button!&lt;/p&gt; &lt;p&gt;I’m not going to give a tutorial on lookless controls, but I want to give a few short pointers.  First, learn how to make these controls from the people who gave you the technology in the first place!  Microsoft.  They have a lot of their controls open source on codeplex.  Look at this &lt;a href="http://silverlight.codeplex.com/SourceControl/changeset/view/25992#636642"&gt;real simple one&lt;/a&gt; for a numeric spinner control in Silverlight.  Notice the attributes on top of the class.  Think of this as your code/style contract.  The attributes are not needed, but Blend looks for these attributes.  So if you want to make life easier in Blend, USE THEM!  Next look at the constructor:&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ButtonSpinner() : &lt;span style="color: #0000ff"&gt;base&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    DefaultStyleKey = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ButtonSpinner);&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This tells WPF/SL to look in the &lt;em&gt;Themes\Generic.xaml&lt;/em&gt; for a style who's key is of type ButtonSpinner:&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', 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: #008000"&gt;&lt;!-- From Themes\Generic.xaml --&gt;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Style&lt;/span&gt; &lt;span style="color: #ff0000"&gt;TargetType&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="inputPrimitivesToolkit:ButtonSpinner"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The next special part of a lookless control is the OnApplyTemplate override:&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OnApplyTemplate()&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.OnApplyTemplate();&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    IncreaseButton = GetTemplateChild(ElementIncreaseButtonName) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; ButtonBase;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    DecreaseButton = GetTemplateChild(ElementDecreaseButtonName) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; ButtonBase;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    Interaction.OnApplyTemplateBase();&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    UpdateVisualState(&lt;span style="color: #0000ff"&gt;false&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    SetButtonUsage();&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This override is where we pull out references to controls we are interested in our template.  Notice the GetTemplateChild method.  Matches the attributes at the top of the class huh?  This is part of our code/style contract I was talking about.  Here can do whatever we like to the controls we pull from the template.  Attach events, directly manipulate.  No need for binding or a ViewModel here! &lt;/p&gt;
&lt;h1&gt;I Hate Diagrams&lt;/h1&gt;
&lt;p&gt;I mean, I really &lt;em&gt;really&lt;/em&gt; fucking hate programming diagrams.  In fact, the easiest way for you to get me to zone out is to show me a UML diagram.  I may nod at you like I care, but really I’ve &lt;em&gt;totally&lt;/em&gt; checked out.  This is why I left the diagram for last.  Because if you made it this far, you deserve a nap.   This image should show most of what I’ve covered so far and how the components communicate.  Yes it’s terrible ugly.  I’ll try make something more intuitive later.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_14.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/AnatomyofanMVVMApplicationorHowTardsLike_BC88/image_thumb_6.png" width="499" height="278"&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/433/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/433/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/433/Default.aspx</guid>
      <pubDate>Tue, 13 Oct 2009 20:16:57 GMT</pubDate>
      <slash:comments>12</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=433</trackback:ping>
    </item>
    <item>
      <title>MVVM for Tarded Folks Like Me *or* MVVM and What it Means to Me</title>
      <description>&lt;p&gt;MVVM has been a trending topic lately.  And why shouldn’t it be?  People &lt;em&gt;want&lt;/em&gt; to build great WPF/SL applications and want guidance on how to build them using the framework’s strengths.  If you are anything like me, you started your WPF/SL career, learning the framework classes and hierarchy.  You learned XAML, triggers, storyboards and animations.  You even hobbled together something that looked mind blowing, but the code was a monstrosity.  &lt;strong&gt;Where do you go from here?  How do you leverage all this separation of UI and biz-code that was promised in WPF?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I’m going to go out on a limb and make a wild assumption.  I believe the majority of people that are trying to learn MVVM [and are having trouble] have never practiced any sort of UI application pattern.  Maybe they dabbled in MVC/MVP.  Maybe they studied the GoF patterns in school.  Why do I assume this?  Well because that describes &lt;u&gt;&lt;strong&gt;myself&lt;/strong&gt;&lt;/u&gt; and it describes lots of other developers I’ve interacted with.  Not very scientific reasoning, but I’m going with it anyways.  Because of this lack of general experience, MVVM tutorials and write-ups can be difficult for many developers.  Some of these developers will no doubt take MVVM as a very strict pattern and do not deviate from what their perception of MVVM purity is as not to upset the MVVM gods.  So that said, the rest of this write up I’m going to try to start from square one.  As if I was talking to myself years ago.  Layman as #%$@.&lt;/p&gt; &lt;h2&gt;Beginner’s MVVM Challenge #1 |or| Takin’ You Down to MVVM Town&lt;/h2&gt; &lt;p&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/MVVMandWhatitMeanstoMe_1092F/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/MVVMandWhatitMeanstoMe_1092F/image_thumb.png" width="217" height="267"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;So we want to begin our journey into MVVM town by way of Bindingopolis.  Our first web search brings us to a tutorial talking a bunch of mumbo jumbo about &lt;strong&gt;models&lt;/strong&gt;, &lt;strong&gt;views&lt;/strong&gt; and &lt;strong&gt;view-models.&lt;/strong&gt;  Usually you get a good description of what each is in &lt;em&gt;concept&lt;/em&gt;, which is cool, but we also want to know what is it in &lt;strong&gt;CODE&lt;/strong&gt;?&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;h3&gt;A &lt;strong&gt;model&lt;/strong&gt; is a class that has your data.  No magic here.&lt;/h3&gt;&lt;/li&gt;&lt;/ul&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Model&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    public &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; 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: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    public &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Address { get; 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3&gt; &lt;/h3&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;A &lt;strong&gt;view&lt;/strong&gt; is, for the &lt;u&gt;&lt;em&gt;sake&lt;/em&gt;&lt;/u&gt; of explanation, is a UserControl.   It’s a kind of like a mullet.  Except its a party in the &lt;em&gt;front&lt;/em&gt;, code in the &lt;em&gt;back&lt;/em&gt;.&lt;/h3&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/MVVMandWhatitMeanstoMe_1092F/image_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/MVVMandWhatitMeanstoMe_1092F/image_thumb_1.png" width="236" height="195"&gt;&lt;/a&gt; &lt;/h3&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', 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: #008000"&gt;/// &lt;summary&gt;&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: 'Courier New', 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: #008000"&gt;/// Interaction logic for View.xaml&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: 'Courier New', 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: #008000"&gt;/// &lt;/summary&gt;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;partial&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; View : UserControl&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; View()&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        InitializeComponent();&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;A View-Model is, again, just another class.  This is where your View (aka UserControl) will get it’s data.  It’s a &lt;em&gt;data abstraction&lt;/em&gt; of your View.  So if you view needs some data, this is where it gets it.  If values need to be converted/formatted, this would be a good place to do it.  Take special notice of the INotifyPropertyChanged interface.&lt;/h3&gt;&lt;/li&gt;&lt;/ul&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ViewModel : INotifyPropertyChanged&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Model m_model;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ViewModel()&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        m_model = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Model();&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_model.Name; }&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&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: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (m_model.Name != &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: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            {&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                m_model.Name = &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: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                InvokePropertyChanged(&lt;span style="color: #006080"&gt;"Name"&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            }&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;event&lt;/span&gt; PropertyChangedEventHandler 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt; &lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; InvokePropertyChanged(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; propertyName)&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        var e = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; PropertyChangedEventArgs(propertyName);&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        PropertyChangedEventHandler changed = 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: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (changed != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) changed(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The ViewModel class is really up to you how you want to design it.  The INotifyPropertyChanged interface allows us to update bindings (more later).  It’s accepted practice to make a base class for the ViewModel.  Some folks inherit from DependencyObject and make dependency properties for things in their view model.  &lt;u&gt;Don’t do this&lt;/u&gt;.  Those people are sadists.&lt;/p&gt;
&lt;h2&gt;Beginner’s MVVM Challenge #2 |or| A Menage a Trois That Won’t Get You in Trouble&lt;/h2&gt;
&lt;p&gt;So how do our three players, the Model, View and ViewModel, work together?  What sort of witchcraft must we implement?  DataContext (again, for the sake of simplicity).  Take a look at your View’s (UserControl) class hierarchy.  You’ll see FrameworkElement in there.  This has a property called DataContext of type &lt;em&gt;object&lt;/em&gt;.  When you set the DataContext, it will propagate down the tree.  So to answer the question of how these all fit…Your model is loaded from where-ever, a data base, a file, etc.  Your ViewModel gets your Model and exposes it’s data to your View.  Your View gets access to your ViewModel from, wait for it…the &lt;em&gt;DataContext&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Consider this from our code snippets above:&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;myView.DataContext = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ViewModel();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And the XAML for the “View” class.&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;UserControl&lt;/span&gt; &lt;span style="color: #ff0000"&gt;x:Class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="WpfApplication3.View"&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: 'Courier New', 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: #ff0000"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&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: 'Courier New', 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: #ff0000"&gt;xmlns:x&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&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: 'Courier New', 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: #ff0000"&gt;Height&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="300"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Width&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="300"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&gt;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&gt;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;&lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding Name}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&gt;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&gt;&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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;UserControl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So you see, we explicitly set the DataContext.  We also setup a binding in our View’s XAML.  WPF/SL will automatically look at the DataContext via reflection and pull out value for the “Name” property.  If we write code in our ViewModel to change the value of the “Name” property, it will automatically be updated in our UI via the binding.  This is the purpose for INotifyPropertyChanged.  &lt;/p&gt;
&lt;p&gt;If we want to update the value in the view model from the UI we’d do something like this:&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBox&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding Name, Mode=TwoWay}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now when we run this, the the value of the “Name” property will be in a TextBox.  When you edit the value (and the TextBox loses focus), the view model’s Name property will be updated.&lt;/p&gt;
&lt;p&gt;I would like to mention that getting the View and ViewModel together is a topic in itself.  Some people explicitly set the ViewModel to the DataContext.  Some people set it in the XAML.  Some people just include the ViewModel as a &lt;UserControl.Resource&gt; and do StaticResource bindings to it.  Some people use dependency injection and some use a service locator pattern (or both DI and ServiceLocator).  All of these have it’s pro’s and cons.   It all depends what is important to you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So now all this raises another question&lt;/strong&gt;:  Why even bother?  I can just load my model from code-behind and fill in the properties myself.&lt;/p&gt;
&lt;p&gt;We have successfully partitioned our application.  A designer can edit the Views XAML in Blend without too much fear of breaking any business logic.  They can design without Blend crashing on them.  Your code now has a separation of concerns, making extensibility, testing and maintenance much less involved than stepping through thousands of lines of interconnected, circular dependant spaghetti.  Don’t get me wrong, you can still write shit code in MVVM, but MVVM is a good start in avoiding shit code.&lt;/p&gt;
&lt;h2&gt;Beginner’s MVVM Challenge #3 |or| MVVM is a Mole-hill, Not a Mountain.&lt;/h2&gt;
&lt;h3&gt;&lt;a href="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/MVVMandWhatitMeanstoMe_1092F/image_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://jmorrill.hjtcentral.com/Portals/21/digmeta/4/WindowsLiveWriter/MVVMandWhatitMeanstoMe_1092F/image_thumb_2.png" width="635" height="251"&gt;&lt;/a&gt; &lt;/h3&gt;
&lt;h3&gt;In my &lt;strong&gt;opinion&lt;/strong&gt;, the last couple pages, this is all MVVM is.  It’s &lt;strong&gt;NOTHING&lt;/strong&gt; more.&lt;/h3&gt;
&lt;p&gt;“But Jer”, you say, “How do I make my View do X with the ViewModel?  How do I make my ViewModel do Y to the View?  This can’t be IT.  There’s gotta be more to MVVM.”  Yes there is more, but not to MVVM.  There are other patterns you should be aware of to assist you in MVVM.  Patterns like commanding (baked into WPF, solutions for SL), mediator and *gasp* dependency injection.  There’s other facilities baked into WPF and Silverlight that can further assist, such as the ItemsControl and data templates.  I will, in a later post, talk more deeply on these subjects in an article named “&lt;em&gt;&lt;a href="http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/433/Anatomy-of-an-MVVM-Application-or-How-Tards-Like-Me-Make-MVVM-Apps.aspx"&gt;Anatomy of an MVVM Application *or* How Tards Like Me Make MVVM Apps&lt;/a&gt;&lt;/em&gt;&lt;em&gt;&lt;/em&gt;”.&lt;/p&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/Default.aspx</guid>
      <pubDate>Sun, 11 Oct 2009 03:36:07 GMT</pubDate>
      <slash:comments>26</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=432</trackback:ping>
    </item>
    <item>
      <title>Some more breaking changes in MediaKit</title>
      <description>&lt;p&gt;The code in the WPF portion of WPF Mediakit was starting to get a little spahgetti-ish.  This was mostly do to me trying to handle as many usages of this control as possible and also dealing with the async nature of MediaKit.  It has to support the XAML parser and code-behind.   But what if you had properties set in a certain order in the xaml, but you put them in another order and everything breaks?  What if you set the source property and start playing in code-behind, then you put it in the visual tree and it executes the “LoadedBehavior”?  Things just weren’t predictable enough.&lt;/p&gt; &lt;p&gt;I now use the ISupportInitialize, which is implemented in FrameworkElement and has overrides for BeginInit/EndInit.  Now the code is much cleaner and further additions won’t be so confusing and buggy.  The idea behind this usage is the xaml parser will automatically call the BeginInit/EndInit when the control is loaded, therefore within the control, we can ensure the properties are set in the correct order and we have some predictability when using the code from code-behind.  If you just mainly use the built in MediaKit controls, things should work, but if you use the BeginInit/EndInit when starting to initialize the control and when you are done initializing it.  After the EndInit is called and properties are set, the next property changes will go directly to the DShow COM thread.&lt;/p&gt; &lt;p&gt;Here is an example of how to create a MediaUriElement from codebehind.&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: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; 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: 'Courier New', 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: 'Courier New', 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; var player = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MediaUriElement();&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: 'Courier New', 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: 'Courier New', 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; player.BeginInit();&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: 'Courier New', 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; player.Source = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri(GetRandomFileFromDirectory());&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: 'Courier New', 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; panel.Children.Insert(pos, player);&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: 'Courier New', 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; player.EndInit();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As always, if you have any issues, contact me directly or leave a message on &lt;a href="http://wpfmediakit.codeplex.com/Thread/List.aspx"&gt;codeplex&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/431/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/431/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/431/Default.aspx</guid>
      <pubDate>Mon, 05 Oct 2009 06:57:51 GMT</pubDate>
      <slash:comments>11</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=431</trackback:ping>
    </item>
    <item>
      <title>WPF MediaKit Updates</title>
      <description>&lt;p&gt;I haven’t had much time the last few months, but in my spare minutes I’ve been doing some work with the MediaKit.  Mostly to solve some very outstanding issues and annoyances.  The biggest one was a reported memory leak and another was a problem with reentrancy of the message pump.  Both were somewhat related.  Both had to be fixed.  Why would you want to dump the leak MediaElement for something that leaked just as bad or worse?&lt;/p&gt; &lt;h1&gt;Reentrancy?  What?&lt;/h1&gt; &lt;p&gt;In the WPF MediaKit, I was using a new WPF Dispatcher instance and thread.  The reason for this was:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;WPF’s UI thread runs STA.  We might want to run MTA COM apartments for our COM objects&lt;/li&gt; &lt;li&gt;DirectShow has blocking calls.  We never want to block the UI thread.  Maybe that was ok in Winforms.  Sure is not kosher in WPF any more.&lt;/li&gt; &lt;li&gt;I need a Win32 message pump, and WPF’s Dispatcher supplied that.&lt;/li&gt; &lt;li&gt;It’s very convenient.  The API is familiar.  It’s well engineered. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;So what’s the issue with the WPF Dispatcher?  Reentrancy!  See, DirectShow uses the Win32 message pump to relay some messages, maybe handle automatically created render windows, fire events and what not.  So lets say we tell our DShow’s Dispatcher to BeginInvoke(OpenFile) then BeginInvoke(Play).  We’d expect (given equal dispatcher priorities) that OpenFile will execute, then finish.  Then the dispatcher will execute Play, then finish.  Imagine my surprise when I saw OpenFile() execute 1/2 of the method, then switch over to the Play method!  Same thread in two places at the same time?  Debugging DShow can be tough, but it shouldn’t be like quantum physics!  What was happening is a call to DShow was dispatching a Win32 message, which was picked up by the WPF Dispatcher and executed, then the Dispatcher would execute the next delegate in the queue, which was something like Play().  Jaime Rodriguez and Dwayne Need &lt;a href="http://groups.google.com/group/wpf-disciples/msg/9f9c8938f879bcb5"&gt;were kind enough to explain&lt;/a&gt; this to me in gory detail.  Apparently, the WPF Dispatcher interleaves the Win32 message pump and .NET delegates.&lt;/p&gt; &lt;p&gt;Fixing this was going to require creating my own simple dispatcher/dispatcher-object that does what the WPF Dispatcher does, just it doesn’t interleave Win32/CLR delegates.  This fixed many issues off the bat.  Specially that damned RaceOnRCWCleanup MDA!  Also, you no longer need some stupid static factory class to create your WPF Dispatcher and initialize your COM player.&lt;/p&gt; &lt;h1&gt;Memory Leaks!  @#$%!&lt;/h1&gt; &lt;p&gt;Running a simple loop of:  Create MediaUriElement, assign a Uri, Play(), Close().  This would eventually show over 16,000 open handles after about half a day and well over a gig working set.   Writing a new Dispatcher fixed quite a bit of my issues in this area, but spending some time with Windbg was really what revealed where the problem areas were.  This still was not an easy process, considering the complexity of a managed COM API, running in .NET, using 3rd party filters, rendering in a D3D environment, interoping to WPF.  It’s a jungle in there.  I still want to monitor the leak area, but so far I’m &lt;strike&gt;pretty&lt;/strike&gt; &lt;strong&gt;very&lt;/strong&gt; pleased with it.&lt;/p&gt; &lt;p&gt;Not really a memory leak, but I wanted to cover a change in the MediaKit’s base classes.  I have now modified it so the default “Unloaded” behavior is Close.  As long as the Close is called by something, either automatic w/ the unloaded behavior, or explicit in your code.  This needs to be called when you are done with any of the players.  This will property shut down the dshow player thread.  What was extremely tricky was the scenario of:  What if you call Close, but then you set a property (ie the Uri “Source”) and tell it to Play().  The control won’t do shit anymore.   I added a method on to my WorkerDispatcher called EnsureThread.  This ensures the WorkerDispatcher has a thread.  This is automatically called in the base classes’ Play() and Pause() protected virtuals.&lt;/p&gt; &lt;h1&gt;Optimization&lt;/h1&gt; &lt;p&gt;Turns out that creating too many IDirect3DDevice9s on lower end cards makes your app die.  I now have one static shared IDirect3DDevice9 in the VMR9 allocator.  This seems to work out great, but this limits us to MTA ONLY at the moment.  In the future I will update the EVR to do the same, but also leave in the ability to support STA (which may take more work on my custom Dispatcher, WorkerDispatcher).  This may be done in the future by setting a “UseSharedResources” flag.&lt;/p&gt; &lt;p&gt;If you are using WPF MediaKit now, there are breaking changes…but I believe them to be very minimal.  Please test &lt;a href="http://wpfmediakit.codeplex.com/"&gt;the newest code&lt;/a&gt; and let me know if you find any issues.  I have not deeply tested any of the sample controls, like the DVD or Webcam controls, extensively but they will be next on my list.&lt;/p&gt;</description>
      <link>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/430/Default.aspx</link>
      <comments>http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/430/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/430/Default.aspx</guid>
      <pubDate>Wed, 30 Sep 2009 06:30:52 GMT</pubDate>
      <slash:comments>14</slash:comments>
      <trackback:ping>http://jmorrill.hjtcentral.com/DesktopModules/Blog/Trackback.aspx?id=430</trackback:ping>
    </item>
  </channel>
</rss>