<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Wandering through the Wilderness - Code</title>
    <link>http://www.julmar.com/blog/mark/</link>
    <description>... a journey through WPF, MVVM and .NET4</description>
    <language>en-us</language>
    <copyright>Mark Smith</copyright>
    <lastBuildDate>Mon, 22 Mar 2010 20:32:02 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>mark@julmar.com</managingEditor>
    <webMaster>mark@julmar.com</webMaster>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=42b78070-6421-4c78-b4c5-706dcd199bf9</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,42b78070-6421-4c78-b4c5-706dcd199bf9.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,42b78070-6421-4c78-b4c5-706dcd199bf9.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=42b78070-6421-4c78-b4c5-706dcd199bf9</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Today I was building a simple simulator to test some events to a new piece of hardware
I’m working on.  Of course, I’m using WPF to show the simulator – and I wanted
to create a topmost window that did not have a Close button on it.  Imagine my
surprise when I realized there was not a set of flags you could supply to the Window
object to actually achieve this result!
</p>
        <p>
However, with a little Win32 mojo we can get the desired effect:
</p>
        <p>
          <font size="2" face="Consolas">public partial class MainWindow<br />
{<br />
    public MainWindow()<br />
    {<br />
        <strong>SourceInitialized += MainWindow_SourceInitialized</strong>;<br />
        InitializeComponent();<br />
    } </font>
        </p>
        <p>
          <font size="2" face="Consolas">    </font>
          <strong>
            <font size="2" face="Consolas">void
MainWindow_SourceInitialized(object sender, EventArgs e)<br />
    {<br />
        WindowInteropHelper wih = new WindowInteropHelper(this);<br />
        int style = GetWindowLong(wih.Handle, GWL_STYLE);<br />
        SetWindowLong(wih.Handle, GWL_STYLE, style
&amp; ~WS_SYSMENU);<br />
    } </font>
          </strong>
        </p>
        <p>
          <font size="2" face="Consolas">    private const int GWL_STYLE = -16;<br />
    private const int WS_SYSMENU = 0x00080000; </font>
        </p>
        <p>
          <font size="2" face="Consolas">    [DllImport("user32.dll")]<br />
    private extern static int SetWindowLong(IntPtr hwnd, int index,
int value);<br />
    [DllImport("user32.dll")]<br />
    private extern static int GetWindowLong(IntPtr hwnd, int index);<br />
}</font>
        </p>
        <p>
The key here is hooking the <strong>SourceInitialized </strong>event and then using
the <strong>SetWindowLong </strong>function to strip off the <strong>WS_SYSMENU </strong>bit. 
You can just cut/paste this code right into your solution.
</p>
      </body>
      <title>Removing the Close Button on a WPF window</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,42b78070-6421-4c78-b4c5-706dcd199bf9.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2010/03/22/RemovingTheCloseButtonOnAWPFWindow.aspx</link>
      <pubDate>Mon, 22 Mar 2010 20:32:02 GMT</pubDate>
      <description>&lt;p&gt;
Today I was building a simple simulator to test some events to a new piece of hardware
I’m working on.&amp;nbsp; Of course, I’m using WPF to show the simulator – and I wanted
to create a topmost window that did not have a Close button on it.&amp;nbsp; Imagine my
surprise when I realized there was not a set of flags you could supply to the Window
object to actually achieve this result!
&lt;/p&gt;
&lt;p&gt;
However, with a little Win32 mojo we can get the desired effect:
&lt;/p&gt;
&lt;p&gt;
&lt;font size="2" face="Consolas"&gt;public partial class MainWindow&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public MainWindow()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;SourceInitialized += MainWindow_SourceInitialized&lt;/strong&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InitializeComponent();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="2" face="Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;void
MainWindow_SourceInitialized(object sender, EventArgs e)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WindowInteropHelper wih = new WindowInteropHelper(this);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int style = GetWindowLong(wih.Handle, GWL_STYLE);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetWindowLong(wih.Handle, GWL_STYLE, style
&amp;amp; ~WS_SYSMENU);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="2" face="Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private const int GWL_STYLE = -16;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private const int WS_SYSMENU = 0x00080000; &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="2" face="Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DllImport("user32.dll")]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private extern static int SetWindowLong(IntPtr hwnd, int index,
int value);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [DllImport("user32.dll")]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private extern static int GetWindowLong(IntPtr hwnd, int index);&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
The key here is hooking the &lt;strong&gt;SourceInitialized &lt;/strong&gt;event and then using
the &lt;strong&gt;SetWindowLong &lt;/strong&gt;function to strip off the &lt;strong&gt;WS_SYSMENU &lt;/strong&gt;bit.&amp;nbsp;
You can just cut/paste this code right into your solution.
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,42b78070-6421-4c78-b4c5-706dcd199bf9.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=a7333798-461f-4471-96b1-d4375c0ee379</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,a7333798-461f-4471-96b1-d4375c0ee379.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,a7333798-461f-4471-96b1-d4375c0ee379.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=a7333798-461f-4471-96b1-d4375c0ee379</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I cannot count how many times people have requested the source code to the ATAPI.NET
or ITAPI3 projects.  My response has always been that I was unable to release
it due to ownership issues (it was developed under contract for a client).  I
am pleased to announce this morning that I have worked through those issues and have
been granted permission to release the project in it’s entirety as source code on
CodePlex!
</p>
        <p>
Here’s their new homes:  <a title="http://atapi.codeplex.com/" href="http://atapi.codeplex.com/">http://atapi.codeplex.com/</a> and <a href="http://itapi3.codeplex.com">http://itapi3.codeplex.com</a></p>
        <p>
I’ll open up discussion board access there as well for Q&amp;A.  If you would
like to contribute to the project, shoot me an email and we’ll see about getting you
access!
</p>
      </body>
      <title>ATAPI.NET and ITAPI3 source code availability!</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,a7333798-461f-4471-96b1-d4375c0ee379.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2010/02/06/ATAPINETAndITAPI3SourceCodeAvailability.aspx</link>
      <pubDate>Sat, 06 Feb 2010 17:56:38 GMT</pubDate>
      <description>&lt;p&gt;
I cannot count how many times people have requested the source code to the ATAPI.NET
or ITAPI3 projects.&amp;nbsp; My response has always been that I was unable to release
it due to ownership issues (it was developed under contract for a client).&amp;nbsp; I
am pleased to announce this morning that I have worked through those issues and have
been granted permission to release the project in it’s entirety as source code on
CodePlex!
&lt;/p&gt;
&lt;p&gt;
Here’s their new homes:&amp;nbsp; &lt;a title="http://atapi.codeplex.com/" href="http://atapi.codeplex.com/"&gt;http://atapi.codeplex.com/&lt;/a&gt; and &lt;a href="http://itapi3.codeplex.com"&gt;http://itapi3.codeplex.com&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I’ll open up discussion board access there as well for Q&amp;amp;A.&amp;nbsp; If you would
like to contribute to the project, shoot me an email and we’ll see about getting you
access!
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,a7333798-461f-4471-96b1-d4375c0ee379.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>Tapi</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=513ec8da-076b-4f88-91be-2151f0010610</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,513ec8da-076b-4f88-91be-2151f0010610.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,513ec8da-076b-4f88-91be-2151f0010610.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=513ec8da-076b-4f88-91be-2151f0010610</wfw:commentRss>
      <title>MVVM: Views and ViewModels</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,513ec8da-076b-4f88-91be-2151f0010610.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2010/01/22/MVVMViewsAndViewModels.aspx</link>
      <pubDate>Fri, 22 Jan 2010 22:35:37 GMT</pubDate>
      <description>&lt;p&gt;
In the previous post, I provided a link to the project template you can use to start
a new MVVM project using the JulMar MVVM library. Here's the two links in case you
didn't get them before: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.julmar.com/samples/mvvmhelpers.zip"&gt;MVVM Helpers Distribution&lt;/a&gt; 
&lt;br&gt;
&lt;a href="http://www.julmar.com/samples/WpfMvvmApplication.zip"&gt;Project Template&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Copy the project template into your Visual Studio 2008 templates directory located
off your user documents - mine is at &lt;strong&gt;%UserProfile%\Documents\Visual Studio
2008\Templates\ProjectTemplates\Visual C#\Windows&lt;/strong&gt;. 
&lt;/p&gt;
&lt;p&gt;
Ok, so once you have these installed, what can you do with them? Well, for starters,
you can now generate a starter project that provides a nice template for an MVVM application.
The starter template creates a simple "Explorer" like program - it looks like this: 
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.julmar.com/blog/mark/content/binary/images/sample-run1.jpg" width=600&gt; 
&lt;/p&gt;
&lt;p&gt;
Notice there are two sections - a &lt;strong&gt;TreeView&lt;/strong&gt; listing all the directories,
and a &lt;strong&gt;ListView&lt;/strong&gt; showing all the files in the selected directory. Let's
look a little closer at the project structure. There are four directories in the solution:
&lt;/p&gt;
&lt;table border=1 cellspacing=0 cellpadding=2 width=588&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top width=113&gt;
&lt;strong&gt;Converters&lt;/strong&gt;&lt;/td&gt;
&lt;td valign=top width=473&gt;
This has a simple &lt;font face="Courier new"&gt;ValueConverter&lt;/font&gt; that takes a filename
and returns an icon as an &lt;strong&gt;ImageSource&lt;/strong&gt;. 
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=top width=118&gt;
&lt;strong&gt;Dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td valign=top width=468&gt;
This is the binary dependencies the project requires, specifically it contains the
JulMar MVVM libraries and Blend action libraries.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=top width=123&gt;
&lt;strong&gt;ViewModels&lt;/strong&gt;&lt;/td&gt;
&lt;td valign=top width=464&gt;
This directory contains all the business logic in the form of ViewModels.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=top width=127&gt;
&lt;strong&gt;Views&lt;/strong&gt;&lt;/td&gt;
&lt;td valign=top width=461&gt;
Finally, this directory contains all the UI (XAML) for the application.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4&gt;Views
&lt;/h4&gt;
&lt;p&gt;
Let's start with the last folder - the Views. Views are the UI presentation of data
- in the case of a WPF/Silverlight application this is most commonly the XAML and
XAML code behind files (they are considered a single element together). We want to
have UI-specific code and designer elements present in these files. Generally we prefer
to place business logic and testable elements into the ViewModel area.
&lt;/p&gt;
&lt;p&gt;
In this starter project, we have a single view &lt;strong&gt;MainWindow.xaml&lt;/strong&gt;. This
is what presents the main UI shown above. The code behind file contains the required
boilerplate code (essentially a constructor and call to &lt;strong&gt;InitializeComponent&lt;/strong&gt;). 
&lt;/p&gt;
&lt;p&gt;
If you open the view (note that the designer will choke on it until you compile the
project), you will find fairly straightforward XAML that creates the UI, let’s break
it down as we go:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs28 \cf1 &amp;lt;\cf3 Window\cf4  x\cf1 :\cf4 Class\cf1 ="WpfMVVMApplication1.Views.MainWindow"\par ??\cf0    \cf4  xmlns\cf1 ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\par ??\cf0    \cf4  xmlns\cf1 :\cf4 x\cf1 ="http://schemas.microsoft.com/winfx/2006/xaml"\par ??\cf0    \cf4  xmlns\cf1 :\cf4 julmar\cf1 ="http://www.julmar.com/wpfhelpers"\par ??\cf0    \cf4  xmlns\cf1 :\cf4 ViewModels\cf1 ="clr-namespace:WpfMVVMApplication1.ViewModels"\par ??\cf0    \cf4  xmlns\cf1 :\cf4 Converters\cf1 ="clr-namespace:WpfMVVMApplication1.Converters"\par ??\cf0    \cf4  DataContext\cf1 ="\{\cf3 julmar\cf1 :\cf3 ViewModelCreator\cf1  \{\cf3 x\cf1 :\cf3 Type\cf4  ViewModels\cf1 :\cf4 MainViewModel\cf1 \}\}"\par ??\cf0    \cf4  Title\cf1 ="File Explorer"\cf4  Height\cf1 ="400"\cf4  Width\cf1 ="500"&amp;gt;\par ??}
--&gt;
&lt;div style="FONT-FAMILY: consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 14pt"&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Window&lt;/span&gt;&lt;span style="COLOR: red"&gt; x&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;Class&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="WpfMVVMApplication1.Views.MainWindow"&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt; xmlns&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt; xmlns&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;x&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt; xmlns&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;julmar&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="http://www.julmar.com/wpfhelpers"&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt; xmlns&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;ViewModels&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="clr-namespace:WpfMVVMApplication1.ViewModels"&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt; xmlns&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;Converters&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="clr-namespace:WpfMVVMApplication1.Converters"&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt; &lt;strong&gt;&lt;u&gt;&lt;em&gt;DataContext&lt;/em&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;u&gt;&lt;em&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;julmar&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;ViewModelCreator&lt;/span&gt;&lt;span style="COLOR: blue"&gt; {&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;x&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Type&lt;/span&gt;&lt;span style="COLOR: red"&gt; ViewModels&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;MainViewModel&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}}"&lt;/span&gt;&lt;/em&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt; Title&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="File
Explorer"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Height&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="400"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Width&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="500"&amp;gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
First, notice how the &lt;strong&gt;DataContext&lt;/strong&gt; is established – through a custom &lt;strong&gt;MarkupExtension&lt;/strong&gt; called &lt;strong&gt;ViewModelCreator&lt;/strong&gt;.&amp;nbsp;
This extension is responsible for creating an associated ViewModel for this view (where
our testable business logic should go) and also wiring up a couple of special event
handlers that will allow the ViewModel to activate the view and close the view respectively.
&lt;/p&gt;
&lt;p&gt;
Next, let’s check out the resources:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red163\green21\blue21;\red255\green255\blue255;\red0\green0\blue255;\red0\green128\blue0;\red255\green0\blue0;}??\fs28 \cf1     \cf3 &amp;lt;\cf1 Window.Resources\cf3 &amp;gt;\par ??\cf1         \cf4 &amp;lt;!-- Bindable commands sit in resources and allow keyboard input to target ViewModel commands --&amp;gt;\par ??\cf1         \cf3 &amp;lt;\cf1 julmar\cf3 :\cf1 BindableCommand\cf5  x\cf3 :\cf5 Key\cf3 ="CloseCommand"\cf5  Command\cf3 ="\{\cf1 Binding\cf5  CloseAppCommand\cf3 \}" /&amp;gt;\par ??\cf1         \par ??        \cf3 &amp;lt;\cf1 Converters\cf3 :\cf1 FilenameToIconConverter\cf5  x\cf3 :\cf5 Key\cf3 ="iconConverter" /&amp;gt;\par ??\cf1         \par ??        \cf3 &amp;lt;\cf1 HierarchicalDataTemplate\cf5  x\cf3 :\cf5 Key\cf3 ="DirectoryTemplate"\cf5  ItemsSource\cf3 ="\{\cf1 Binding\cf5  Subdirectories\cf3 \}"&amp;gt;\par ??\cf1             \cf3 &amp;lt;\cf1 StackPanel\cf5  Orientation\cf3 ="Horizontal"&amp;gt;\par ??\cf1                 \cf3 &amp;lt;\cf1 Image\cf5  Width\cf3 ="16"\cf5  Height\cf3 ="16"\cf5  Source\cf3 ="\{\cf1 Binding\cf5  FullName\cf3 ,\cf5  Converter\cf3 =\{\cf1 StaticResource\cf5  iconConverter\cf3 \}\}" /&amp;gt;\par ??\cf1                 \cf3 &amp;lt;\cf1 TextBlock\cf5  x\cf3 :\cf5 Name\cf3 ="tb"\cf5  Margin\cf3 ="5,0"\cf5  Text\cf3 ="\{\cf1 Binding\cf5  Name\cf3 \}" /&amp;gt;\par ??\cf1             \cf3 &amp;lt;/\cf1 StackPanel\cf3 &amp;gt;\cf1  \par ??            \cf3 &amp;lt;\cf1 HierarchicalDataTemplate.Triggers\cf3 &amp;gt;\par ??\cf1                 \cf3 &amp;lt;\cf1 DataTrigger\cf5  Binding\cf3 ="\{\cf1 Binding\cf5  IsSelected\cf3 \}"\cf5  Value\cf3 ="True"&amp;gt;\par ??\cf1                     \cf3 &amp;lt;\cf1 Setter\cf5  TargetName\cf3 ="tb"\cf5  Property\cf3 ="FontWeight"\cf5  Value\cf3 ="Bold" /&amp;gt;\par ??\cf1                 \cf3 &amp;lt;/\cf1 DataTrigger\cf3 &amp;gt;\par ??\cf1             \cf3 &amp;lt;/\cf1 HierarchicalDataTemplate.Triggers\cf3 &amp;gt;\par ??\cf1         \cf3 &amp;lt;/\cf1 HierarchicalDataTemplate\cf3 &amp;gt;\par ??\par ??\cf1     \cf3 &amp;lt;/\cf1 Window.Resources\cf3 &amp;gt;\par ??}
--&gt;
&lt;div style="FONT-FAMILY: consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 14pt"&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Window.Resources&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: green"&gt;&amp;nbsp; &amp;lt;!-- Bindable commands sit in resources
and allow keyboard input to target ViewModel commands --&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;julmar&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;BindableCommand&lt;/span&gt;&lt;span style="COLOR: red"&gt; x&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;Key&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="CloseCommand"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Command&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; CloseAppCommand&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}"
/&amp;gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Converters&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;FilenameToIconConverter&lt;/span&gt;&lt;span style="COLOR: red"&gt; x&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;Key&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="iconConverter"
/&amp;gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;HierarchicalDataTemplate&lt;/span&gt;&lt;span style="COLOR: red"&gt; x&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;Key&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="DirectoryTemplate"&lt;/span&gt;&lt;span style="COLOR: red"&gt; &lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: red"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ItemsSource&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; Subdirectories&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}"&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR: red"&gt; Orientation&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="Horizontal"&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Image&lt;/span&gt;&lt;span style="COLOR: red"&gt; Width&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="16"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Height&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="16"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Source&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; FullName&lt;/span&gt;&lt;span style="COLOR: blue"&gt;,&lt;/span&gt;&lt;span style="COLOR: red"&gt; &lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: red"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Converter&lt;/span&gt;&lt;span style="COLOR: blue"&gt;={&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;StaticResource&lt;/span&gt;&lt;span style="COLOR: red"&gt; iconConverter&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}}"
/&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;TextBlock&lt;/span&gt;&lt;span style="COLOR: red"&gt; x&lt;/span&gt;&lt;span style="COLOR: blue"&gt;:&lt;/span&gt;&lt;span style="COLOR: red"&gt;Name&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="tb"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Margin&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="5,0"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Text&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; Name&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}"
/&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;StackPanel&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt; &lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;HierarchicalDataTemplate.Triggers&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;DataTrigger&lt;/span&gt;&lt;span style="COLOR: red"&gt; Binding&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; IsSelected&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Value&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="True"&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="COLOR: red"&gt; TargetName&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="tb"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Property&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="FontWeight"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Value&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="Bold"
/&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;DataTrigger&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;HierarchicalDataTemplate.Triggers&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;HierarchicalDataTemplate&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;font size=2&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Window.Resources&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;br&gt;
Here we find three defined resources – first we have a JulMar MVVM &lt;strong&gt;BindableCommand&lt;/strong&gt;.&amp;nbsp;
This is a special &lt;strong&gt;ICommand&lt;/strong&gt; instance that can be data bound and forwards
to the specified binding.&amp;nbsp; We use this a bit later in the keyboard accelerator
to close the application.&amp;nbsp; Next, there is the converter that takes a filename
and converts it to an icon – that’s the source code in the &lt;strong&gt;Converters&lt;/strong&gt; folder
mentioned earlier.&amp;nbsp; I use a converter here because this is very UI-centric and
not very testable – so the converter will data bind to a string (filename) property
of the ViewModel and retrieve the icon for the UI to display.&amp;nbsp; That way, my ViewModel
sticks with base (non-WPF) types.&amp;nbsp; This isn’t a hard rule – but it’s a good one
to try to follow.
&lt;/p&gt;
&lt;p&gt;
Finally, there is a &lt;strong&gt;DataTemplate&lt;/strong&gt; that is used to display the directory
structure – this is what the &lt;strong&gt;TreeView&lt;/strong&gt; uses to display it’s data.&amp;nbsp;
Notice it data binds to a couple of properties – &lt;strong&gt;FullName&lt;/strong&gt;, Name and &lt;strong&gt;IsSelected&lt;/strong&gt;.&amp;nbsp;
All of these, as you will see, exist in our ViewModel definition.&amp;nbsp; The View takes
the data from the ViewModel and displays it onto the UI for the user to interact with.
&lt;/p&gt;
&lt;p&gt;
Next in the XAML is the input bindings – this is where we define keyboard and mouse
gesture accelerators, and it’s where I use the bindable command I defined earlier:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red163\green21\blue21;\red255\green255\blue255;\red0\green0\blue255;\red255\green0\blue0;}??\fs28 \cf1     \cf3 &amp;lt;\cf1 Window.InputBindings\cf3 &amp;gt;\par ??\cf1         \cf3 &amp;lt;\cf1 KeyBinding\cf4  Key\cf3 ="X"\cf4  Modifiers\cf3 ="ALT"\cf4  Command\cf3 ="\{\cf1 StaticResource\cf4  CloseCommand\cf3 \}" /&amp;gt;\par ??\cf1     \cf3 &amp;lt;/\cf1 Window.InputBindings\cf3 &amp;gt;\par ??}
--&gt;
&lt;div style="FONT-FAMILY: consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 10pt"&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #a31515"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Window.InputBindings&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #a31515"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;KeyBinding&lt;/span&gt;&lt;span style="COLOR: red"&gt; Key&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="X"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Modifiers&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="ALT"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Command&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;StaticResource&lt;/span&gt;&lt;span style="COLOR: red"&gt; CloseCommand&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}"
/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #a31515"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Window.InputBindings&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Here you can see that instead of trying to bind to the command, we use &lt;strong&gt;{StaticResource}&lt;/strong&gt; to
get it from the resources.&amp;nbsp; This is necessary under WPF 3.5 because the &lt;strong&gt;KeyBinding&lt;/strong&gt; will
not inherit the &lt;strong&gt;DataContext &lt;/strong&gt;and so cannot bind directly to the command
– but resources can, and specifically Freezable resources can – that’s what the &lt;strong&gt;BindableCommand&lt;/strong&gt; provides
– a Freezable resource that forwards the &lt;strong&gt;ICommand&lt;/strong&gt; implementation
onto a command defined in the DataContext ViewModel.&amp;nbsp; This is not necessary under
WPF4 – this is actually one of the new features they’ve added: to inherit the DataContext
in your input bindings!&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
The remainder of the view is fairly traditional – we use bindings to connect the UI
up to the ViewModel definitions, so let’s go look at what those are.
&lt;/p&gt;
&lt;h4&gt;ViewModels
&lt;/h4&gt;
&lt;p&gt;
The ViewModel folder contains three source code files – &lt;strong&gt;DirectoryViewModel.cs&lt;/strong&gt;, &lt;strong&gt;FileViewModel.cs&lt;/strong&gt;,
and &lt;strong&gt;MainViewModel.cs&lt;/strong&gt;.&amp;nbsp; If you recall from above, &lt;strong&gt;MainViewModel&lt;/strong&gt; is
the primary ViewModel that is data bound to the view.&amp;nbsp; The other two are child
view models used to represent the files and folders respectively.&amp;nbsp; Let’s look
at FileViewModel as an example:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red128\green128\blue128;\red0\green128\blue0;}??\fs28     \cf3 public\cf0  \cf3 class\cf0  \cf4 FileViewModel\cf0  : \cf4 SimpleViewModel\par ??\cf0     \{\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  File expansion marker used by the directory\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 internal\cf0  \cf3 static\cf0  \cf4 FileViewModel\cf0  MarkerFile = \cf3 new\cf0  \cf4 FileViewModel\cf0 ();\par ??\par ??\cf3         #region\cf0  Internal Data\par ??        \cf3 private\cf0  \cf3 readonly\cf0  \cf4 FileInfo\cf0  _data;\par ??\cf3         #endregion\par ??\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  File name\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf3 string\cf0  Name\par ??        \{\par ??            \cf3 get\cf0  \{ \cf3 return\cf0  _data.Name; \}\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Full path + filename\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf3 string\cf0  FullPath\par ??        \{\par ??            \cf3 get\cf0  \{ \cf3 return\cf0  _data.FullName; \}\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Size of the file in bytes\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf3 long\cf0  Size\par ??        \{\par ??            \cf3 get\cf0  \{ \cf3 return\cf0  _data.Length; \}\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Internal constructor used to create the file marker.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 private\cf0  FileViewModel()\par ??        \{\par ??            _data = \cf3 null\cf0 ;\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Public constructor that captures a list of files.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;param name="fi"&amp;gt;\cf6 FileInfo to grab file information from\cf5 &amp;lt;/param&amp;gt;\par ??\cf0         \cf3 public\cf0  FileViewModel(\cf4 FileInfo\cf0  fi)\par ??        \{\par ??            _data = fi;\par ??        \}\par ??    \}\par ??}
--&gt;
&lt;div style="FONT-FAMILY: consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 10pt"&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;class&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt; : &lt;span style="COLOR: #2b91af"&gt;SimpleViewModel&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Marker
file that signals expansion of the tree.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;internal&lt;/span&gt; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt; MarkerFile
= &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;readonly&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;FileInfo&lt;/span&gt; _data;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; File
name&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; Name
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _data.Name;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Full
path + filename&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; FullPath
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _data.FullName;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Size
of the file in bytes&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;long&lt;/span&gt; Size
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _data.Length;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Private
constructor used to create marker file.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; FileViewModel()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Public
constructor that captures a list of files.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;param
name="fi"&amp;gt;&lt;/span&gt;&lt;span style="COLOR: green"&gt;FileInfo to grab file information from&lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; FileViewModel(&lt;span style="COLOR: #2b91af"&gt;FileInfo&lt;/span&gt; fi)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _data = fi;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
As you can see, it is &lt;em&gt;very&lt;/em&gt; simple – it is simply a wrapper around a piece
of data, a &lt;strong&gt;FileInfo&lt;/strong&gt; that represents a file on disk.&amp;nbsp; It exposes
properties that are data bindable.&amp;nbsp; There is one element (&lt;strong&gt;MarkerFile&lt;/strong&gt;)
that I want you to ignore for a moment – we’ll get to it in a second.&amp;nbsp; Notice
that it extends &lt;strong&gt;SimpleViewModel&lt;/strong&gt;.&amp;nbsp; This is one of three primary
VM classes in the MVVM helper library.&amp;nbsp; &lt;strong&gt;SimpleViewModel&lt;/strong&gt; is intended
for cases where you need the bare minimum support – specifically support for &lt;strong&gt;INotifyPropertyChanged&lt;/strong&gt;.&amp;nbsp;
No other services are provided by this base class, and as such it is very light.&amp;nbsp;
Let’s look at the directory class next:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs28     \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0     \cf3 ///\cf4  Sample ViewModel that wraps a Directory.\par ??\cf0     \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0     \cf5 public\cf0  \cf5 class\cf0  \cf6 DirectoryViewModel\cf0  : \cf6 ViewModel\par ??\cf0     \{\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  String used to send message to main view model about directory selection.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 internal\cf0  \cf5 const\cf0  \cf5 string\cf0  SelectedDirectoryChangedMessage = \cf7 @"SelectedDirectoryChanged"\cf0 ;\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Marker directory that signals expansion of the tree.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 internal\cf0  \cf5 static\cf0  \cf6 DirectoryViewModel\cf0  MarkerDirectory = \cf5 new\cf0  \cf6 DirectoryViewModel\cf0 ();\par ??\par ??\cf5         #region\cf0  Internal Data\par ??        \cf5 private\cf0  \cf5 bool\cf0  _isSelected, _isExpanded;\par ??        \cf5 private\cf0  \cf5 readonly\cf0  \cf6 DirectoryInfo\cf0  _data;\par ??        \cf5 private\cf0  \cf5 readonly\cf0  \cf6 ObservableCollection\cf0 &amp;lt;\cf6 FileViewModel\cf0 &amp;gt; _files;\par ??        \cf5 private\cf0  \cf5 readonly\cf0  \cf6 ObservableCollection\cf0 &amp;lt;\cf6 DirectoryViewModel\cf0 &amp;gt; _subdirs;\par ??\cf5         #endregion\par ??\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Name of the directory\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf5 string\cf0  Name\par ??        \{\par ??            \cf5 get\cf0  \{ \cf5 return\cf0  _data.Name; \}\par ??        \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Full path + name of the directory\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf5 string\cf0  FullName\par ??        \{\par ??            \cf5 get\cf0  \{ \cf5 return\cf0  _data.FullName; \}\par ??        \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  True/False whether the directory is selected (i.e. current).\par ??\cf0         \cf3 ///\cf4  Selecting the directory causes it to populate it's file collection.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf5 bool\cf0  IsSelected\par ??        \{\par ??            \cf5 get\cf0  \{ \cf5 return\cf0  _isSelected; \}\par ??            \cf5 set\par ??\cf0             \{\par ??                \cf5 if\cf0  (_isSelected != \cf5 value\cf0 )\par ??                \{\par ??                    _isSelected = \cf5 value\cf0 ;\par ??\par ??                    \cf5 if\cf0  (_isSelected)\par ??                    \{\par ??                        \cf5 if\cf0  (_files.Count == 1 &amp;amp;&amp;amp; _files[0] == \cf6 FileViewModel\cf0 .MarkerFile)\par ??                        \{\par ??                            _files.Clear();\par ??                            _data.GetFiles()\par ??                                .Where(f =&amp;gt; (f.Attributes &amp;amp; (\cf6 FileAttributes\cf0 .Hidden | \cf6 FileAttributes\cf0 .System)) == 0)\par ??                                .ForEach(f =&amp;gt; _files.Add(\cf5 new\cf0  \cf6 FileViewModel\cf0 (f)));\par ??                            OnPropertyChanged(\cf7 "TotalFiles"\cf0 , \cf7 "TotalFileSize"\cf0 );\par ??                        \}\par ??                        SendMessage(SelectedDirectoryChangedMessage, \cf5 this\cf0 );\par ??                    \}\par ??                    \cf5 else\par ??\cf0                     \{\par ??                        _files.Clear();\par ??                        _files.Add(\cf6 FileViewModel\cf0 .MarkerFile);\par ??                    \}\par ??\par ??                    OnPropertyChanged(\cf7 "IsSelected"\cf0 );\par ??                \}\par ??            \}\par ??        \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  True/False if the directory is expanded. Expanding the directory causes it\par ??\cf0         \cf3 ///\cf4  to fill it's subdirectory collection.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf5 bool\cf0  IsExpanded\par ??        \{\par ??            \cf5 get\cf0  \{ \cf5 return\cf0  _isExpanded; \}\par ??            \cf5 set\par ??\cf0             \{\par ??                \cf5 if\cf0  (_isExpanded != \cf5 value\cf0 )\par ??                \{\par ??                    _isExpanded = \cf5 value\cf0 ;\par ??                    \cf5 if\cf0  (_isExpanded)\par ??                    \{\par ??                        \cf5 if\cf0  (_subdirs.Count == 1 &amp;amp;&amp;amp; _subdirs[0] == \cf6 DirectoryViewModel\cf0 .MarkerDirectory)\par ??                        \{\par ??                            _subdirs.Clear();\par ??                            _data.GetDirectories()\par ??                                .Where(d =&amp;gt; (d.Attributes &amp;amp; (\cf6 FileAttributes\cf0 .Hidden | \cf6 FileAttributes\cf0 .System)) == 0)\par ??                                .ForEach(d =&amp;gt; _subdirs.Add(\cf5 new\cf0  \cf6 DirectoryViewModel\cf0 (d)));\par ??                        \}\par ??                    \}\par ??                    \cf4 // Throw them away to recollect later - implements a refresh.\par ??\cf0                     \cf5 else\par ??\cf0                     \{\par ??                        _subdirs.Clear();\par ??                        _subdirs.Add(\cf6 DirectoryViewModel\cf0 .MarkerDirectory);\par ??                    \}\par ??                \}\par ??\par ??                OnPropertyChanged(\cf7 "IsExpanded"\cf0 );\par ??            \}\par ??        \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  List of files in this directory.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf6 IList\cf0 &amp;lt;\cf6 FileViewModel\cf0 &amp;gt; Files \{ \cf5 get\cf0  \{ \cf5 return\cf0  _files; \} \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  List of subdirectories in this directory.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf6 IList\cf0 &amp;lt;\cf6 DirectoryViewModel\cf0 &amp;gt; Subdirectories \{ \cf5 get\cf0  \{ \cf5 return\cf0  _subdirs; \} \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Count of files in this directory.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf5 int\cf0  TotalFiles \{ \cf5 get\cf0  \{ \cf5 return\cf0  _files.Count; \} \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Total size of all files in this directory.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf5 long\cf0  TotalFileSize \{ \cf5 get\cf0  \{ \cf5 return\cf0  _files.Sum(file =&amp;gt; file.Size); \} \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Constructor for the marker directory.  This is used to detect an expansion.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 private\cf0  DirectoryViewModel()\par ??        \{\par ??            _data = \cf5 null\cf0 ;\par ??        \}\par ??\par ??        \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Public constructor\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;param name="di"&amp;gt;\cf4 DirectoryInfo to pull information from\cf3 &amp;lt;/param&amp;gt;\par ??\cf0         \cf5 public\cf0  DirectoryViewModel(\cf6 DirectoryInfo\cf0  di)\par ??        \{\par ??            \cf5 if\cf0  (di == \cf5 null\cf0 )\par ??                \cf5 throw\cf0  \cf5 new\cf0  \cf6 ArgumentNullException\cf0 (\cf7 "di"\cf0 );\par ??\par ??            _data = di;\par ??            _files = \cf5 new\cf0  \cf6 ObservableCollection\cf0 &amp;lt;\cf6 FileViewModel\cf0 &amp;gt; \{ \cf6 FileViewModel\cf0 .MarkerFile \};\par ??            _subdirs = \cf5 new\cf0  \cf6 ObservableCollection\cf0 &amp;lt;\cf6 DirectoryViewModel\cf0 &amp;gt; \{ \cf6 DirectoryViewModel\cf0 .MarkerDirectory \};\par ??        \}\par ??    \}\par ??}
--&gt;
&lt;div style="FONT-FAMILY: consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 10pt"&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Sample
ViewModel that wraps a Directory.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;class&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt; : &lt;span style="COLOR: #2b91af"&gt;ViewModel&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; String
used to send message to main view model about directory selection.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;internal&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; SelectedDirectoryChangedMessage
= &lt;span style="COLOR: #a31515"&gt;@"SelectedDirectoryChanged"&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Marker
directory that signals expansion of the tree.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;internal&lt;/span&gt; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt; MarkerDirectory
= &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;bool&lt;/span&gt; _isSelected,
_isExpanded;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;readonly&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryInfo&lt;/span&gt; _data;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;readonly&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;&amp;gt;
_files;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;readonly&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;&amp;gt;
_subdirs;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Name
of the directory&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; Name
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _data.Name;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Full
path + name of the directory&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; FullName
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _data.FullName;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; True/False
whether the directory is selected (i.e. current).&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Selecting
the directory causes it to populate it's file collection.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;bool&lt;/span&gt; IsSelected
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _isSelected;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;set&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (_isSelected
!= &lt;span style="COLOR: blue"&gt;value&lt;/span&gt;)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_isSelected = &lt;span style="COLOR: blue"&gt;value&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (_isSelected)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (_files.Count
== 1 &amp;amp;&amp;amp; _files[0] == &lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;.MarkerFile)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_files.Clear();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_data.GetFiles()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
.Where(f =&amp;gt; (f.Attributes &amp;amp; (&lt;span style="COLOR: #2b91af"&gt;FileAttributes&lt;/span&gt;.Hidden
| &lt;span style="COLOR: #2b91af"&gt;FileAttributes&lt;/span&gt;.System)) == 0)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
.ForEach(f =&amp;gt; _files.Add(&lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;(f)));
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
OnPropertyChanged(&lt;span style="COLOR: #a31515"&gt;"TotalFiles"&lt;/span&gt;, &lt;span style="COLOR: #a31515"&gt;"TotalFileSize"&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
SendMessage(SelectedDirectoryChangedMessage, &lt;span style="COLOR: blue"&gt;this&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;else&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_files.Clear();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_files.Add(&lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;.MarkerFile);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
OnPropertyChanged(&lt;span style="COLOR: #a31515"&gt;"IsSelected"&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; True/False
if the directory is expanded. Expanding the directory causes it&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; to
fill it's subdirectory collection.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;bool&lt;/span&gt; IsExpanded
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _isExpanded;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;set&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (_isExpanded
!= &lt;span style="COLOR: blue"&gt;value&lt;/span&gt;)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_isExpanded = &lt;span style="COLOR: blue"&gt;value&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (_isExpanded)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (_subdirs.Count
== 1 &amp;amp;&amp;amp; _subdirs[0] == &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;.MarkerDirectory)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_subdirs.Clear();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_data.GetDirectories()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
.Where(d =&amp;gt; (d.Attributes &amp;amp; (&lt;span style="COLOR: #2b91af"&gt;FileAttributes&lt;/span&gt;.Hidden
| &lt;span style="COLOR: #2b91af"&gt;FileAttributes&lt;/span&gt;.System)) == 0)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
.ForEach(d =&amp;gt; _subdirs.Add(&lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;(d)));
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
Throw them away to recollect later - implements a refresh.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;else&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_subdirs.Clear();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
_subdirs.Add(&lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;.MarkerDirectory);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
OnPropertyChanged(&lt;span style="COLOR: #a31515"&gt;"IsExpanded"&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; List
of files in this directory.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;&amp;gt;
Files { &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _files;
} }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; List
of subdirectories in this directory.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;&amp;gt;
Subdirectories { &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _subdirs;
} }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Count
of files in this directory.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;int&lt;/span&gt; TotalFiles
{ &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _files.Count;
} }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Total
size of all files in this directory.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;long&lt;/span&gt; TotalFileSize
{ &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _files.Sum(file
=&amp;gt; file.Size); } }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Constructor
for the marker directory.&amp;nbsp; This is used to detect an expansion.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; DirectoryViewModel()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _data = &lt;span style="COLOR: blue"&gt;null&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Public
constructor&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;param
name="di"&amp;gt;&lt;/span&gt;&lt;span style="COLOR: green"&gt;DirectoryInfo to pull information from&lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; DirectoryViewModel(&lt;span style="COLOR: #2b91af"&gt;DirectoryInfo&lt;/span&gt; di)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (di
== &lt;span style="COLOR: blue"&gt;null&lt;/span&gt;)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;throw&lt;/span&gt; &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="COLOR: #a31515"&gt;"di"&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _data = di;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _files = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;&amp;gt;
{ &lt;span style="COLOR: #2b91af"&gt;FileViewModel&lt;/span&gt;.MarkerFile };
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _subdirs = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;&amp;gt;
{ &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;.MarkerDirectory };
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
This file is a bit more complicated – like the &lt;strong&gt;FileViewModel&lt;/strong&gt;, this
wraps a simple data object (a &lt;strong&gt;DirectoryInfo&lt;/strong&gt; in this case).&amp;nbsp;
Notice that it too exposes properties to provide access to various bits of information.&amp;nbsp;
Here you can see that it is creating new properties such as &lt;strong&gt;TotalFileSize&lt;/strong&gt; which
is the sum of all the files sizes in this directory.&amp;nbsp; That’s one of the jobs
of the ViewModel – to provide easily bindable properties for the bits of information
we want to display.&amp;nbsp; In this case, the &lt;strong&gt;TotalFiles&lt;/strong&gt; and &lt;strong&gt;TotalFileSize&lt;/strong&gt; gets
displayed in the &lt;strong&gt;StatusBar&lt;/strong&gt; of the window when the directory has files.
&lt;/p&gt;
&lt;p&gt;
Notice that the directory exposes files and subdirectories in &lt;strong&gt;ObservableCollections&lt;/strong&gt; –
but they are delay populated.&amp;nbsp; This is done so that the &lt;strong&gt;TreeView&lt;/strong&gt; comes
up quickly and we don’t have to enumerate the entire disk to retrieve the directories
and files!&amp;nbsp; When you expand and collapse the nodes in the tree, it is populating
the data.&amp;nbsp; This is done through the &lt;strong&gt;IsExpanded&lt;/strong&gt; property – if
you look back in the View, you will see that the &lt;strong&gt;TreeView&lt;/strong&gt; actually
binds the &lt;strong&gt;TreeViewItem.IsExpanded&lt;/strong&gt; to this property:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs28 \cf1 &amp;lt;\cf3 TreeView\cf4  Grid.Column\cf1 ="0"\cf4  ItemsSource\cf1 ="\{\cf3 Binding\cf4  RootDirectory\cf1 \}"\cf0  \par ??                 \cf4  ItemTemplate\cf1 ="\{\cf3 StaticResource\cf4  DirectoryTemplate\cf1 \}"&amp;gt;\par ??\cf3                 \cf1 &amp;lt;\cf3 TreeView.ItemContainerStyle\cf1 &amp;gt;\par ??\cf3                     \cf1 &amp;lt;\cf3 Style\cf4  TargetType\cf1 ="TreeViewItem"&amp;gt;\par ??\cf3                         \cf1 &amp;lt;\cf3 Setter\cf4  Property\cf1 ="IsSelected"\cf4  Value\cf1 ="\{\cf3 Binding\cf4  IsSelected\cf1 ,\cf4  Mode\cf1 =TwoWay\}" /&amp;gt;\par ??\cf3                         \cf1 &amp;lt;\cf3 Setter\cf4  Property\cf1 ="IsExpanded"\cf4  Value\cf1 ="\{\cf3 Binding\cf4  IsExpanded\cf1 ,\cf4  Mode\cf1 =TwoWay\}" /&amp;gt;\par ??\cf3                     \cf1 &amp;lt;/\cf3 Style\cf1 &amp;gt;\par ??\cf3                 \cf1 &amp;lt;/\cf3 TreeView.ItemContainerStyle\cf1 &amp;gt;\par ??\cf3             \cf1 &amp;lt;/\cf3 TreeView\cf1 &amp;gt;}
--&gt;
&lt;div style="FONT-FAMILY: consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 10pt"&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;TreeView&lt;/span&gt;&lt;span style="COLOR: red"&gt; Grid.Column&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="0"&lt;/span&gt;&lt;span style="COLOR: red"&gt; ItemsSource&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; RootDirectory&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}"&lt;/span&gt; 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: red"&gt;ItemTemplate&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;StaticResource&lt;/span&gt;&lt;span style="COLOR: red"&gt; DirectoryTemplate&lt;/span&gt;&lt;span style="COLOR: blue"&gt;}"&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;TreeView.ItemContainerStyle&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Style&lt;/span&gt;&lt;span style="COLOR: red"&gt; TargetType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="TreeViewItem"&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="COLOR: red"&gt; Property&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="IsSelected"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Value&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; IsSelected&lt;/span&gt;&lt;span style="COLOR: blue"&gt;,&lt;/span&gt;&lt;span style="COLOR: red"&gt; Mode&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=TwoWay}"
/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;u&gt;&lt;em&gt;&amp;lt;&lt;/em&gt;&lt;/u&gt;&lt;/span&gt;&lt;u&gt;&lt;em&gt;&lt;span style="COLOR: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="COLOR: red"&gt; Property&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="IsExpanded"&lt;/span&gt;&lt;span style="COLOR: red"&gt; Value&lt;/span&gt;&lt;span style="COLOR: blue"&gt;="{&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Binding&lt;/span&gt;&lt;span style="COLOR: red"&gt; IsExpanded&lt;/span&gt;&lt;span style="COLOR: blue"&gt;,&lt;/span&gt;&lt;span style="COLOR: red"&gt; Mode&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=TwoWay}"
/&amp;gt;&lt;/span&gt;&lt;/em&gt;&lt;/u&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;Style&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;TreeView.ItemContainerStyle&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;TreeView&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Notice it also binds up the &lt;strong&gt;IsSelected&lt;/strong&gt; property – this is when we
populate the files collection.&amp;nbsp; Since they are observable, they will force the
UI to update when new items are added or removed and we see the Explorer effect we
desire.
&lt;/p&gt;
&lt;p&gt;
Lastly, before we leave this file, notice that when a directory is selected, it makes
a method call to a function called &lt;strong&gt;SendMessage&lt;/strong&gt;:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;SendMessage(SelectedDirectoryChangedMessage, &lt;span style="COLOR: blue"&gt;this&lt;/span&gt;);&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
It passes a string (the key) and an object (the data).&amp;nbsp; This is a built-in service
of the &lt;strong&gt;ViewModel&lt;/strong&gt; base class and it’s the reason why this ViewModel
does not derive from &lt;strong&gt;SimpleViewModel&lt;/strong&gt;, but instead from &lt;strong&gt;ViewModel&lt;/strong&gt; which
is the full version.&amp;nbsp; One of the services provided is a &lt;em&gt;Message Mediator&lt;/em&gt;.&amp;nbsp;
This service basically allows you to loosely couple various objects together – we’ll
see how the target registers, but for now, just notice the sender – it passes a string
key and an object.&amp;nbsp; Any target registered for the given key will receive the
object.&amp;nbsp; There are several overrides for the message mediator which I’ll detail
in a later post.
&lt;/p&gt;
&lt;p&gt;
Ok, let’s switch to the final file – the MainViewModel:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red128\green128\blue128;\red0\green128\blue0;\red163\green21\blue21;}??\fs28     \cf3 public\cf0  \cf3 class\cf0  \cf4 MainViewModel\cf0  : \cf4 ViewModel\par ??\cf0     \{\par ??\cf3         #region\cf0  Internal Data\par ??        \cf3 private\cf0  \cf4 DirectoryViewModel\cf0  _selectedDirectory;\par ??\cf3         #endregion\par ??\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Root directory - can be bound to an ItemsControl on the UI.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf4 DirectoryViewModel\cf0 [] RootDirectory \{ \cf3 get\cf0 ; \cf3 private\cf0  \cf3 set\cf0 ; \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Selected (active) directory\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf4 DirectoryViewModel\cf0  SelectedDirectory\par ??        \{\par ??            \cf3 get\cf0  \{ \cf3 return\cf0  _selectedDirectory; \}\par ??            \cf3 set\cf0  \{ _selectedDirectory = \cf3 value\cf0 ; OnPropertyChanged(\cf7 "SelectedDirectory"\cf0 ); \}\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Command to display the About Box.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf4 ICommand\cf0  DisplayAboutCommand \{ \cf3 get\cf0 ; \cf3 private\cf0  \cf3 set\cf0 ; \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Command to end the application\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf4 ICommand\cf0  CloseAppCommand \{ \cf3 get\cf0 ; \cf3 private\cf0  \cf3 set\cf0 ; \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Main constructor\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 public\cf0  MainViewModel()\par ??        \{\par ??            \cf6 // Register this instance with the message mediator so it can receive\par ??\cf0             \cf6 // messages from other views/viewmodels.\par ??\cf0             RegisterWithMessageMediator();\par ??\par ??            \cf6 // Create our commands\par ??\cf0             DisplayAboutCommand = \cf3 new\cf0  \cf4 DelegatingCommand\cf0 (OnShowAbout);\par ??            CloseAppCommand = \cf3 new\cf0  \cf4 DelegatingCommand\cf0 (OnCloseApp);\par ??\par ??            \cf6 // Fill in the root directory from C:\par ??\cf0             RootDirectory = \cf3 new\cf0 [] \{ \cf3 new\cf0  \cf4 DirectoryViewModel\cf0 (\cf3 new\cf0  \cf4 DirectoryInfo\cf0 (\cf7 @"C:\\"\cf0 )) \{ IsSelected = \cf3 true\cf0  \} \};\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  This method closes the application window.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 private\cf0  \cf3 void\cf0  OnCloseApp()\par ??        \{\par ??            \cf6 // Ask the view to close.\par ??\cf0             RaiseCloseRequest();\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  This method displays the About Box.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 private\cf0  \cf3 void\cf0  OnShowAbout()\par ??        \{\par ??            \cf6 // Get the message visualizer service from the service resolver.\par ??\cf0             \cf6 // All services can be replaced, so make sure to check if we have something\par ??\cf0             \cf6 // registered.\par ??\cf0             \cf4 IMessageVisualizer\cf0  messageVisualizer = Resolve&amp;lt;\cf4 IMessageVisualizer\cf0 &amp;gt;();\par ??            \cf3 if\cf0  (messageVisualizer != \cf3 null\cf0 )\par ??            \{\par ??                \cf6 // Show a message box.\par ??\cf0                 messageVisualizer.Show(\cf7 "About File Explorer Sample"\cf0 , \cf7 "File Explorer Sample 1.0"\cf0 , \cf4 MessageButtons\cf0 .OK);\par ??            \}\par ??        \}\par ??\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  This method is invoked by the message mediator when a DirectoryViewModel is selected.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;param name="newDirectory"&amp;gt;\cf6 DirectoryViewModel that is now active\cf5 &amp;lt;/param&amp;gt;\par ??\cf0         [\cf4 MessageMediatorTarget\cf0 (\cf4 DirectoryViewModel\cf0 .SelectedDirectoryChangedMessage)]\par ??        \cf3 private\cf0  \cf3 void\cf0  OnCurrentDirectoryChanged(\cf4 DirectoryViewModel\cf0  newDirectory)\par ??        \{\par ??            SelectedDirectory = newDirectory;\par ??        \}\par ??    \}\par ??}
--&gt;
&lt;div style="FONT-FAMILY: consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 10pt"&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;class&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;MainViewModel&lt;/span&gt; : &lt;span style="COLOR: #2b91af"&gt;ViewModel&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt; _selectedDirectory;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Root
directory - can be bound to an ItemsControl on the UI.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;[]
RootDirectory { &lt;span style="COLOR: blue"&gt;get&lt;/span&gt;; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;set&lt;/span&gt;;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Selected
(active) directory&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt; SelectedDirectory
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;get&lt;/span&gt; { &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; _selectedDirectory;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;set&lt;/span&gt; {
_selectedDirectory = &lt;span style="COLOR: blue"&gt;value&lt;/span&gt;; OnPropertyChanged(&lt;span style="COLOR: #a31515"&gt;"SelectedDirectory"&lt;/span&gt;);
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Command
to display the About Box.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;ICommand&lt;/span&gt; DisplayAboutCommand
{ &lt;span style="COLOR: blue"&gt;get&lt;/span&gt;; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;set&lt;/span&gt;;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Command
to end the application&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;ICommand&lt;/span&gt; CloseAppCommand
{ &lt;span style="COLOR: blue"&gt;get&lt;/span&gt;; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;set&lt;/span&gt;;
}
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; Main
constructor&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; MainViewModel()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
Register this instance with the message mediator so it can receive&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
messages from other views/viewmodels.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RegisterWithMessageMediator();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
Create our commands&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DisplayAboutCommand
= &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DelegatingCommand&lt;/span&gt;(OnShowAbout);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseAppCommand
= &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DelegatingCommand&lt;/span&gt;(OnCloseApp);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
Fill in the root directory from C:&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RootDirectory = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt;[]
{ &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;(&lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;DirectoryInfo&lt;/span&gt;(&lt;span style="COLOR: #a31515"&gt;@"C:\"&lt;/span&gt;))
{ IsSelected = &lt;span style="COLOR: blue"&gt;true&lt;/span&gt; } };
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; This
method closes the application window.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; OnCloseApp()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
Ask the view to close.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RaiseCloseRequest();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; This
method displays the About Box.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; OnShowAbout()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
Get the message visualizer service from the service resolver.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
All services can be replaced, so make sure to check if we have something&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
registered.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: #2b91af"&gt;IMessageVisualizer&lt;/span&gt; messageVisualizer
= Resolve&amp;lt;&lt;span style="COLOR: #2b91af"&gt;IMessageVisualizer&lt;/span&gt;&amp;gt;();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (messageVisualizer
!= &lt;span style="COLOR: blue"&gt;null&lt;/span&gt;)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: green"&gt;//
Show a message box.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
messageVisualizer.Show(&lt;span style="COLOR: #a31515"&gt;"About File Explorer Sample"&lt;/span&gt;, &lt;span style="COLOR: #a31515"&gt;"File
Explorer Sample 1.0"&lt;/span&gt;, &lt;span style="COLOR: #2b91af"&gt;MessageButtons&lt;/span&gt;.OK);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; This
method is invoked by the message mediator when a DirectoryViewModel is selected.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: gray"&gt;///&lt;/span&gt;&lt;span style="COLOR: green"&gt; &lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;param
name="newDirectory"&amp;gt;&lt;/span&gt;&lt;span style="COLOR: green"&gt;DirectoryViewModel that is
now active&lt;/span&gt;&lt;span style="COLOR: gray"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="COLOR: #2b91af"&gt;MessageMediatorTarget&lt;/span&gt;(&lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt;.SelectedDirectoryChangedMessage)]
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; OnCurrentDirectoryChanged(&lt;span style="COLOR: #2b91af"&gt;DirectoryViewModel&lt;/span&gt; newDirectory)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SelectedDirectory
= newDirectory;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Here you can see the same basic principle – it exposes properties the UI binds to.&amp;nbsp;
In particular here we see Commands being exposed as properties.&amp;nbsp; Commands is
what drives a UI – it allows a UI to trigger actions in the ViewModel.&amp;nbsp; We are
using two basic commands here – &lt;strong&gt;CloseAppCommand&lt;/strong&gt; and &lt;strong&gt;DisplayAboutCommand&lt;/strong&gt;.&amp;nbsp;
If you look at the constructor, you will see they are backed by a &lt;strong&gt;DelegatingCommand&lt;/strong&gt; object.&amp;nbsp;
This is a common pattern found in almost every MVVM framework out there, but it’s
essentially a pair of delegates that are called when the command is checked and when
it is invoked.&amp;nbsp; In our cases here, we always allow the command to execute so
we only provide the execution handler (a second parameter would define the typical &lt;strong&gt;CanExecute&lt;/strong&gt; handler).&amp;nbsp;
There are a couple of overrides for this object as well – one that provides type safety
for the parameter and one that always uses object and allows for any object as data.&amp;nbsp;
Again here we are being simple and not using any parameters so our bound methods are
both no-parameter methods.
&lt;/p&gt;
&lt;p&gt;
The &lt;strong&gt;CloseAppCommand &lt;/strong&gt;command invokes the &lt;strong&gt;OnCloseApp&lt;/strong&gt; method
– which in turn calls &lt;strong&gt;RaiseCloseRequest&lt;/strong&gt;.&amp;nbsp; This JulMar ViewModel
method will close the view associated with the ViewModel &lt;em&gt;if you associated the
two using the &lt;strong&gt;ViewModelCreator&lt;/strong&gt;&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
The &lt;strong&gt;OnShowAbout&lt;/strong&gt; method is called by the &lt;strong&gt;DisplayAboutCommand.&amp;nbsp; &lt;/strong&gt;It
uses another registered service in the library called &lt;strong&gt;IMessageVisualizer&lt;/strong&gt;.&amp;nbsp;
The message visualizer is used to display a simple message box from the ViewModel.&amp;nbsp;
Here we use it to display an about box.&amp;nbsp; There are several other services I’ll
talk about in the next post.
&lt;/p&gt;
&lt;p&gt;
Notice that the &lt;strong&gt;RootDirectory&lt;/strong&gt; property which is data bound to the &lt;strong&gt;TreeView.ItemsSource&lt;/strong&gt; is
exposes as an array – this is because the &lt;strong&gt;TreeView&lt;/strong&gt; always expects
a collection of items even though we always have a single root item.&amp;nbsp; So we wrap
a single &lt;strong&gt;DirectoryViewModel&lt;/strong&gt; into a collection and return it as the
property.
&lt;/p&gt;
&lt;p&gt;
If you look at the end of the file you will find our message mediator target – &lt;strong&gt;OnCurrentDirectoryChanged&lt;/strong&gt;.&amp;nbsp;
We use this as a way to see when a new directory has been selected in the tree.&amp;nbsp;
For a &lt;strong&gt;ListBox&lt;/strong&gt;, we could&amp;nbsp; have just data bound the &lt;strong&gt;SelectedItem&lt;/strong&gt; to
the property, but &lt;strong&gt;TreeView&lt;/strong&gt; isn’t a selector and doesn’t expose a &lt;strong&gt;SelectedItem&lt;/strong&gt; property.&amp;nbsp;
Instead you either have to catch an event (I’ll show how you can do that in a future
blog entry about the MVVM helpers library) or use this little mediator trick.
&lt;/p&gt;
&lt;p&gt;
The &lt;strong&gt;[MessageMediatorTarget]&lt;/strong&gt; attribute is the secret sauce here –
it tells the message mediator to wire this method up to the passed string key.&amp;nbsp;
When that key is used in a &lt;strong&gt;SendMessage&lt;/strong&gt; call &lt;em&gt;and&lt;/em&gt; the parameter
type is a &lt;strong&gt;DirectoryViewModel&lt;/strong&gt; (or derived type), the mediator will
invoke this method.&amp;nbsp; This all happens without any direct linkage between the &lt;strong&gt;DirectoryViewModel&lt;/strong&gt; and
the &lt;strong&gt;MainViewModel&lt;/strong&gt;.&amp;nbsp; The delegate instance is held in a weak
reference so there’s no concern for memory leaks.
&lt;/p&gt;
&lt;p&gt;
The second part of the magic is in the constructor – the message mediator is an opt-in
service, so notice the call to &lt;strong&gt;RegisterWithMessageMediator()&lt;/strong&gt;.&amp;nbsp;
This is what causes this instance to be noticed by the mediator.&amp;nbsp; There is a
balancing &lt;strong&gt;UnregisterWithMessageMediator&lt;/strong&gt; if you ever want to unhook
the instance.&amp;nbsp; You can also use methods to directly wire up handlers (without
attributes).&amp;nbsp; This is useful when you are dynamically linking things together
at runtime vs. compile time.
&lt;/p&gt;
&lt;p&gt;
Well, that covers the basics of the framework Views + ViewModels.&amp;nbsp; In the next
post, I will detail the service registration and basic service mechanism that’s built
into the framework for you to use.&amp;nbsp; Until then, ciao!
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,513ec8da-076b-4f88-91be-2151f0010610.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>MVVM</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=f4fd7f33-fba2-472e-8491-8b5a7ee06000</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,f4fd7f33-fba2-472e-8491-8b5a7ee06000.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,f4fd7f33-fba2-472e-8491-8b5a7ee06000.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=f4fd7f33-fba2-472e-8491-8b5a7ee06000</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">To start off this new series, I have created
a MVVM Helpers project template - this is a Visual Studio 2008 template which will
create the starter project I will be using as an example. It shows off the primary
usage of the MVVM library and has directories and references to required assemblies
already established so it's a nice starting point for any MVVM WPF app using the helpers. 
<br /><br />
Download it from <a href="http://www.julmar.com/samples/WpfMvvmApplication.zip">here</a> and
copy the zip file into your template directory. 
<br /><br />
As an example, if your user name was "Mark", like me and you are running Windows 7
it would be: 
<div><strong>"C:\Users\Mark\Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual
C#\Windows"</strong></div><br />
Here's what my directory looks like: 
<br /><br /><img border="0" alt="templatedir.jpg" align="center" src="http://www.julmar.com/blog/mark/content/binary/images/templatedir.jpg" width="500" /><p>
With that in place you should be able to fire up Visual Studio 2008 and create a sample
MVVM project: 
</p><p><img border="0" alt="project_screen.jpg" align="center" src="http://www.julmar.com/blog/mark/content/binary/images/project_screen.jpg" width="500" /></p><p>
Let it generate a project and the build it -- running the program will give you a
simple file explorer using the MVVM design pattern and WPF:
</p><p>
 <img border="0" alt="sample-run1.jpg" align="center" src="http://www.julmar.com/blog/mark/content/binary/images/sample-run1.jpg" width="700" />  
</p><p>
In tomorrow's post, we'll break the sample down and see how I built it. See you then! 
</p><p>
 
</p></body>
      <title>MVVM Helpers Project Template</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,f4fd7f33-fba2-472e-8491-8b5a7ee06000.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2010/01/20/MVVMHelpersProjectTemplate.aspx</link>
      <pubDate>Wed, 20 Jan 2010 23:35:13 GMT</pubDate>
      <description>To start off this new series, I have created a MVVM Helpers project template - this is a Visual Studio 2008 template which will create the starter project I will be using as an example. It shows off the primary usage of the MVVM library and has directories and references to required assemblies already established so it's a nice starting point for any MVVM WPF app using the helpers. &lt;br&gt;
&lt;br&gt;
Download it from &lt;a href="http://www.julmar.com/samples/WpfMvvmApplication.zip"&gt;here&lt;/a&gt; and
copy the zip file into your template directory. 
&lt;br&gt;
&lt;br&gt;
As an example, if your user name was "Mark", like me and you are running Windows 7
it would be: 
&lt;div&gt;&lt;strong&gt;"C:\Users\Mark\Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual
C#\Windows"&lt;/strong&gt;
&lt;/div&gt;
&lt;br&gt;
Here's what my directory looks like: 
&lt;br&gt;
&lt;br&gt;
&lt;img border=0 alt=templatedir.jpg align=center src="http://www.julmar.com/blog/mark/content/binary/images/templatedir.jpg" width=500&gt; 
&lt;p&gt;
With that in place you should be able to fire up Visual Studio 2008 and create a sample
MVVM project: 
&lt;/p&gt;
&lt;p&gt;
&lt;img border=0 alt=project_screen.jpg align=center src="http://www.julmar.com/blog/mark/content/binary/images/project_screen.jpg" width=500&gt; 
&lt;/p&gt;
&lt;p&gt;
Let it generate a project and the build it -- running the program will give you a
simple file explorer using the MVVM design pattern and WPF:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&lt;img border=0 alt=sample-run1.jpg align=center src="http://www.julmar.com/blog/mark/content/binary/images/sample-run1.jpg" width=700&gt;&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
In tomorrow's post, we'll break the sample down and see how I built it. See you then! 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,f4fd7f33-fba2-472e-8491-8b5a7ee06000.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=8913b470-bc63-4c27-b8c0-48af7ef1093e</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,8913b470-bc63-4c27-b8c0-48af7ef1093e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,8913b470-bc63-4c27-b8c0-48af7ef1093e.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=8913b470-bc63-4c27-b8c0-48af7ef1093e</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
With this post I am starting a new series - I hope to be more consistent in posting
at least once or twice a week. To that end, I am going to focus on the WPF/MVVM helper
library I use daily. I released an earlier version of it onto the web and have gotten
a lot of comments which has been great, so I am releasing the latest version which
has a <strong>lot</strong> of changes. So, without further ado, here's the code for
you to download and play with, this compiles with <strong>Visual Studio 2008 SP1</strong>,
or with <strong>Visual Studio 2010 Beta 2</strong>. 
</p>
        <p>
          <a href="http://www.julmar.com/samples/mvvmhelpers.zip">mvvmhelpers.zip</a>
        </p>
        <p>
Read on for the basics of the project structure and files. 
</p>
        <h2>Project Structure
</h2>
        <div>The code is broken into two assemblies: <strong>Julmar.Wpf.Helpers</strong> and <strong>Julmar.Wpf.Behaviors</strong>.
The helpers assembly contains core WPF helper classes and MVVM support and the behaviors
assembly depends on the <strong>System.Windows.Interactivity</strong> support and
provides Blend-based behaviors for a variety of situations. 
</div>
        <table>
          <tbody>
            <tr>
              <td valign="top" width="400">
                <h3>Building and Usage
</h3>
There are pre-built assemblies included in the distribution, but you are free to build
the source on your own - I don't include the certificate file (so I can tell versions
that I have built) but you are free to delete the certificate from the solution or
replace it with your own and build your own binaries from the source code. Or you
can take any of the source code, modify it however you like and add it directly to
your project. 
<h3>Credits
</h3>
As with most projects, this library has benefited significantly from the community.
The WPF Disciples list on has been a particular source for ideas and even source code.
There are some source files in the project that I did not author, or where I took
a bit of code and modified it to suit my purposes. I have tried to make sure people
get credit where appropriate in the source code itself, if I missed anyone I am truly
sorry. 
<h3>Documentation
</h3>
As I mentioned earlier, my goal is to produce a set of blog posts that detail how
to use the library, but there is also some documentation on each class included in
the distribution in the form of a .CHM (Windows Help File). I encourage anyone who
wants to use this library to check that out. 
</td>
              <td valign="top">
                <img border="0" alt="Solution.jpg" align="center" src="http://www.julmar.com/blog/mark/content/binary/images/Solution.jpg" width="322" height="543" />
              </td>
            </tr>
          </tbody>
        </table>
        <br />
      </body>
      <title>MVVM Helpers 1.05</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,8913b470-bc63-4c27-b8c0-48af7ef1093e.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2010/01/20/MVVMHelpers105.aspx</link>
      <pubDate>Wed, 20 Jan 2010 20:22:12 GMT</pubDate>
      <description>&lt;p&gt;
With this post I am starting a new series - I hope to be more consistent in posting
at least once or twice a week. To that end, I am going to focus on the WPF/MVVM helper
library I use daily. I released an earlier version of it onto the web and have gotten
a lot of comments which has been great, so I am releasing the latest version which
has a &lt;strong&gt;lot&lt;/strong&gt; of changes. So, without further ado, here's the code for
you to download and play with, this compiles with &lt;strong&gt;Visual Studio 2008 SP1&lt;/strong&gt;,
or with &lt;strong&gt;Visual Studio 2010 Beta 2&lt;/strong&gt;. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.julmar.com/samples/mvvmhelpers.zip"&gt;mvvmhelpers.zip&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Read on for the basics of the project structure and files. 
&lt;/p&gt;
&lt;h2&gt;Project Structure
&lt;/h2&gt;
&lt;div&gt;The code is broken into two assemblies: &lt;strong&gt;Julmar.Wpf.Helpers&lt;/strong&gt; and &lt;strong&gt;Julmar.Wpf.Behaviors&lt;/strong&gt;.
The helpers assembly contains core WPF helper classes and MVVM support and the behaviors
assembly depends on the &lt;strong&gt;System.Windows.Interactivity&lt;/strong&gt; support and
provides Blend-based behaviors for a variety of situations. 
&lt;/div&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top width=400&gt;
&lt;h3&gt;Building and Usage
&lt;/h3&gt;
There are pre-built assemblies included in the distribution, but you are free to build
the source on your own - I don't include the certificate file (so I can tell versions
that I have built) but you are free to delete the certificate from the solution or
replace it with your own and build your own binaries from the source code. Or you
can take any of the source code, modify it however you like and add it directly to
your project. 
&lt;h3&gt;Credits
&lt;/h3&gt;
As with most projects, this library has benefited significantly from the community.
The WPF Disciples list on has been a particular source for ideas and even source code.
There are some source files in the project that I did not author, or where I took
a bit of code and modified it to suit my purposes. I have tried to make sure people
get credit where appropriate in the source code itself, if I missed anyone I am truly
sorry. 
&lt;h3&gt;Documentation
&lt;/h3&gt;
As I mentioned earlier, my goal is to produce a set of blog posts that detail how
to use the library, but there is also some documentation on each class included in
the distribution in the form of a .CHM (Windows Help File). I encourage anyone who
wants to use this library to check that out. 
&lt;/td&gt;
&lt;td valign=top&gt;
&lt;img border=0 alt=Solution.jpg align=center src="http://www.julmar.com/blog/mark/content/binary/images/Solution.jpg" width=322 height=543&gt; 
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,8913b470-bc63-4c27-b8c0-48af7ef1093e.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=43b8da4d-a392-46f9-9e03-939950798b41</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,43b8da4d-a392-46f9-9e03-939950798b41.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,43b8da4d-a392-46f9-9e03-939950798b41.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=43b8da4d-a392-46f9-9e03-939950798b41</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A recent series of blog entries at <a href="http://themechanicalbride.blogspot.com/">http://themechanicalbride.blogspot.com/</a> introduced
the Rx framework (System.Reactive.dll) which is an assembly used in the Silverlight
toolkit for UI testing purposes.  It essentially provides a mechanism to do event
driven programming through LINQ.  I'll refer you to the blog referenced above
for all the gory details - frankly I'm still trying to wrap my mind around it!
</p>
        <p>
Silverlight isn't my favorite technology however, I much prefer working in WPF and
so I spent some time rebuilding Rx for the desktop CLR!  My original approach
was to take my favorite exploration tool, reflector (available for free from <a href="http://www.redgate.com">www.redgate.com</a>),
and disassemble all the classes into C#, placing them into a project file.  I
found however that Reflector choked on some of the more complicated structures - requiring
me to go and hand-edit a bunch of the code.  I realized while I was doing this
that there was a much easier way to convert a Silverlight assembly to a WPF assembly.
</p>
        <p>
As you probably already know, Silverlight shares the same assembly format as the desktop
CLR - there is no difference in the IL or structure of the assembly itself. 
The difference is in the dependency on mscorlib and other references.  Specifically,
when you add an assembly via VS2008, it looks at the <strong>version</strong> of the
referenced mscorlib to determine whether it's a desktop CLR assembly or Silverlight
assembly.  
</p>
        <p>
Here's the header of a Silverlight assembly examined through ILDASM:
</p>
        <font size="3">
          <p>
            <font face="Courier New">
              <strong>// Metadata version: v2.0.50727<br />
.assembly extern mscorlib<br />
{<br />
   .publickeytoken = (7C EC 85 D7 BE A7 79 8E ) // |.....y.<br />
   .ver 2:0:5:0<br />
}</strong>
            </font>
          </p>
          <p>
            <font size="2">Here is a desktop assembly:</font>
          </p>
          <p>
            <font face="Courier New">
              <strong>// Metadata version: v2.0.50727<br />
.assembly extern mscorlib<br />
{<br />
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                        
// .z\V.4..<br />
  .ver 2:0:0:0<br />
}<br /></strong>
            </font>
            <font face="Courier New">
              <font size="2" face="Verdana">
                <br />
Notice the version difference .. Silverlight uses 2.0.5.0 of mscorlib and the desktop
CLR uses 2.0.0.0.  The public key is also different, but this is really just
used for loading purposes.</font>
            </font>
          </p>
          <p>
            <font size="2">Assuming the assembly doesn't use something Silverlight specific, we
can modify the assembly references and allow the asembly to be used in the desktop
CLR fairly easily.  </font>
          </p>
          <p>
            <font size="2">Here's how I did it for System.Reactive.dll:</font>
          </p>
          <font face="Courier New">
            <p>
              <font size="2">
                <strong>ILDASM System.Reactive.dll /out:SR.il</strong>
              </font>
            </p>
            <p>
              <font size="2" face="Verdana">change the assembly references in the resulting IL text
file (for mscorlib, system and system.core)</font>
            </p>
            <p>
              <font size="2">
                <strong>ILASM SR.il /resource=sr.res /output=WPF/System.Reactive.dll</strong>
              </font>
            </p>
            <p>
              <font size="2" face="Verdana">That gave me a desktop version of the assembly without
modifying anything in the code itself - much easier than my original reflector route!</font>
            </p>
            <p>
              <font size="2" face="Verdana">Next, I took a couple of the samples from the blog and
ported them to WPF - specifically, I took the events sample listed here <a href="http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-1-extension.html">http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-1-extension.html</a> and
ported it to WPF to test it.  I made very few changes, primarily just switching
Application.Current.MainWindow for Application.Current.RootVisual.  Here is the
resulting project and switched assembly for anyone who is interested in it. </font>
            </p>
            <p>
              <a href="http://www.julmar.com/blog/mark/content/binary/ExtensionEvents.zip">ExtensionEvents.zip
(44.62 KB)</a>
            </p>
            <p>
              <font size="2" face="Verdana">I think Rx is a fascinating piece of code, although
it will take me a bit of time to realize just what I can do with it I suspect. 
I'm looking forward to building more with this using WPF now that's for sure!</font>
            </p>
          </font>
        </font>
      </body>
      <title>Using Rx (Linq to Events) with WPF</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,43b8da4d-a392-46f9-9e03-939950798b41.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2009/08/03/UsingRxLinqToEventsWithWPF.aspx</link>
      <pubDate>Mon, 03 Aug 2009 15:56:03 GMT</pubDate>
      <description>&lt;p&gt;
A recent series of blog entries at &lt;a href="http://themechanicalbride.blogspot.com/"&gt;http://themechanicalbride.blogspot.com/&lt;/a&gt;&amp;nbsp;introduced
the Rx framework (System.Reactive.dll) which is an assembly used in the Silverlight
toolkit for UI testing purposes.&amp;nbsp; It essentially provides a mechanism to do event
driven programming through LINQ.&amp;nbsp; I'll refer you to the blog referenced above
for all the gory details - frankly I'm still trying to wrap my mind around it!
&lt;/p&gt;
&lt;p&gt;
Silverlight isn't my favorite technology however, I much prefer working in WPF and
so I spent some time rebuilding Rx for the desktop CLR!&amp;nbsp; My original approach
was to take my favorite exploration tool, reflector (available for free from &lt;a href="http://www.redgate.com"&gt;www.redgate.com&lt;/a&gt;),
and disassemble all the classes into C#, placing them into a project file.&amp;nbsp; I
found however that Reflector choked on some of the more complicated structures - requiring
me to go and hand-edit a bunch of the code.&amp;nbsp; I realized while I was doing this
that there was a much easier way to convert a Silverlight assembly to a WPF assembly.
&lt;/p&gt;
&lt;p&gt;
As you probably already know, Silverlight shares the same assembly format as the desktop
CLR - there is no difference in the IL or structure of the assembly itself.&amp;nbsp;
The difference is in the dependency on mscorlib and other references.&amp;nbsp; Specifically,
when you add an assembly via VS2008, it looks at the &lt;strong&gt;version&lt;/strong&gt; of the
referenced&amp;nbsp;mscorlib to determine whether it's a desktop CLR assembly or Silverlight
assembly.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Here's the header of a Silverlight assembly examined through ILDASM:
&lt;/p&gt;
&lt;font size=3&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;strong&gt;// Metadata version: v2.0.50727&lt;br&gt;
.assembly extern mscorlib&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; .publickeytoken = (7C EC 85 D7 BE A7 79 8E ) // |.....y.&lt;br&gt;
&amp;nbsp;&amp;nbsp; .ver 2:0:5:0&lt;br&gt;
}&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;Here is a desktop assembly:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;strong&gt;// Metadata version: v2.0.50727&lt;br&gt;
.assembly extern mscorlib&lt;br&gt;
{&lt;br&gt;
&amp;nbsp; .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// .z\V.4..&lt;br&gt;
&amp;nbsp; .ver 2:0:0:0&lt;br&gt;
}&lt;br&gt;
&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2 face=Verdana&gt;
&lt;br&gt;
Notice the version difference .. Silverlight uses 2.0.5.0 of mscorlib and the desktop
CLR uses 2.0.0.0.&amp;nbsp; The public key is also different, but this is really just
used for loading purposes.&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;Assuming the assembly doesn't use something Silverlight specific, we
can modify the assembly references and allow the asembly to be used in the desktop
CLR fairly easily.&amp;nbsp; &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;Here's how I did it for System.Reactive.dll:&lt;/font&gt;
&lt;/p&gt;
&lt;font face="Courier New"&gt; 
&lt;p&gt;
&lt;font size=2&gt;&lt;strong&gt;ILDASM System.Reactive.dll /out:SR.il&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face=Verdana&gt;change the assembly references in the resulting IL text
file (for mscorlib, system and system.core)&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;&lt;strong&gt;ILASM SR.il /resource=sr.res /output=WPF/System.Reactive.dll&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face=Verdana&gt;That gave me a desktop version of the assembly without modifying
anything in the code itself - much easier than my original reflector route!&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face=Verdana&gt;Next, I took a couple of the samples from the blog and ported
them to WPF - specifically, I took the events sample listed here &lt;a href="http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-1-extension.html"&gt;http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-1-extension.html&lt;/a&gt;&amp;nbsp;and
ported it to WPF to test it.&amp;nbsp; I made very few changes, primarily just switching
Application.Current.MainWindow for Application.Current.RootVisual.&amp;nbsp; Here is the
resulting project and switched assembly for anyone who is interested in it. &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.julmar.com/blog/mark/content/binary/ExtensionEvents.zip"&gt;ExtensionEvents.zip
(44.62 KB)&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face=Verdana&gt;I think Rx is a fascinating piece of code, although it will
take me a bit of time to realize just what I can do with it I suspect.&amp;nbsp; I'm looking
forward to building more with this using WPF now that's for sure!&lt;/font&gt;
&lt;/p&gt;
&lt;/font&gt;&lt;/font&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,43b8da4d-a392-46f9-9e03-939950798b41.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=7953f9ef-2003-444e-8f8a-f9a138bb030f</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,7953f9ef-2003-444e-8f8a-f9a138bb030f.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,7953f9ef-2003-444e-8f8a-f9a138bb030f.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=7953f9ef-2003-444e-8f8a-f9a138bb030f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of the coolest new features of Blend 3 is the inclusion of behaviors. This
new feature formalizes the "attached behavior" model that has become so prevelant
in WPF (and Silverlight) development.  I won't go into details on the architecture
- instead I'll refer you to a nice reference:
</p>
        <p>
          <a href="http://blogs.msdn.com/expression/archive/2009/05/19/link-round-up-behaviors-related-posts.aspx">http://blogs.msdn.com/expression/archive/2009/05/19/link-round-up-behaviors-related-posts.aspx</a>
        </p>
        <p>
To play with this new support, I built a WatermarkTextBehavior which places a watermark
into a TextBox when it has no entered data.  I've included this new behavior
into the current build of my MVVM toolkit which I'll release soon, but for now, let's
look at the behavior:
</p>
        <p>
First, we derive from <strong>System.Windows.Interactivity.Behavior&lt;T&gt;</strong> -
the placeholder parameter is the Visual type you want the behavior to act on. 
This can be <strong>UIElement</strong> for anything WPF, or more restrictive if necessary
based on the events you intend to hook up.  For our purposes here, we will set
the restricted type to <strong>TextBox</strong>.
</p>
        <font color="#0000ff" size="4">
          <font color="#0000ff" size="4">
            <p>
              <font size="3" face="Courier New">public</font>
            </p>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#000000">
            </font>
            <font color="#0000ff">
              <font color="#0000ff">class</font>
            </font>
            <font color="#000000">
            </font>
            <font color="#2b91af">
              <font color="#2b91af">WatermarkTextBehavior</font>
            </font>
            <font color="#000000"> : </font>
            <font color="#2b91af">
              <font color="#2b91af">Behavior</font>
            </font>
            <font color="#000000">&lt;</font>
            <font color="#2b91af">
              <font color="#2b91af">TextBox</font>
            </font>
            <font color="#000000">&gt;</font>
          </font>
          <font size="4">
          </font>
        </font>
        <p>
Next, you override the<strong> OnAttached()</strong> and<strong> OnDetaching()</strong> methods
to hook up your event behaviors you desire.  Call the base implementation first,
and then the <strong>AssociatedObject</strong> property will be the element you've
been attached to (the <strong>TextBox</strong> in this case).  In our case we
want to hook the <strong>GotFocus</strong> and <strong>LostFocus</strong> events -
this is where we trigger our behavior.
</p>
        <font color="#0000ff" size="4">
          <font color="#0000ff" size="4">
            <p>
              <font size="3" face="Courier New">protected</font>
            </p>
          </font>
        </font>
        <font size="3">
          <font face="Courier New">
            <font color="#000000">
            </font>
            <font color="#0000ff">
              <font color="#0000ff">override</font>
            </font>
            <font color="#000000">
            </font>
            <font color="#0000ff">
              <font color="#0000ff">void</font>
            </font>
          </font>
          <font color="#000000" face="Courier New"> OnAttached()<br /></font>
        </font>
        <font size="3" face="Courier New">{<br />
   </font>
        <font size="3">
          <font color="#0000ff">
            <font color="#0000ff" face="Courier New">base</font>
          </font>
          <font face="Courier New">.OnAttached();<br />
   </font>
        </font>
        <font size="3" face="Courier New">AssociatedObject.GotFocus
+= OnGotFocus;<br />
   </font>
        <font size="3" face="Courier New">AssociatedObject.LostFocus +=
OnLostFocus;<br />
   </font>
        <font size="3">
          <font face="Courier New">...</font>
          <font face="Courier New">
            <br />
          </font>
        </font>
        <font size="3" face="Courier New">}</font>
        <font size="3" face="Courier New">
          <font color="#0000ff" size="4">
            <font color="#0000ff" size="4">
              <p>
                <font size="3">protected</font>
              </p>
            </font>
          </font>
          <font color="#000000">
          </font>
          <font color="#0000ff">
            <font color="#0000ff">override</font>
          </font>
          <font color="#000000">
          </font>
          <font color="#0000ff">
            <font color="#0000ff">void</font>
          </font>
          <font color="#000000"> OnDetaching()<br /></font>{<br /><font color="#0000ff"><font color="#0000ff">   base</font></font>.OnDetaching();<br />
   AssociatedObject.GotFocus -= OnGotFocus;<br />
   AssociatedObject.LostFocus -= OnLostFocus;<br />
}
</font>
        <p>
Finally, we can provide any properties necessary to drive our behavior.  These
should be done in the form of Dependency Properties so they are bindable and interact
nicely with WPF.  The base<strong> Behavior&lt;T&gt;</strong> derives from <strong>Freezable</strong> and
inherits the DataContext automatically to enable this support.  In our implementation
we will have a Text property to indicate the watermark, and an attached property which
we will place onto the TextBox so it can be styled when the watermark is being used.
</p>
        <font size="4">
          <p>
          </p>
        </font>
        <font size="3">
          <font face="Courier New">
            <font color="#0000ff">
              <font color="#0000ff">public</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">static</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">readonly</font>
            </font>
            <font color="#2b91af">
              <font color="#2b91af">DependencyProperty</font>
            </font>
          </font>
          <font face="Courier New"> TextProperty
=<br />
   </font>
        </font>
        <font size="3">
          <font face="Courier New">
            <font color="#2b91af">
              <font color="#2b91af">DependencyProperty</font>
            </font>.Register(<font color="#a31515"><font color="#a31515">"Text"</font></font>, <font color="#0000ff"><font color="#0000ff">typeof</font></font> (<font color="#0000ff"><font color="#0000ff">string</font></font>), <font color="#0000ff"><font color="#0000ff">typeof</font></font> (<font color="#2b91af"><font color="#2b91af">WatermarkTextBehavior</font></font></font>
          <font face="Courier New">),<br />
                      </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">new</font>
            </font>
            <font color="#2b91af">
              <font color="#2b91af">FrameworkPropertyMetadata</font>
            </font>(<font color="#0000ff"><font color="#0000ff">string</font></font>.Empty));</font>
        </font>
        <p>
Next we can hook it up in Blend through the Asset panel - all known assets are shown
here (either registered, in the Blend directory, or project references).  Drag
our <strong>WatermarkTextBehavior</strong> onto any <strong>TextBox</strong> and set
the <strong>Text</strong> property and it will generate the following XAML:
</p>
        <font color="#a31515" size="4">
          <font color="#a31515" size="4">
            <p>
            </p>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">TextBox</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">  
&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">TextBox.Style</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">     
&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Style</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> TargetType</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="TextBox"</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> BasedOn</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="{</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">StaticResource</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff"> {</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">x</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">:</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Type</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> TextBox</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">}}"&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">        
&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Style.Triggers</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">           
&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Trigger</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> Property</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="julmar:WatermarkTextBehavior.IsWatermarked"</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> Value</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="True"&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">              
&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Setter</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> Property</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="Foreground"</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> Value</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="Gray"
/&gt;</font>
            </font>
          </font>
        </font>
        <font color="#a31515">
          <font color="#a31515">
            <font size="3" face="Courier New"> <br /></font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">               &lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Setter</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> Property</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="FontStyle"</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> Value</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="Italic"
/&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">            &lt;/</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Trigger</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">         &lt;/</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Style.Triggers</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">      &lt;/</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Style</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">   &lt;/</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">TextBox.Style</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">  
&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">i</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">:</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Interaction.Behaviors</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">     
&lt;</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">julmar</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">:</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">WatermarkTextBehavior</font>
            </font>
            <font color="#ff0000">
              <font color="#ff0000"> Text</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">="Enter
a name here" /&gt;<br /></font>
            </font>
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">  
&lt;/</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">i</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">:</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">Interaction.Behaviors</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;<br /></font>
            </font>
          </font>
        </font>
        <font color="#a31515">
          <font color="#a31515">
          </font>
        </font>
        <font face="Courier New">
          <font size="3">
            <font color="#0000ff">
              <font color="#0000ff">&lt;/</font>
            </font>
            <font color="#a31515">
              <font color="#a31515">TextBox</font>
            </font>
            <font color="#0000ff">
              <font color="#0000ff">&gt;
</font>
            </font>
          </font>
        </font>
        <p>
Here is the complete source code to the behavior:
</p>
        <pre>
          <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: black; FONT-SIZE: 11px">
            <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">using</span> System; <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">using</span> System.Windows; <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">using</span> System.Windows.Controls; <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">using</span> System.Windows.Interactivity; <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">namespace</span> JulMar.Windows.Interactivity
{ <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
This behavior associates a watermark onto a TextBox indicating what the user should</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
provide as input.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">public</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">class</span> WatermarkTextBehavior
: Behavior&lt;TextBox&gt; { <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
The watermark text</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">public</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">static</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">readonly</span> DependencyProperty
TextProperty <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px">=</span> DependencyProperty.Register(<span style="BACKGROUND-COLOR: #e4e4e4; FONT-FAMILY: Courier New; COLOR: #666666; FONT-SIZE: 11px">"Text"</span>, <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">typeof</span> (<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">string</span>), <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">typeof</span> (WatermarkTextBehavior), <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">new</span> FrameworkPropertyMetadata(<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">string</span>.Empty)); <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">static</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">readonly</span> DependencyPropertyKey
IsWatermarkedPropertyKey <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px">=</span> DependencyProperty.RegisterAttachedReadOnly(<span style="BACKGROUND-COLOR: #e4e4e4; FONT-FAMILY: Courier New; COLOR: #666666; FONT-SIZE: 11px">"IsWatermarked"</span>, <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">typeof</span>(<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">bool</span>), <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">typeof</span>(WatermarkTextBehavior), <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">new</span> FrameworkPropertyMetadata(<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">false</span>)); <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
This readonly property is applied to the TextBox and indicates whether the watermark</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
is currently being displayed. It allows a style to change the visual appearanve of
the</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
TextBox.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">public</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">static</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">readonly</span> DependencyProperty
IsWatermarkedProperty <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px">=</span> IsWatermarkedPropertyKey.DependencyProperty; <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
Retrieves the current watermarked state of the TextBox.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;param name="tb"&gt;&lt;/param&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;returns&gt;&lt;/returns&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">public</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">static</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">bool</span> GetIsWatermarked(TextBox
tb) { <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">return</span> (<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">bool</span>)
tb.GetValue(IsWatermarkedProperty); } <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
Retrieves the current watermarked state of the TextBox.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">public</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">bool</span> IsWatermarked
{ get { <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">return</span> GetIsWatermarked(AssociatedObject);
} <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">private</span> set
{ AssociatedObject.SetValue(IsWatermarkedPropertyKey, value);} } <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
The watermark text</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">public</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">string</span> Text
{ get { <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">return</span> (<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">string</span>) <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">base</span>.GetValue(TextProperty);
} set { <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">base</span>.SetValue(TextProperty,
value); } } <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
Called after the behavior is attached to an AssociatedObject.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;remarks&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
Override this to hook up functionality to the AssociatedObject.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/remarks&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">protected</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">override</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">void</span> OnAttached()
{ <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">base</span>.OnAttached();
AssociatedObject.GotFocus += OnGotFocus; AssociatedObject.LostFocus += OnLostFocus;
OnLostFocus(<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">null</span>, <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">null</span>);
} <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
Called when the behavior is being detached from its AssociatedObject, but before it
has actually occurred.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;remarks&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
Override this to unhook functionality from the AssociatedObject.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/remarks&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">protected</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">override</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">void</span> OnDetaching()
{ <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">base</span>.OnDetaching();
AssociatedObject.GotFocus -= OnGotFocus; AssociatedObject.LostFocus -= OnLostFocus;
} <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
This method is called when the textbox gains focus. It removes the watermark.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;param name="sender"&gt;&lt;/param&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;param name="e"&gt;&lt;/param&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">private</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">void</span> OnGotFocus(<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">object</span> sender,
RoutedEventArgs e) { <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">if</span> (<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">string</span>.Compare(AssociatedObject.Text, <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">this</span>.Text,
StringComparison.OrdinalIgnoreCase) == 0) { AssociatedObject.Text <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px">=</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">string</span>.Empty;
IsWatermarked <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px">=</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">false</span>;
} } <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
This method is called when focus is lost from the TextBox. It puts the watermark</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
into place if no text is in the textbox.</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;/summary&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;param name="sender"&gt;&lt;/param&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px">///
&lt;param name="e"&gt;&lt;/param&gt;</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">private</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">void</span> OnLostFocus(<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">object</span> sender,
RoutedEventArgs e) { <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">if</span> (<span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">string</span>.IsNullOrEmpty(AssociatedObject.Text))
{ AssociatedObject.Text <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px">=</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">this</span>.Text;
IsWatermarked <span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px">=</span><span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px">true</span>;
} } } } </span>
        </pre>
        <p>
 
</p>
      </body>
      <title>Playing with WPF Behaviors - a WatermarkText behavior</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,7953f9ef-2003-444e-8f8a-f9a138bb030f.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2009/07/24/PlayingWithWPFBehaviorsAWatermarkTextBehavior.aspx</link>
      <pubDate>Fri, 24 Jul 2009 19:14:52 GMT</pubDate>
      <description>&lt;p&gt;
One of the coolest new features of Blend 3 is the inclusion of behaviors.&amp;nbsp;This
new feature formalizes the "attached behavior" model that has become so prevelant
in WPF (and Silverlight) development.&amp;nbsp; I won't go into details on the architecture
- instead I'll refer you to a nice reference:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blogs.msdn.com/expression/archive/2009/05/19/link-round-up-behaviors-related-posts.aspx"&gt;http://blogs.msdn.com/expression/archive/2009/05/19/link-round-up-behaviors-related-posts.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
To play with this new support, I built a WatermarkTextBehavior which places a watermark
into a TextBox when it has no entered data.&amp;nbsp; I've included this new behavior
into the current build of my MVVM toolkit which I'll release soon, but for now, let's
look at the behavior:
&lt;/p&gt;
&lt;p&gt;
First, we derive from &lt;strong&gt;System.Windows.Interactivity.Behavior&amp;lt;T&amp;gt;&lt;/strong&gt; -
the placeholder parameter is the Visual type you want the behavior to act on.&amp;nbsp;
This can be &lt;strong&gt;UIElement&lt;/strong&gt; for anything WPF, or more restrictive if necessary
based on the events you intend to hook up.&amp;nbsp; For our purposes here, we will set
the restricted type to &lt;strong&gt;TextBox&lt;/strong&gt;.
&lt;/p&gt;
&lt;font color=#0000ff size=4&gt;&lt;font color=#0000ff size=4&gt; 
&lt;p&gt;
&lt;font size=3 face="Courier New"&gt;public&lt;/font&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;class&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#2b91af&gt;&lt;font color=#2b91af&gt;WatermarkTextBehavior&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt; : &lt;/font&gt;&lt;font color=#2b91af&gt;&lt;font color=#2b91af&gt;Behavior&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt;&amp;lt;&lt;/font&gt;&lt;font color=#2b91af&gt;&lt;font color=#2b91af&gt;TextBox&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;font size=4&gt;&gt;
&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;
Next, you override the&lt;strong&gt; OnAttached()&lt;/strong&gt; and&lt;strong&gt; OnDetaching()&lt;/strong&gt; methods
to hook up your event behaviors you desire.&amp;nbsp; Call the base implementation first,
and then the &lt;strong&gt;AssociatedObject&lt;/strong&gt; property will be the element you've
been attached to (the &lt;strong&gt;TextBox&lt;/strong&gt; in this case).&amp;nbsp; In our case we
want to hook the &lt;strong&gt;GotFocus&lt;/strong&gt; and &lt;strong&gt;LostFocus&lt;/strong&gt; events -
this is where we trigger our behavior.
&lt;/p&gt;
&lt;font color=#0000ff size=4&gt;&lt;font color=#0000ff size=4&gt; 
&lt;p&gt;
&lt;font size=3 face="Courier New"&gt;protected&lt;/font&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font face="Courier New"&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;override&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000 face="Courier New"&gt; OnAttached()&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font size=3 face="Courier New"&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff face="Courier New"&gt;base&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;.OnAttached();&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font size=3 face="Courier New"&gt;AssociatedObject.GotFocus
+= OnGotFocus;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3 face="Courier New"&gt;AssociatedObject.LostFocus +=
OnLostFocus;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&lt;font face="Courier New"&gt;...&lt;/font&gt;&lt;font face="Courier New"&gt;
&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font size=3 face="Courier New"&gt;}&lt;/font&gt;&gt;
&lt;font size=3 face="Courier New"&gt;&lt;font color=#0000ff size=4&gt;&lt;font color=#0000ff size=4&gt; 
&lt;p&gt;
&lt;font size=3&gt;protected&lt;/font&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;override&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt; OnDetaching()&lt;br&gt;
&lt;/font&gt;{&lt;br&gt;
&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp; base&lt;/font&gt;&lt;/font&gt;.OnDetaching();&lt;br&gt;
&amp;nbsp;&amp;nbsp; AssociatedObject.GotFocus -= OnGotFocus;&lt;br&gt;
&amp;nbsp;&amp;nbsp; AssociatedObject.LostFocus -= OnLostFocus;&lt;br&gt;
}&gt;
&lt;/font&gt; 
&lt;p&gt;
Finally, we can provide any properties necessary to drive our behavior.&amp;nbsp; These
should be done in the form of Dependency Properties so they are bindable and interact
nicely with WPF.&amp;nbsp; The base&lt;strong&gt; Behavior&amp;lt;T&amp;gt;&lt;/strong&gt; derives from &lt;strong&gt;Freezable&lt;/strong&gt; and
inherits the DataContext automatically to enable this support.&amp;nbsp; In our implementation
we will have a Text property to indicate the watermark, and an attached property which
we will place onto the TextBox so it can be styled when the watermark is being used.
&lt;/p&gt;
&lt;font size=4&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font size=3&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;public&lt;/font&gt;&lt;/font&gt; &lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;static&lt;/font&gt;&lt;/font&gt; &lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;readonly&lt;/font&gt;&lt;/font&gt; &lt;font color=#2b91af&gt;&lt;font color=#2b91af&gt;DependencyProperty&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt; TextProperty
=&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font face="Courier New"&gt;&lt;font color=#2b91af&gt;&lt;font color=#2b91af&gt;DependencyProperty&lt;/font&gt;&lt;/font&gt;.Register(&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;"Text"&lt;/font&gt;&lt;/font&gt;, &lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;typeof&lt;/font&gt;&lt;/font&gt; (&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;string&lt;/font&gt;&lt;/font&gt;), &lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;typeof&lt;/font&gt;&lt;/font&gt; (&lt;font color=#2b91af&gt;&lt;font color=#2b91af&gt;WatermarkTextBehavior&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;new&lt;/font&gt;&lt;/font&gt; &lt;font color=#2b91af&gt;&lt;font color=#2b91af&gt;FrameworkPropertyMetadata&lt;/font&gt;&lt;/font&gt;(&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;string&lt;/font&gt;&lt;/font&gt;.Empty));&lt;/font&gt;&gt;
&lt;/font&gt; 
&lt;p&gt;
Next we can hook it up in Blend through the Asset panel - all known assets are shown
here (either registered, in the Blend directory, or project references).&amp;nbsp; Drag
our &lt;strong&gt;WatermarkTextBehavior&lt;/strong&gt; onto any &lt;strong&gt;TextBox&lt;/strong&gt; and set
the &lt;strong&gt;Text&lt;/strong&gt; property and it will generate the following XAML:
&lt;/p&gt;
&lt;font color=#a31515 size=4&gt;&lt;font color=#a31515 size=4&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;TextBox&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;TextBox.Style&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Style&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; TargetType&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="TextBox"&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; BasedOn&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="{&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;StaticResource&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt; {&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;x&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;:&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Type&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; TextBox&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;}}"&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Style.Triggers&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Trigger&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; Property&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="julmar:WatermarkTextBehavior.IsWatermarked"&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; Value&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="True"&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Setter&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; Property&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="Foreground"&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; Value&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="Gray"
/&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;&lt;font size=3 face="Courier New"&gt;&amp;nbsp;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Setter&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; Property&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="FontStyle"&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; Value&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="Italic"
/&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Trigger&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Style.Triggers&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Style&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;TextBox.Style&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;i&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;:&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Interaction.Behaviors&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;julmar&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;:&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;WatermarkTextBehavior&lt;/font&gt;&lt;/font&gt;&lt;font color=#ff0000&gt;&lt;font color=#ff0000&gt; Text&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;="Enter
a name here" /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;
&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;i&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;:&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;Interaction.Behaviors&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#a31515&gt;&lt;font color=#a31515&gt;TextBox&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font color=#0000ff&gt;&amp;gt;&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;
Here is the complete source code to the behavior:
&lt;/p&gt;
&lt;pre&gt;&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: black; FONT-SIZE: 11px"&gt;&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;using&lt;/span&gt; System; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;using&lt;/span&gt; System.Windows; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;using&lt;/span&gt; System.Windows.Controls; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;using&lt;/span&gt; System.Windows.Interactivity; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;namespace&lt;/span&gt; JulMar.Windows.Interactivity
{ &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
This behavior associates a watermark onto a TextBox indicating what the user should&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
provide as input.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;public&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;class&lt;/span&gt; WatermarkTextBehavior
: Behavior&amp;lt;TextBox&amp;gt; { &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
The watermark text&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;public&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;static&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;readonly&lt;/span&gt; DependencyProperty
TextProperty &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px"&gt;=&lt;/span&gt; DependencyProperty.Register(&lt;span style="BACKGROUND-COLOR: #e4e4e4; FONT-FAMILY: Courier New; COLOR: #666666; FONT-SIZE: 11px"&gt;"Text"&lt;/span&gt;, &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;typeof&lt;/span&gt; (&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;string&lt;/span&gt;), &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;typeof&lt;/span&gt; (WatermarkTextBehavior), &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;new&lt;/span&gt; FrameworkPropertyMetadata(&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;string&lt;/span&gt;.Empty)); &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;static&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;readonly&lt;/span&gt; DependencyPropertyKey
IsWatermarkedPropertyKey &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px"&gt;=&lt;/span&gt; DependencyProperty.RegisterAttachedReadOnly(&lt;span style="BACKGROUND-COLOR: #e4e4e4; FONT-FAMILY: Courier New; COLOR: #666666; FONT-SIZE: 11px"&gt;"IsWatermarked"&lt;/span&gt;, &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;typeof&lt;/span&gt;(&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;bool&lt;/span&gt;), &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;typeof&lt;/span&gt;(WatermarkTextBehavior), &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;new&lt;/span&gt; FrameworkPropertyMetadata(&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;false&lt;/span&gt;)); &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
This readonly property is applied to the TextBox and indicates whether the watermark&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
is currently being displayed. It allows a style to change the visual appearanve of
the&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
TextBox.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;public&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;static&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;readonly&lt;/span&gt; DependencyProperty
IsWatermarkedProperty &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px"&gt;=&lt;/span&gt; IsWatermarkedPropertyKey.DependencyProperty; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
Retrieves the current watermarked state of the TextBox.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;param name="tb"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;public&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;static&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;bool&lt;/span&gt; GetIsWatermarked(TextBox
tb) { &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;return&lt;/span&gt; (&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;bool&lt;/span&gt;)
tb.GetValue(IsWatermarkedProperty); } &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
Retrieves the current watermarked state of the TextBox.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;public&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;bool&lt;/span&gt; IsWatermarked
{ get { &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;return&lt;/span&gt; GetIsWatermarked(AssociatedObject);
} &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;private&lt;/span&gt; set
{ AssociatedObject.SetValue(IsWatermarkedPropertyKey, value);} } &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
The watermark text&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;public&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;string&lt;/span&gt; Text
{ get { &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;return&lt;/span&gt; (&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;string&lt;/span&gt;) &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;base&lt;/span&gt;.GetValue(TextProperty);
} set { &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;base&lt;/span&gt;.SetValue(TextProperty,
value); } } &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
Called after the behavior is attached to an AssociatedObject.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;remarks&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
Override this to hook up functionality to the AssociatedObject.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/remarks&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;protected&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;override&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;void&lt;/span&gt; OnAttached()
{ &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;base&lt;/span&gt;.OnAttached();
AssociatedObject.GotFocus += OnGotFocus; AssociatedObject.LostFocus += OnLostFocus;
OnLostFocus(&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;null&lt;/span&gt;, &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;null&lt;/span&gt;);
} &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
Called when the behavior is being detached from its AssociatedObject, but before it
has actually occurred.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;remarks&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
Override this to unhook functionality from the AssociatedObject.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/remarks&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;protected&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;override&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;void&lt;/span&gt; OnDetaching()
{ &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;base&lt;/span&gt;.OnDetaching();
AssociatedObject.GotFocus -= OnGotFocus; AssociatedObject.LostFocus -= OnLostFocus;
} &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
This method is called when the textbox gains focus. It removes the watermark.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;private&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;void&lt;/span&gt; OnGotFocus(&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;object&lt;/span&gt; sender,
RoutedEventArgs e) { &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;if&lt;/span&gt; (&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;string&lt;/span&gt;.Compare(AssociatedObject.Text, &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;this&lt;/span&gt;.Text,
StringComparison.OrdinalIgnoreCase) == 0) { AssociatedObject.Text &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px"&gt;=&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;string&lt;/span&gt;.Empty;
IsWatermarked &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px"&gt;=&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;false&lt;/span&gt;;
} } &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
This method is called when focus is lost from the TextBox. It puts the watermark&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
into place if no text is in the textbox.&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: green; FONT-SIZE: 11px"&gt;///
&amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;private&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;void&lt;/span&gt; OnLostFocus(&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;object&lt;/span&gt; sender,
RoutedEventArgs e) { &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;if&lt;/span&gt; (&lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;string&lt;/span&gt;.IsNullOrEmpty(AssociatedObject.Text))
{ AssociatedObject.Text &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px"&gt;=&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;this&lt;/span&gt;.Text;
IsWatermarked &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: red; FONT-SIZE: 11px"&gt;=&lt;/span&gt; &lt;span style="BACKGROUND-COLOR: transparent; FONT-FAMILY: Courier New; COLOR: blue; FONT-SIZE: 11px"&gt;true&lt;/span&gt;;
} } } } &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,7953f9ef-2003-444e-8f8a-f9a138bb030f.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=3e5e25ec-d3e6-4a15-9fbb-aeb7e354583e</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,3e5e25ec-d3e6-4a15-9fbb-aeb7e354583e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,3e5e25ec-d3e6-4a15-9fbb-aeb7e354583e.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=3e5e25ec-d3e6-4a15-9fbb-aeb7e354583e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A project I've been working on for the last two months is finally online in beta form
- check out
</p>
        <p>
          <a href="http://rcat.codeplex.com/">http://rcat.codeplex.com/</a>
        </p>
        <p>
It's essentially a biological alignment viewer for RNA sequences.  Here's a couple
of screen shots:
</p>
        <p>
          <strong>Alignment Viewer</strong>
        </p>
        <p>
          <img style="WIDTH: 648px; HEIGHT: 383px" border="0" src="http://www.julmar.com/blog/mark/content/binary/rCat001.jpg" width="830" height="488" />
        </p>
        <p>
          <strong>2D Structure Viewer</strong>
        </p>
        <p>
          <img style="WIDTH: 720px; HEIGHT: 441px" border="0" src="http://www.julmar.com/blog/mark/content/binary/rCat002.jpg" width="812" height="495" />
        </p>
        <p>
          <strong>2D Circle relationship Viewer</strong>
        </p>
        <p>
          <img style="WIDTH: 767px; HEIGHT: 403px" border="0" src="http://www.julmar.com/blog/mark/content/binary/rCat003.jpg" width="883" height="489" />
        </p>
        <p>
You can download the source code from the above link to play with it - it's a MVVM
implementation and has quite a bit of interesting optimizations in it for performance
purposes, including a read-only data virtualization for large sequence manipulation. 
The next release will include a full read/write implementation so watch the project
if you are interested!
</p>
        <p>
 
</p>
      </body>
      <title>rCAT 1.0 beta is online</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,3e5e25ec-d3e6-4a15-9fbb-aeb7e354583e.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2009/07/06/rCAT10BetaIsOnline.aspx</link>
      <pubDate>Mon, 06 Jul 2009 18:24:44 GMT</pubDate>
      <description>&lt;p&gt;
A project I've been working on for the last two months is finally online in beta form
- check out
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://rcat.codeplex.com/"&gt;http://rcat.codeplex.com/&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
It's essentially a biological alignment viewer for RNA sequences.&amp;nbsp; Here's a couple
of screen shots:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Alignment Viewer&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img style="WIDTH: 648px; HEIGHT: 383px" border=0 src="http://www.julmar.com/blog/mark/content/binary/rCat001.jpg" width=830 height=488&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;2D Structure Viewer&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img style="WIDTH: 720px; HEIGHT: 441px" border=0 src="http://www.julmar.com/blog/mark/content/binary/rCat002.jpg" width=812 height=495&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;2D Circle relationship Viewer&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img style="WIDTH: 767px; HEIGHT: 403px" border=0 src="http://www.julmar.com/blog/mark/content/binary/rCat003.jpg" width=883 height=489&gt;
&lt;/p&gt;
&lt;p&gt;
You can download the source code from the above link to play with it - it's a MVVM
implementation and has quite a bit of interesting optimizations in it for performance
purposes, including a read-only data virtualization for large sequence manipulation.&amp;nbsp;
The next release will include a full read/write implementation so watch the project
if you are interested!
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,3e5e25ec-d3e6-4a15-9fbb-aeb7e354583e.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>Real World</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=eca611aa-f16c-4db9-b84b-5149984d9f3b</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,eca611aa-f16c-4db9-b84b-5149984d9f3b.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,eca611aa-f16c-4db9-b84b-5149984d9f3b.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=eca611aa-f16c-4db9-b84b-5149984d9f3b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <b>Update</b>
        <br />
Microsoft has released the API code pack including Windows 7 support -- get it here: <a href="http://code.msdn.microsoft.com/WindowsAPICodePack">http://code.msdn.microsoft.com/WindowsAPICodePack</a><br /><br />
Well, it's been a while since I posted anything, I'm sorry! 
<br /><br />
I've been busy working with Windows 7 and Microsoft Surface touch-computing. To that
end, I needed to get access to some of the new Windows 7 APIs in managed code ...
which isn't supported yet (but is coming). 
<br /><br />
So I built an interop library to access: <strong><br /><br /></strong><ul><li><strong>Scenic Ribbon (native Win32 ribbon) in Windows Forms</strong></li><li><strong> Native WM_TOUCH and WM_GESTURE messages</strong></li><li><strong> Sensor API</strong></li><li><strong> Shell APIs (jump lists, thumbnail buttons, libraries) </strong></li></ul><strong>One note:</strong> I make no guarantee that everything is correct (it's hard
to do that on a shifting beta with minimal docs, but in addition I'm not sure I've
gotten 100% coverage with everything anyway). Here's the interop library with source
code: 
<br /><br /><a href="http://www.julmar.com/samples/win7Interop.zip">Windows 7 Beta 1 Interop Library
for .NET 2.0</a><br /><br />
I'll be posting more details and samples a bit later, here's a couple to get you started. 
<br /><br />
Here's a simple example of using the Scenic Ribbon and native touch support to create
a (very) simple Windows Forms finger<br />
paint program:<br /><br /><img src="http://www.julmar.com/blog/mark/content/binary/touch_img.jpg" alt="touch_img.jpg" border="0" height="469" width="699" /><br /><br /><a href="http://www.julmar.com/samples/touch_sample.zip">Multi Touch example with
Windows Forms</a><br /><br />
Here's a simple example of using the gestures and library support in a WPF application.
It grabs all the directories in your Pictures Library and then shows you each picture
and lets you use the swipe gesture to move between then, pinch to scale and of course,
rotate. 
<br /><br /><img src="http://www.julmar.com/blog/mark/content/binary/gesture_img.jpg" alt="gesture_img.jpg" border="0" height="372" width="498" /><br /><br /><a href="http://www.julmar.com/samples/gesture_sample.zip">Gesture example with WPF</a><br /><br />
Both of these samples work with the HP Touchmate (and multi-touch drivers) and Windows
7 Beta 1. Have fun! -mark</body>
      <title>It's been such a long time.. [WPF + Windows 7]</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,eca611aa-f16c-4db9-b84b-5149984d9f3b.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2009/01/29/ItsBeenSuchALongTimeWPFWindows7.aspx</link>
      <pubDate>Thu, 29 Jan 2009 18:02:21 GMT</pubDate>
      <description>&lt;b&gt;Update&lt;/b&gt;
&lt;br /&gt;
Microsoft has released the API code pack including Windows 7 support -- get it here: &lt;a href="http://code.msdn.microsoft.com/WindowsAPICodePack"&gt;http://code.msdn.microsoft.com/WindowsAPICodePack&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
Well, it's been a while since I posted anything, I'm sorry! 
&lt;br&gt;
&lt;br&gt;
I've been busy working with Windows 7 and Microsoft Surface touch-computing. To that
end, I needed to get access to some of the new Windows 7 APIs in managed code ...
which isn't supported yet (but is coming). 
&lt;br&gt;
&lt;br&gt;
So I built an interop library to access: &lt;strong&gt; 
&lt;br&gt;
&lt;br&gt;
&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenic Ribbon (native Win32 ribbon) in Windows Forms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt; Native WM_TOUCH and WM_GESTURE messages&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt; Sensor API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt; Shell APIs (jump lists, thumbnail buttons, libraries) &lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;One note:&lt;/strong&gt; I make no guarantee that everything is correct (it's hard
to do that on a shifting beta with minimal docs, but in addition I'm not sure I've
gotten 100% coverage with everything anyway). Here's the interop library with source
code: 
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.julmar.com/samples/win7Interop.zip"&gt;Windows 7 Beta 1 Interop Library
for .NET 2.0&lt;/a&gt; 
&lt;br&gt;
&lt;br&gt;
I'll be posting more details and samples a bit later, here's a couple to get you started. 
&lt;br&gt;
&lt;br&gt;
Here's a simple example of using the Scenic Ribbon and native touch support to create
a (very) simple Windows Forms finger&lt;br&gt;
paint program:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.julmar.com/blog/mark/content/binary/touch_img.jpg" alt="touch_img.jpg" border="0" height="469" width="699"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.julmar.com/samples/touch_sample.zip"&gt;Multi Touch example with
Windows Forms&lt;/a&gt; 
&lt;br&gt;
&lt;br&gt;
Here's a simple example of using the gestures and library support in a WPF application.
It grabs all the directories in your Pictures Library and then shows you each picture
and lets you use the swipe gesture to move between then, pinch to scale and of course,
rotate. 
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.julmar.com/blog/mark/content/binary/gesture_img.jpg" alt="gesture_img.jpg" border="0" height="372" width="498"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.julmar.com/samples/gesture_sample.zip"&gt;Gesture example with WPF&lt;/a&gt; 
&lt;br&gt;
&lt;br&gt;
Both of these samples work with the HP Touchmate (and multi-touch drivers) and Windows 7 Beta 1.

Have fun!

-mark</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,eca611aa-f16c-4db9-b84b-5149984d9f3b.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=39b19479-d49d-4f4c-b1b5-af2a8ef59ade</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,39b19479-d49d-4f4c-b1b5-af2a8ef59ade.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,39b19479-d49d-4f4c-b1b5-af2a8ef59ade.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=39b19479-d49d-4f4c-b1b5-af2a8ef59ade</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Thanks to all who attended - it was great
to meet all of you and hang out until the wee hours and play Rock Band!  
<br /><br /><a href="http://www.julmar.com/DMStuff/demos.zip">Here are the demos from the class</a> -
I removed most of the binaries to bring it down to a reasonable size.<br /><br />
I also put the <a href="http://www.flickr.com/gp/62167965@N00/84Y4ba">pictures online
at Flickr</a><br /><br />
Thanks again everyone!<br /><br /><br /><p></p></body>
      <title>GNET demos from LA</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,39b19479-d49d-4f4c-b1b5-af2a8ef59ade.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2008/09/22/GNETDemosFromLA.aspx</link>
      <pubDate>Mon, 22 Sep 2008 13:33:32 GMT</pubDate>
      <description>Thanks to all who attended - it was great to meet all of you and hang out until the wee hours and play Rock Band!&amp;nbsp; &lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.julmar.com/DMStuff/demos.zip"&gt;Here are the demos from the class&lt;/a&gt; -
I removed most of the binaries to bring it down to a reasonable size.&lt;br&gt;
&lt;br&gt;
I also put the &lt;a href="http://www.flickr.com/gp/62167965@N00/84Y4ba"&gt;pictures online
at Flickr&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
Thanks again everyone!&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,39b19479-d49d-4f4c-b1b5-af2a8ef59ade.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=adc227ac-2da6-4ad4-8b7e-e7d5aee32fb2</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,adc227ac-2da6-4ad4-8b7e-e7d5aee32fb2.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,adc227ac-2da6-4ad4-8b7e-e7d5aee32fb2.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=adc227ac-2da6-4ad4-8b7e-e7d5aee32fb2</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">It's been a long time since I blogged anything
specific on WPF -- I've been doing a lot of it lately, along with some Silverlight. 
Recently I was experimenting with dragging tabs around on a TabControl at runtime. 
My end goal is really to implement it with Silverlight 2, but I've found it's much
easier to prototype things in WPF and then port them over because the debugging experience
is easier with WPF.<br /><br />
I didn't want to create derived implementations of any classes - I wanted something
that was non-intrusive to my code so I decided to use an <a href="http://msdn.microsoft.com/en-us/library/ms749011.aspx">attached
property</a>.  Attached properties are basically property values "attached" to
a class at runtime - where the property itself isn't defined on the target but instead
on some other type.  The cool thing about attached properties is they can register
a change notification handler which gives them a reference to the object they are
being placed on -- this is how the Spell Checker works with the TextBox in WPF. 
All the code for the spell checking lives in the SpellChecker class and when you add
the SpellCheck.IsEnabled property onto the TextBox, it adds handlers to the TextBlock's
TextChanged property and adds all the nifty spell checking goodness <i>without changing
the code in TextBox</i>.<br /><br />
Back to my drag/drop prototype.  So with this code, I can add the property to
any TabControl and get a nice, simple drag/drop experience.  It's far from complete
- it would be cooler if the tabs moved around as you dragged (they don't), but I was
just prototyping here.<br /><br />
Here's the code:<br /><br /><br /><p><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"></span><br /></span></p><br /><p></p><!-- code formatted by http://manoli.net/csharpformat/ --><style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
</style><pre class="csharpcode"><span class="kwrd">using</span> System; <span class="kwrd">using</span> System.Diagnostics; <span class="kwrd">using</span> System.Windows; <span class="kwrd">using</span> System.Windows.Controls; <span class="kwrd">using</span> System.Windows.Input; <span class="kwrd">using</span> System.Windows.Media; <span class="kwrd">namespace</span> WpfApplication1
{ <span class="kwrd">public</span><span class="kwrd">class</span> DragDropTabManager
{ <span class="kwrd">private</span><span class="kwrd">static</span><span class="kwrd">readonly</span> DependencyProperty
ManagerProperty = DependencyProperty.Register(<span class="kwrd">typeof</span> (DragDropTabManager).ToString(), <span class="kwrd">typeof</span> (DragDropTabManager), <span class="kwrd">typeof</span> (DragDropTabManager)); <span class="kwrd">public</span><span class="kwrd">static</span><span class="kwrd">readonly</span> DependencyProperty
EnabledProperty = DependencyProperty.RegisterAttached(<span class="str">"Enabled"</span>, <span class="kwrd">typeof</span>(<span class="kwrd">bool</span>), <span class="kwrd">typeof</span>(DragDropTabManager), <span class="kwrd">new</span> PropertyMetadata(<span class="kwrd">false</span>,
DDTM_EnabledChanged)); <span class="kwrd">private</span><span class="kwrd">static</span><span class="kwrd">void</span> DDTM_EnabledChanged(DependencyObject
d, DependencyPropertyChangedEventArgs e) { var tc = d <span class="kwrd">as</span> TabControl; <span class="kwrd">if</span> (tc
!= <span class="kwrd">null</span>) { var oldValue = (<span class="kwrd">bool</span>)
e.OldValue; var newValue = (<span class="kwrd">bool</span>) e.NewValue; <span class="kwrd">if</span> (oldValue
== <span class="kwrd">true</span> &amp;&amp; newValue == <span class="kwrd">false</span>)
{ var ddtm = tc.GetValue(ManagerProperty) <span class="kwrd">as</span> DragDropTabManager; <span class="kwrd">if</span> (ddtm
!= <span class="kwrd">null</span>) { tc.PreviewMouseDown -= ddtm.TabItem_PreviewMouseDown;
tc.SetValue(ManagerProperty, <span class="kwrd">null</span>); } } <span class="kwrd">else</span><span class="kwrd">if</span> (oldValue
== <span class="kwrd">false</span> &amp;&amp; newValue == <span class="kwrd">true</span>)
{ var ddtm = <span class="kwrd">new</span> DragDropTabManager(); tc.SetValue(ManagerProperty,
ddtm); tc.PreviewMouseDown += ddtm.TabItem_PreviewMouseDown; } } } <span class="kwrd">public</span><span class="kwrd">static</span><span class="kwrd">bool</span> GetEnabled(DependencyObject
obj) { <span class="kwrd">return</span> (<span class="kwrd">bool</span>)obj.GetValue(EnabledProperty);
} <span class="kwrd">public</span><span class="kwrd">static</span><span class="kwrd">void</span> SetEnabled(DependencyObject
obj, <span class="kwrd">bool</span><span class="kwrd">value</span>) { obj.SetValue(EnabledProperty, <span class="kwrd">value</span>);
} <span class="kwrd">private</span><span class="kwrd">bool</span> isMoving; <span class="kwrd">private</span> TabItem
movingTabItem; <span class="kwrd">private</span> TabItem lastTab; <span class="kwrd">private</span> Point
ptStart; <span class="kwrd">void</span> TabItem_PreviewMouseDown(<span class="kwrd">object</span> sender,
MouseEventArgs e) { var ti = e.Source <span class="kwrd">as</span> TabItem; <span class="kwrd">if</span> (ti
!= <span class="kwrd">null</span> &amp;&amp; e.LeftButton == MouseButtonState.Pressed)
{ var tc = ti.Parent <span class="kwrd">as</span> TabControl; <span class="kwrd">if</span> (tc
!= <span class="kwrd">null</span>) { tc.MouseMove += tc_MouseMove; tc.MouseLeftButtonUp
+= tc_MouseLeftButtonUp; ptStart = e.GetPosition(tc); movingTabItem = ti; } } } <span class="kwrd">void</span> tc_MouseMove(<span class="kwrd">object</span> sender,
MouseEventArgs e) { var tc = sender <span class="kwrd">as</span> TabControl; <span class="kwrd">if</span> (tc
== <span class="kwrd">null</span>) <span class="kwrd">return</span>; Point pt = e.GetPosition(tc); <span class="kwrd">if</span> (isMoving
== <span class="kwrd">false</span>) { <span class="kwrd">if</span> (Math.Abs(pt.X
- ptStart.X) &gt; 10) { movingTabItem.IsHitTestVisible = <span class="kwrd">false</span>;
movingTabItem.RenderTransformOrigin = <span class="kwrd">new</span> Point(.5, .5);
movingTabItem.RenderTransform = <span class="kwrd">new</span> TranslateTransform(0,
0); tc.Cursor = Cursors.Hand; Panel.SetZIndex(movingTabItem, 1); isMoving = <span class="kwrd">true</span>;
tc.CaptureMouse(); } <span class="kwrd">return</span>; } TabItem newPos = FindTabItem(tc,
pt); <span class="kwrd">if</span> (newPos == <span class="kwrd">null</span>) tc.Cursor
= Cursors.No; <span class="kwrd">else</span> { lastTab = newPos; var xform = movingTabItem.RenderTransform <span class="kwrd">as</span> TranslateTransform; <span class="kwrd">if</span> (xform
!= <span class="kwrd">null</span>) xform.X = pt.X - ptStart.X; tc.Cursor = Cursors.Hand;
} } <span class="kwrd">void</span> tc_MouseLeftButtonUp(<span class="kwrd">object</span> sender,
MouseButtonEventArgs e) { var tc = sender <span class="kwrd">as</span> TabControl;
Debug.Assert(tc != <span class="kwrd">null</span>); tc.ReleaseMouseCapture(); tc.MouseMove
-= tc_MouseMove; tc.MouseLeftButtonUp -= tc_MouseLeftButtonUp; <span class="kwrd">if</span> (isMoving
== <span class="kwrd">true</span>) { isMoving = <span class="kwrd">false</span>; tc.Cursor
= Cursors.Arrow; movingTabItem.RenderTransform = <span class="kwrd">null</span>; movingTabItem.IsHitTestVisible
= <span class="kwrd">true</span>; Panel.SetZIndex(movingTabItem, 0); <span class="kwrd">if</span> (lastTab
!= <span class="kwrd">null</span>) { <span class="kwrd">if</span> (lastTab != <span class="kwrd">null</span> &amp;&amp;
movingTabItem != lastTab) { <span class="kwrd">int</span> targetIndex = tc.Items.IndexOf(lastTab);
tc.Items.Remove(movingTabItem); tc.Items.Insert(targetIndex, movingTabItem); movingTabItem.Focus();
} } } movingTabItem = lastTab = <span class="kwrd">null</span>; } <span class="kwrd">private</span><span class="kwrd">static</span> TabItem
FindTabItem(UIElement parent, Point pt) { var fe = parent.InputHitTest(pt) <span class="kwrd">as</span> FrameworkElement; <span class="kwrd">while</span> (fe
!= <span class="kwrd">null</span> &amp;&amp; fe.GetType() != <span class="kwrd">typeof</span>(TabItem))
fe = VisualTreeHelper.GetParent(fe) <span class="kwrd">as</span> FrameworkElement; <span class="kwrd">return</span> fe <span class="kwrd">as</span> TabItem;
} } } </pre></body>
      <title>Implementing Drag/Drop with TabControl</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,adc227ac-2da6-4ad4-8b7e-e7d5aee32fb2.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2008/07/25/ImplementingDragDropWithTabControl.aspx</link>
      <pubDate>Fri, 25 Jul 2008 20:09:45 GMT</pubDate>
      <description>It's been a long time since I blogged anything specific on WPF -- I've been doing a lot of it lately, along with some Silverlight.&amp;nbsp; Recently I was experimenting with dragging tabs around on a TabControl at runtime.&amp;nbsp; My end goal is really to implement it with Silverlight 2, but I've found it's much easier to prototype things in WPF and then port them over because the debugging experience is easier with WPF.&lt;br&gt;
&lt;br&gt;
I didn't want to create derived implementations of any classes - I wanted something
that was non-intrusive to my code so I decided to use an &lt;a href="http://msdn.microsoft.com/en-us/library/ms749011.aspx"&gt;attached
property&lt;/a&gt;.&amp;nbsp; Attached properties are basically property values "attached" to
a class at runtime - where the property itself isn't defined on the target but instead
on some other type.&amp;nbsp; The cool thing about attached properties is they can register
a change notification handler which gives them a reference to the object they are
being placed on -- this is how the Spell Checker works with the TextBox in WPF.&amp;nbsp;
All the code for the spell checking lives in the SpellChecker class and when you add
the SpellCheck.IsEnabled property onto the TextBox, it adds handlers to the TextBlock's
TextChanged property and adds all the nifty spell checking goodness &lt;i&gt;without changing
the code in TextBox&lt;/i&gt;.&lt;br&gt;
&lt;br&gt;
Back to my drag/drop prototype.&amp;nbsp; So with this code, I can add the property to
any TabControl and get a nice, simple drag/drop experience.&amp;nbsp; It's far from complete
- it would be cooler if the tabs moved around as you dragged (they don't), but I was
just prototyping here.&lt;br&gt;
&lt;br&gt;
Here's the code:&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;
&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;/span&gt;
&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Controls; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Input; &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Media; &lt;span class="kwrd"&gt;namespace&lt;/span&gt; WpfApplication1
{ &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DragDropTabManager
{ &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DependencyProperty
ManagerProperty = DependencyProperty.Register(&lt;span class="kwrd"&gt;typeof&lt;/span&gt; (DragDropTabManager).ToString(), &lt;span class="kwrd"&gt;typeof&lt;/span&gt; (DragDropTabManager), &lt;span class="kwrd"&gt;typeof&lt;/span&gt; (DragDropTabManager)); &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DependencyProperty
EnabledProperty = DependencyProperty.RegisterAttached(&lt;span class="str"&gt;"Enabled"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;bool&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(DragDropTabManager), &lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyMetadata(&lt;span class="kwrd"&gt;false&lt;/span&gt;,
DDTM_EnabledChanged)); &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DDTM_EnabledChanged(DependencyObject
d, DependencyPropertyChangedEventArgs e) { var tc = d &lt;span class="kwrd"&gt;as&lt;/span&gt; TabControl; &lt;span class="kwrd"&gt;if&lt;/span&gt; (tc
!= &lt;span class="kwrd"&gt;null&lt;/span&gt;) { var oldValue = (&lt;span class="kwrd"&gt;bool&lt;/span&gt;)
e.OldValue; var newValue = (&lt;span class="kwrd"&gt;bool&lt;/span&gt;) e.NewValue; &lt;span class="kwrd"&gt;if&lt;/span&gt; (oldValue
== &lt;span class="kwrd"&gt;true&lt;/span&gt; &amp;amp;&amp;amp; newValue == &lt;span class="kwrd"&gt;false&lt;/span&gt;)
{ var ddtm = tc.GetValue(ManagerProperty) &lt;span class="kwrd"&gt;as&lt;/span&gt; DragDropTabManager; &lt;span class="kwrd"&gt;if&lt;/span&gt; (ddtm
!= &lt;span class="kwrd"&gt;null&lt;/span&gt;) { tc.PreviewMouseDown -= ddtm.TabItem_PreviewMouseDown;
tc.SetValue(ManagerProperty, &lt;span class="kwrd"&gt;null&lt;/span&gt;); } } &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (oldValue
== &lt;span class="kwrd"&gt;false&lt;/span&gt; &amp;amp;&amp;amp; newValue == &lt;span class="kwrd"&gt;true&lt;/span&gt;)
{ var ddtm = &lt;span class="kwrd"&gt;new&lt;/span&gt; DragDropTabManager(); tc.SetValue(ManagerProperty,
ddtm); tc.PreviewMouseDown += ddtm.TabItem_PreviewMouseDown; } } } &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; GetEnabled(DependencyObject
obj) { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;bool&lt;/span&gt;)obj.GetValue(EnabledProperty);
} &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetEnabled(DependencyObject
obj, &lt;span class="kwrd"&gt;bool&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;) { obj.SetValue(EnabledProperty, &lt;span class="kwrd"&gt;value&lt;/span&gt;);
} &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; isMoving; &lt;span class="kwrd"&gt;private&lt;/span&gt; TabItem
movingTabItem; &lt;span class="kwrd"&gt;private&lt;/span&gt; TabItem lastTab; &lt;span class="kwrd"&gt;private&lt;/span&gt; Point
ptStart; &lt;span class="kwrd"&gt;void&lt;/span&gt; TabItem_PreviewMouseDown(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender,
MouseEventArgs e) { var ti = e.Source &lt;span class="kwrd"&gt;as&lt;/span&gt; TabItem; &lt;span class="kwrd"&gt;if&lt;/span&gt; (ti
!= &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; e.LeftButton == MouseButtonState.Pressed)
{ var tc = ti.Parent &lt;span class="kwrd"&gt;as&lt;/span&gt; TabControl; &lt;span class="kwrd"&gt;if&lt;/span&gt; (tc
!= &lt;span class="kwrd"&gt;null&lt;/span&gt;) { tc.MouseMove += tc_MouseMove; tc.MouseLeftButtonUp
+= tc_MouseLeftButtonUp; ptStart = e.GetPosition(tc); movingTabItem = ti; } } } &lt;span class="kwrd"&gt;void&lt;/span&gt; tc_MouseMove(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender,
MouseEventArgs e) { var tc = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; TabControl; &lt;span class="kwrd"&gt;if&lt;/span&gt; (tc
== &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;return&lt;/span&gt;; Point pt = e.GetPosition(tc); &lt;span class="kwrd"&gt;if&lt;/span&gt; (isMoving
== &lt;span class="kwrd"&gt;false&lt;/span&gt;) { &lt;span class="kwrd"&gt;if&lt;/span&gt; (Math.Abs(pt.X
- ptStart.X) &amp;gt; 10) { movingTabItem.IsHitTestVisible = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
movingTabItem.RenderTransformOrigin = &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(.5, .5);
movingTabItem.RenderTransform = &lt;span class="kwrd"&gt;new&lt;/span&gt; TranslateTransform(0,
0); tc.Cursor = Cursors.Hand; Panel.SetZIndex(movingTabItem, 1); isMoving = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
tc.CaptureMouse(); } &lt;span class="kwrd"&gt;return&lt;/span&gt;; } TabItem newPos = FindTabItem(tc,
pt); &lt;span class="kwrd"&gt;if&lt;/span&gt; (newPos == &lt;span class="kwrd"&gt;null&lt;/span&gt;) tc.Cursor
= Cursors.No; &lt;span class="kwrd"&gt;else&lt;/span&gt; { lastTab = newPos; var xform = movingTabItem.RenderTransform &lt;span class="kwrd"&gt;as&lt;/span&gt; TranslateTransform; &lt;span class="kwrd"&gt;if&lt;/span&gt; (xform
!= &lt;span class="kwrd"&gt;null&lt;/span&gt;) xform.X = pt.X - ptStart.X; tc.Cursor = Cursors.Hand;
} } &lt;span class="kwrd"&gt;void&lt;/span&gt; tc_MouseLeftButtonUp(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender,
MouseButtonEventArgs e) { var tc = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; TabControl;
Debug.Assert(tc != &lt;span class="kwrd"&gt;null&lt;/span&gt;); tc.ReleaseMouseCapture(); tc.MouseMove
-= tc_MouseMove; tc.MouseLeftButtonUp -= tc_MouseLeftButtonUp; &lt;span class="kwrd"&gt;if&lt;/span&gt; (isMoving
== &lt;span class="kwrd"&gt;true&lt;/span&gt;) { isMoving = &lt;span class="kwrd"&gt;false&lt;/span&gt;; tc.Cursor
= Cursors.Arrow; movingTabItem.RenderTransform = &lt;span class="kwrd"&gt;null&lt;/span&gt;; movingTabItem.IsHitTestVisible
= &lt;span class="kwrd"&gt;true&lt;/span&gt;; Panel.SetZIndex(movingTabItem, 0); &lt;span class="kwrd"&gt;if&lt;/span&gt; (lastTab
!= &lt;span class="kwrd"&gt;null&lt;/span&gt;) { &lt;span class="kwrd"&gt;if&lt;/span&gt; (lastTab != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp;
movingTabItem != lastTab) { &lt;span class="kwrd"&gt;int&lt;/span&gt; targetIndex = tc.Items.IndexOf(lastTab);
tc.Items.Remove(movingTabItem); tc.Items.Insert(targetIndex, movingTabItem); movingTabItem.Focus();
} } } movingTabItem = lastTab = &lt;span class="kwrd"&gt;null&lt;/span&gt;; } &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; TabItem
FindTabItem(UIElement parent, Point pt) { var fe = parent.InputHitTest(pt) &lt;span class="kwrd"&gt;as&lt;/span&gt; FrameworkElement; &lt;span class="kwrd"&gt;while&lt;/span&gt; (fe
!= &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; fe.GetType() != &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(TabItem))
fe = VisualTreeHelper.GetParent(fe) &lt;span class="kwrd"&gt;as&lt;/span&gt; FrameworkElement; &lt;span class="kwrd"&gt;return&lt;/span&gt; fe &lt;span class="kwrd"&gt;as&lt;/span&gt; TabItem;
} } } &lt;/pre&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,adc227ac-2da6-4ad4-8b7e-e7d5aee32fb2.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=4e4f6f4e-ca26-48e3-b096-c8dfc282209f</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,4e4f6f4e-ca26-48e3-b096-c8dfc282209f.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=4e4f6f4e-ca26-48e3-b096-c8dfc282209f</wfw:commentRss>
      <title>Creating Extensible Applications with MAF (System.AddIn)</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,4e4f6f4e-ca26-48e3-b096-c8dfc282209f.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2008/05/06/CreatingExtensibleApplicationsWithMAFSystemAddIn.aspx</link>
      <pubDate>Tue, 06 May 2008 21:46:26 GMT</pubDate>
      <description>
&lt;!--[if gte mso 10]&gt;
&lt;style&gt;
 /* Style Definitions */
table.MsoNormalTable
	{mso-style-name:"Table Normal";
	mso-tstyle-rowband-size:0;
	mso-tstyle-colband-size:0;
	mso-style-noshow:yes;
	mso-style-parent:"";
	mso-padding-alt:0in 5.4pt 0in 5.4pt;
	mso-para-margin-top:0in;
	mso-para-margin-right:0in;
	mso-para-margin-bottom:10.0pt;
	mso-para-margin-left:0in;
	mso-pagination:widow-orphan;
	font-size:12.0pt;
	font-family:"Times New Roman";
	mso-ascii-font-family:Cambria;
	mso-ascii-theme-font:minor-latin;
	mso-hansi-font-family:Cambria;
	mso-hansi-theme-font:minor-latin;}
&lt;/style&gt;
&lt;![endif]--&gt;
&lt;!--[if gte mso 9]&gt;&lt;xml&gt;
 &lt;o:shapedefaults v:ext="edit" spidmax="2050"/&gt;
&lt;/xml&gt;&lt;![endif]--&gt;
&lt;!--[if gte mso 9]&gt;&lt;xml&gt;
 &lt;o:shapelayout v:ext="edit"&gt;
  &lt;o:idmap v:ext="edit" data="1"/&gt;
 &lt;/o:shapelayout&gt;&lt;/xml&gt;&lt;![endif]--&gt;
&lt;div class="Section1"&gt;
&lt;h1&gt;
&lt;/h1&gt;
&lt;p class="MsoNormal"&gt;
&lt;br&gt;
Last month, my colleague, &lt;a href="http://www.develop.com/us/technology/bio.aspx?id=87"&gt;Pinku
Surana&lt;/a&gt;, wrote an article about .NET AppDomains and how they can be used to provide
component isolation and make your applications more reliable.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;If
you missed it, you can read the &lt;a href="http://www.develop.com/us/technology/technology.aspx?tech=all"&gt;Developments
archives&lt;/a&gt; on Developmentor’s website.&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;This month,
I’d like to continue exploring reliability and extensibility by introducing you to
a new framework included with .NET 3.5: The Managed Add-in Framework (MAF), sometimes
referred to as System.AddIn.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Developers (and managers) have long desired a way to easily create extensible applications
that allow new features to be added without jeopardizing the stability of the existing
code base.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The .NET framework has provided the underlying
support to accomplish this from the very beginning through the reflection API and
AppDomain support Pinku examined last month.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;MAF builds
on that fundamental support to provide a higher-level service that allow you to dynamically
discover, load, secure and interact with external assemblies used to provide features
for your application.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Several common architectural requirements
are made trivial with MAF:
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpFirst" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;1)&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Isolate aspects of your code for security reasons or partial-trust scenarios.
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpMiddle" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;2)&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Allow business partners to extend your application safely without access
to the source code; Adobe Illustrator is a great example of this style of application.
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpMiddle" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;3)&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Separate volatile sections of your application out – where depending
on the customer the application needs to execute different sets of code.
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpMiddle" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;4)&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Add or change code without unloading the application – for example pay-to-play
scenarios, or where you need to update an assembly but the application must continue
to run.
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpLast" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;5)&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Develop and evolve different sections of the application in parallel
without any fear of destabilizing one based on the other.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
If any of these scenarios sound like something you could utilize in your application
then you should know about MAF!
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
At the center of the MAF-based application is the pipeline.
&lt;/p&gt;
&lt;h2&gt;The Pipeline
&lt;/h2&gt;
&lt;p class="MsoNormal"&gt;
Communication between add-ins and the host application is strictly regulated by the
pipeline.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The pipeline is dynamically created by MAF through
a set of loosely-coupled components which are used to version, marshal and transform
the data as it passes back and forth between the host and each loaded add-in.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;span style=""&gt;
&lt;!--[if gte vml 1]&gt;&lt;v:shapetype
 id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"
 path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"&gt;
 &lt;v:stroke joinstyle="miter"/&gt;
 &lt;v:formulas&gt;
  &lt;v:f eqn="if lineDrawn pixelLineWidth 0"/&gt;
  &lt;v:f eqn="sum @0 1 0"/&gt;
  &lt;v:f eqn="sum 0 0 @1"/&gt;
  &lt;v:f eqn="prod @2 1 2"/&gt;
  &lt;v:f eqn="prod @3 21600 pixelWidth"/&gt;
  &lt;v:f eqn="prod @3 21600 pixelHeight"/&gt;
  &lt;v:f eqn="sum @0 0 1"/&gt;
  &lt;v:f eqn="prod @6 1 2"/&gt;
  &lt;v:f eqn="prod @7 21600 pixelWidth"/&gt;
  &lt;v:f eqn="sum @8 21600 0"/&gt;
  &lt;v:f eqn="prod @7 21600 pixelHeight"/&gt;
  &lt;v:f eqn="sum @10 21600 0"/&gt;
 &lt;/v:formulas&gt;
 &lt;v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/&gt;
 &lt;o:lock v:ext="edit" aspectratio="t"/&gt;
&lt;/v:shapetype&gt;&lt;v:shape id="O_x0020_2" o:spid="_x0000_i1028" type="#_x0000_t75"
 style='width:6in;height:81pt;visibility:visible' o:gfxdata="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

"&gt;
 &lt;v:imagedata src="Creating%20Extensible%20Applications%20with%20MAF_files/image001.png"
  o:title="" croptop="-786f" cropbottom="-414f"/&gt;
 &lt;o:lock v:ext="edit" aspectratio="f"/&gt;
&lt;/v:shape&gt;&lt;![endif]--&gt;
&lt;!--[if !vml]--&gt;&lt;img src="http://www.julmar.com/blog/mark/content/binary/image001.png" alt="image001.png" border="0" height="102" width="557"&gt;
&lt;br&gt;
&lt;!--[endif]--&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Each section of the pipeline is contained in a separate assembly, loaded as necessary
to manage the specific add-in.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;MAF discovers each component
and then loads them on request using reflection.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
For reliability, MAF allows optional isolation boundaries to be created between the
add-in and host – everything to the left of the contract is loaded into the main (host)
AppDomain and everything to the right loaded into a newly created AppDomain which
has its own security permission set.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The isolation can
also be done through cross-process calls if true process-level isolation is necessary.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Under
the covers, the system uses traditional remoting calls to do the work of marshaling
calls back and forth.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Breaking down the pipeline, there are three main parts starting in the center with
the contract.
&lt;/p&gt;
&lt;h2&gt;Contract
&lt;/h2&gt;
&lt;p class="MsoNormal"&gt;
As you might expect, MAF is based on interface contracts.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Interfaces
allow classes in an application to be loosely coupled, reducing the risk when changes
are made between dependent sections of the code.&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;The
interface contract is shared between the host and add-in and once it has been established,
it should never be changed.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Consider the simple example of a translator program.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The
host will expect to load one or more translator add-ins that will do some work on
an inbound string and return the results.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;To accomplish
this, I might create an &lt;b style=""&gt;ITranslator&lt;/b&gt; interface that looks like:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;[AddInContract]&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;public interface ITranslator
: IContract&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;string
Translate(string input);&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
&lt;br&gt;
}&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;br&gt;
Notice that the interface derives from &lt;b style=""&gt;IContract&lt;/b&gt;. &lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;This
is a requirement for add-in contracts and is what will be used to provide marshalling
support when the pipeline is established.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;We also need
to decorate the interface with the &lt;b style=""&gt;[AddInContract]&lt;/b&gt; attribute – this
is the marker used by MAF to identify the contract when it is dynamically constructing
the pipeline.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Both of these types come from the &lt;b style=""&gt;System.AddIn.Pipeline&lt;/b&gt; namespace
in &lt;b style=""&gt;System.AddIn.Contract.dll&lt;/b&gt;.
&lt;/p&gt;
&lt;h2&gt;Views
&lt;/h2&gt;
&lt;p class="MsoNormal"&gt;
Moving to the edges, we find the views.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;This is the code
that the add-in and host directly interact with.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;It represents
a host or add-in specific “view” of the contract and, like the contract, is contained
in a separate assembly.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Both of the view classes will echo the structure of the contract, but not actually
be dependent upon the contract. &lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;For example, our host
side view might look like this:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;public abstract class
TranslatorHostView&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
abstract string Translate(string input);&lt;br&gt;
}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;br&gt;
The view is commonly exposed as an abstract class to make it look more natural when
used by the host, but an interface will work just as well.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The
host uses the view directly when communicating with any add-in based on the contract.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
On the add-in side, we have an almost identical class – except we decorate this type
with the &lt;b style=""&gt;[AddInBase]&lt;/b&gt; attribute so MAF knows which side of the pipeline
this view is for (the add-in).&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;This is located in
the &lt;b style=""&gt;System.AddIn.Pipeline&lt;/b&gt; namespace in the &lt;b style=""&gt;System.AddIn&lt;/b&gt; assembly.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
When we create each add-in, the implementation will use this type as the base class.
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;[AddInBase]&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;public abstract class
TranslatorAddInView&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
abstract string Translate(stringinp);&lt;br&gt;
}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;h2&gt;Adapters
&lt;/h2&gt;
&lt;p class="MsoNormal"&gt;
The last piece of the pipeline is the adapters.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The adapters
play a very special role in the pipeline – they are the glue that binds the contract
to the view: implementing lifetime management and any necessary data conversion between
the two ends.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
It may seem redundant to have this class, but by separating the view from the contract
we introduce version tolerance into our architecture – the host can version independently
of the add-in and vice-versa.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Depending on the situation,
the adapters can be as simple as a pass-through class, or can provide higher-level
services to allow non-serializable types to be marshaled across the isolation boundaries.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
On the host side, the adapter will implement the view (remember it is either an interface
or abstract class).&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;It will be passed a reference to the
contract in the constructor and it is responsible for connecting the two together.
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;[HostAdapter]&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;public class TranslatorHostViewToContract
: &lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;TranslatorHostView&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ITranslator
_contract;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ContractHandle
_lifetime;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
TranslatorHostViewToContract(&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ITranslator
contract)&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;_contract
= contract;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_lifetime
= new ContractHandle(contract);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
override string Translate(string inp)&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;return
_contract.Translate(inp);&lt;br&gt;
&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;br&gt;
In this simple example, the code caches off the contract interface.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;This
is a remoting proxy to the actual loaded add-in.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The adapter
then implements the &lt;b style=""&gt;Translate&lt;/b&gt; method and passes it forward to the
contract for implementation.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;If we had non-serializable
types, then the adapter would be responsible for converting them into something that &lt;i style=""&gt;was&lt;/i&gt; serializable.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
It also provides some lifetime management for the contract.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Because
the contract is a remoting proxy and is likely running in a separate AppDomain (or
even process) we have to be concerned with how long it lives.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;MAF
provides all the support for this through the &lt;b style=""&gt;ContractHandle&lt;/b&gt; class.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Most
of the time, all you will need to do is store a &lt;b style=""&gt;ContractHandle&lt;/b&gt; in
your host adapter and then pass it the inbound contract to wrap in your constructor.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Finally, in order for MAF to identify this class, it must be decorated with the &lt;b style=""&gt;[HostAdapter]&lt;/b&gt; attribute
from the &lt;b style=""&gt;System.AddIn.Pipeline&lt;/b&gt; namespace out of the &lt;b style=""&gt;System.AddIn.dll&lt;/b&gt;. 
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
The add-in side looks very similar, but does the opposite: it makes the add-in view
look like the contract.
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;[AddInAdapter]&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;public class TranslatorAddInViewToContract
: 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ContractBase,
ITranslator&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;TranslatorAddInView
_view;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
TranslatorAddInViewToContract(&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;TranslatorView
view)&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;_view
= view;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;i&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
string Translate(string inp)&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;{&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return
_view.Translate(inp);&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;} 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;
&lt;br&gt;
MAF passes the view to the constructor and the class caches the reference off in a
field.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;It implements the contract (&lt;b style=""&gt;ITranslator&lt;/b&gt;)
and &lt;b style=""&gt;ContractBase&lt;/b&gt; which provides the implementation of the &lt;b style=""&gt;IContract&lt;/b&gt; interface
for us (remember this was a required interface on our contract).&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;As
the host makes calls to the contract interface, this class will translate those calls
to the add-in view, which as you will see is the implementation provided by the add-in
itself.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Note how the &lt;b style=""&gt;[AddInAdapter]&lt;/b&gt; attribute
is used to mark this class so MAF can discover it.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
If it seems like all the above is a lot of repetitious, boilerplate code well.. you’re
right!&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;To make it easier on the developer to create the
pipeline components, the MAF team has created a &lt;a href="http://www.codeplex.com/clraddins"&gt;pipeline
builder&lt;/a&gt; available at http://www.codeplex.com/clraddins.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;It
takes the contract assembly and then generates the views and adapters from it: 
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;span style=""&gt;
&lt;!--[if gte vml 1]&gt;&lt;v:shape
 id="P_x0020_3" o:spid="_x0000_i1027" type="#_x0000_t75" alt="image1.jpg"
 style='width:6in;height:284pt;visibility:visible;mso-wrap-style:square'&gt;
 &lt;v:imagedata src="Creating%20Extensible%20Applications%20with%20MAF_files/image003.jpg"
  o:title="image1.jpg"/&gt;
 &lt;v:textbox style='mso-rotate-with-shape:t'/&gt;
&lt;/v:shape&gt;&lt;![endif]--&gt;
&lt;!--[if !vml]--&gt;&lt;img src="http://www.julmar.com/blog/mark/content/binary/image003.jpg" alt="image003.jpg" border="0" height="623" width="947"&gt;
&lt;br&gt;
&lt;!--[endif]--&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;h2&gt;Creating an add-in
&lt;/h2&gt;
&lt;p class="MsoNormal"&gt;
Once the pipeline pieces are built you can create add-ins.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Each
add-in provides an implementation of the abstract add-in view.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;For
example, we might provide a BabelFish add-in for universalized translation:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;[AddIn(“BabelFishTranslator”, 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Description=“Universal
translator”, 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Version=“1.0.0.0”,
Publisher=“Zaphod Beeblebrox”]&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;public class BabelFishAddIn
: TranslatorAddInView&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
string Translate(string input) 
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;...&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;br&gt;
The add-in implements the &lt;b style=""&gt;AddInView&lt;/b&gt;, providing a concrete implementation
of the &lt;b style=""&gt;Translate&lt;/b&gt; method.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;It is decorated
with the &lt;b style=""&gt;[AddIn]&lt;/b&gt; attribute that allows it to provide a name, version,
description and other data the host can use to decide whether it is a useful translator.
&lt;/p&gt;
&lt;h2&gt;Putting the pieces together – the directory structure
&lt;/h2&gt;
&lt;p class="MsoNormal"&gt;
To properly identify each of the components necessary, MAF enforces a particular directory
structure you need to follow for deployment.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Each piece
is stored in a sub-directory off the root of the pipeline directory (this is typically
the APPBASE where the host executable is stored).&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;span style=""&gt;
&lt;!--[if gte vml 1]&gt;&lt;v:shape
 id="O_x0020_4" o:spid="_x0000_i1026" type="#_x0000_t75" style='width:6in;
 height:182pt;visibility:visible' o:gfxdata="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

"&gt;
 &lt;v:imagedata src="Creating%20Extensible%20Applications%20with%20MAF_files/image005.png"
  o:title="" croptop="-1068f" cropbottom="-276f" cropleft="-247f" cropright="-7858f"/&gt;
 &lt;o:lock v:ext="edit" aspectratio="f"/&gt;
&lt;/v:shape&gt;&lt;![endif]--&gt;
&lt;!--[if !vml]--&gt;&lt;img src="http://www.julmar.com/blog/mark/content/binary/image006.png" alt="image006.png" border="0" height="184" width="434"&gt;
&lt;br&gt;
&lt;!--[endif]--&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;!--[if gte vml 1]&gt;&lt;v:shape id="O_x0020_5" o:spid="_x0000_s1026"
 type="#_x0000_t75" style='position:absolute;margin-left:251.55pt;margin-top:36.6pt;
 width:196.3pt;height:156.5pt;z-index:1;visibility:visible;
 mso-wrap-distance-left:9pt;mso-wrap-distance-top:.48pt;
 mso-wrap-distance-right:9pt;mso-wrap-distance-bottom:1.04pt;
 mso-position-horizontal:absolute;mso-position-horizontal-relative:text;
 mso-position-vertical:absolute;mso-position-vertical-relative:text'
 wrapcoords="-221 0 -221 21327 21186 21327 21628 16132 21628 15311 21186 0 -221 0"
 o:gfxdata="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

CwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy

MjIy/8AAEQgAvgDEAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//E

ALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJ

ChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeI

iYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq

8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQH

BQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJico

KSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZ

mqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/a

AAwDAQACEQMRAD8A9isZ0t9DsXfOPIjHH+6Kf/atv/t/lVMf8i3Y/wDXKP8A9BrjtUW7n1mWG2F2

ZBaxmJorjZHE5ZxuZdw3DgcYbp0rRRTZEpNHe/2rb/7f5Uf2rb/7f5VxK6lfPESDbq0l41tExjYh

Apb5m+YZyFxgY5NMGq30zW0MbWscjicPJIjFSYmAyo3Dg89+PU45ORC52dz/AGrb/wC3+VH9q2/+

3+VcKutX9zLYpa2YbzII55gccKxwcEsuMYJzhu3Apkl5qVzcWjpcQRR/2hJCFEbEsqhx8x3DP3em

OuD7U+RBzv8Ar7zvf7Vt/R/yo/tW39H/ACrgpNWvlRIbK2EtxJPcAA/MNqORj5nXrkd+OwrTiu7g

6s1vOqxRmPdEuwkv03HeDgYJxjHoc0KCYc7Oq/tW39H/ACo/tW3/ANv8qxKKORBzs2/7Vt/9v8qP

7Vt/R/yrEoo5EHOzb/tW29H/ACo/tW29H/KsSijkQc7Nv+1bb0f8qP7VtvR/yrEoo5EHOzb/ALVt

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

BQYAAAAABgAGAH0BAABfLAAAAAA=

"&gt;
 &lt;v:imagedata src="Creating%20Extensible%20Applications%20with%20MAF_files/image007.png"
  o:title=""/&gt;
 &lt;o:lock v:ext="edit" aspectratio="f"/&gt;
 &lt;w:wrap type="tight"/&gt;
&lt;/v:shape&gt;&lt;![endif]--&gt;
&lt;!--[if !vml]--&gt;
&lt;!--[endif]--&gt;The directory names are required, but not case sensitive – each directory
holding a single piece of the pipeline that MAF will load dynamically when it is loading
the add-in.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The host-side view is always located in the
same directory as the host executable itself so it does not need a dedicated directory.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;When
creating your Visual Studio project, it is important to set the output directories
appropriately so that you create the above directory structure.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;In
addition, all references between the components should be marked as CopyLocal = “false”
in Visual Studio to ensure a local copy of the assembly isn’t placed into the sub-directory:&amp;nbsp; &lt;span style=""&gt;
&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;span style=""&gt;&lt;img src="http://www.julmar.com/blog/mark/content/binary/image008.png" alt="image008.png" border="0" height="159" width="198"&gt;
&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;h2&gt;Discovering and loading add-ins from the host
&lt;/h2&gt;
&lt;p class="MsoNormal"&gt;
The last piece of the puzzle is the actual loading of add-ins from the host.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;This
is done in three basic steps:
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpFirst" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;1.&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Identify and catalog the add-ins
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpMiddle" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;2.&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Retrieve the list of specific add-ins based on view or name
&lt;/p&gt;
&lt;p class="MsoListParagraphCxSpLast" style="text-indent: -0.25in;"&gt;
&lt;!--[if !supportLists]--&gt;&lt;span style=""&gt;&lt;span style=""&gt;3.&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;!--[endif]--&gt;Activate and use the add-in
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
The first step is to identify the available add-ins for the host.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;This
is done through the &lt;b style=""&gt;System.AddIn.AddInStore&lt;/b&gt; class:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;string[] errorList
= AddInStore.Rebuild(&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;PipelineStoreLocation.ApplicationBase);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Calling &lt;b style=""&gt;Rebuild&lt;/b&gt; forces MAF to walk the directory structure and create
the pipeline database.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;It stores this information in the
pipeline root directory and returns a list of errors, if any occur.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;The
most common errors are missing pipeline components – where MAF is unable to locate
some required portion of the pipeline such as a View or Adapter.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Next, the host will retrieve a list of add-ins based on the host view through the &lt;b style=""&gt;FindAddIns&lt;/b&gt; method
– these will be the add-ins conforming to a specific contract (whatever the view/adapter
is bound to):
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;Collection&amp;lt;AddInToken&amp;gt;
addinTokens = AddInStore.FindAddIns(&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;typeof(TranslatorHostView),&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;PipelineStoreLocation.ApplicationBase);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
The first parameter is the host view type – so MAF knows what add-ins we are looking
for, the second is the pipeline root directory, which is the same directory passed
to the &lt;b style=""&gt;Rebuild&lt;/b&gt; method and indicates where the pipeline database is
stored.
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
The returning collection represents a series of &lt;i style=""&gt;tokens &lt;/i&gt;that are used
to identify and control the add-ins.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;This is how the host
can examine, activate and unload the add-in.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;To activate
a specific add-in, you can take the token and call &lt;b style=""&gt;Activate&lt;/b&gt;:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;Collection&amp;lt;AddInToken&amp;gt;
addinTokens;&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;...&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;foreach (AddInToken token in
addinTokens)&lt;br&gt;
{&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;TranslatorHostView
view =&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;token.Activate&amp;lt;TranslatorHostView&amp;gt;(&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;AddInSecurityLevel.Internet);&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;string
hello = view.Translate(“Bonjour”);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;...&lt;br&gt;
}&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
The &lt;b style=""&gt;Activate&lt;/b&gt; call loads all the required components, instantiates
the add-in type and returns the host view used to interact with the add-in.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Calls
made to this object will be marshaled back and forth to the add-in using the pipeline.
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
Notice that the parameter passed to &lt;b style=""&gt;Activate&lt;/b&gt; indicates the security
level required.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;There are several overrides that allow
you to dictate exactly how the add-in is loaded.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;You can
load the add-in into a specific AppDomain – the current one for best performance:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;token.Activate&amp;lt;TranslatorHostView&amp;gt;(AppDomain.CurrentDomain)&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
You can specify a specific permission set to restrict the things the add-in can do
on your behalf:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;PermissionSet pset = ...;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;token.Activate&amp;lt;TranslatorHostView&amp;gt;(pset);&lt;/span&gt;&lt;/b&gt;&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;br&gt;
Or you can specify a known permission set based on the CAS zones:
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;img src="http://www.julmar.com/blog/mark/content/binary/image010.png" alt="image010.png" border="0" height="102" width="244"&gt;
&lt;br&gt;
&lt;span style=""&gt;
&lt;!--[if gte vml 1]&gt;&lt;v:shape id="P_x0020_11" o:spid="_x0000_i1025"
 type="#_x0000_t75" alt="image1.JPG" style='width:242pt;height:100pt;
 visibility:visible;mso-wrap-style:square'&gt;
 &lt;v:imagedata src="Creating%20Extensible%20Applications%20with%20MAF_files/image009.png"
  o:title="image1.JPG" chromakey="#f4f4f4"/&gt;
 &lt;v:textbox style='mso-rotate-with-shape:t'/&gt;
&lt;/v:shape&gt;&lt;![endif]--&gt;
&lt;!--[if !vml]--&gt;
&lt;!--[endif]--&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
Once the add-in is activated, the host can call it just like any other object – but
never forget that you are likely crossing an isolation barrier!&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Make
sure to design your contracts so that you minimize the number of calls between the
host and add-ins to ensure your performance doesn’t suffer.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
When you are finished with the add-in, you can tell MAF to unload it through the &lt;b style=""&gt;AddInController&lt;/b&gt; associated
with the view:
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;AddInController ctrl
= &lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;AddInController.GetAddInController(view);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNoSpacing"&gt;
&lt;b style=""&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;"&gt;ctrl.Shutdown();&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
&lt;br&gt;
This will unload the add-in side pipeline and then destroy the containing AppDomain
so you release the resources associated with it.
&lt;/p&gt;
&lt;p class="MsoNormal"&gt;
There are many other capabilities MAF provides such as versioning, passing collections
and WPF visuals, passing non-serializable types, etc.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;You
can get a pretty decent overview of the features from &lt;a href="http://msdn.microsoft.com/en-us/library/bb384241.aspx"&gt;MSDN&lt;/a&gt; and
the MAF team has a blog at &lt;a href="http://blogs.msdn.com/clraddins/"&gt;&lt;span style="font-family: &amp;quot;Lucida Grande&amp;quot;;"&gt;http://blogs.msdn.com/clraddins/&lt;/span&gt;&lt;/a&gt; that
has some great, practical information on using this new framework.&lt;span style="font-family: &amp;quot;Lucida Grande&amp;quot;; color: black;"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,4e4f6f4e-ca26-48e3-b096-c8dfc282209f.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>Real World</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=ad823418-2717-4002-8d26-bd634139edec</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,ad823418-2717-4002-8d26-bd634139edec.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,ad823418-2717-4002-8d26-bd634139edec.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=ad823418-2717-4002-8d26-bd634139edec</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Thanks to all those who attended the GNET
in Tampa last week. We had a blast with all of you and wish you the best of luck going
back and using all the cool tricks and technologies we showed you! As promised, here
are the demos we build during the week - <a href="http://www.julmar.com/DMStuff/gnet-demos.zip">Demos</a>.
Enjoy! 
</body>
      <title>Guerrilla .NET Tampa samples</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,ad823418-2717-4002-8d26-bd634139edec.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2007/11/19/GuerrillaNETTampaSamples.aspx</link>
      <pubDate>Mon, 19 Nov 2007 23:01:13 GMT</pubDate>
      <description>Thanks to all those who attended the GNET in Tampa last week.  We had a blast with all of you and wish you the best of luck going back and using all the cool tricks and technologies we showed you!

As promised, here are the demos we build during the week - &lt;a href="http://www.julmar.com/DMStuff/gnet-demos.zip"&gt;Demos&lt;/a&gt;.

Enjoy!
</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,ad823418-2717-4002-8d26-bd634139edec.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=61b8e49c-f652-4897-a4cf-087b3ac6bb2e</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,61b8e49c-f652-4897-a4cf-087b3ac6bb2e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,61b8e49c-f652-4897-a4cf-087b3ac6bb2e.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=61b8e49c-f652-4897-a4cf-087b3ac6bb2e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Sales of the TSP++ products have steadily fallen over the past 5 years, so much so
that I decided two years ago to release the 2.x product into the open-source community,
and now I am doing the same for the server edition. 
</p>
        <p>
The download is available <a href="http://www.julmar.com/_Media/tspv3053.exe">here</a> and
requires a key to install it - use <span style="font-family: 'Lucida Grande'; font-size: 14px;"></span></p>
        <p>
          <span style="font-family: 'Lucida Grande'; font-size: 14px;">J35M-3KXo-q60T</span>
        </p>
        <p>
          <span style="font-family: 'Lucida Grande'; font-size: 14px;">
            <span style="font-family: Times; font-size: 16px;">
            </span>
          </span>
        </p>
        <p style="font-family: Verdana; font-size: 12px;">
which will let you install the full product. Documentation and samples are all part
of the image so have fun!
</p>
        <p>
        </p>
      </body>
      <title>TSP++ 3.0 is now free!</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,61b8e49c-f652-4897-a4cf-087b3ac6bb2e.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2007/07/13/TSP30IsNowFree.aspx</link>
      <pubDate>Fri, 13 Jul 2007 21:46:33 GMT</pubDate>
      <description>&lt;p&gt;
Sales of the TSP++ products have steadily fallen over the past 5 years, so much so
that I decided two years ago to release the 2.x product into the open-source community,
and now I am doing the same for the server edition. 
&lt;/p&gt;
&lt;p&gt;
The download is available &lt;a href="http://www.julmar.com/_Media/tspv3053.exe"&gt;here&lt;/a&gt; and
requires a key to install it - use &lt;span style="font-family: 'Lucida Grande'; font-size: 14px;"&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family: 'Lucida Grande'; font-size: 14px;"&gt;J35M-3KXo-q60T&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family: 'Lucida Grande'; font-size: 14px;"&gt;&lt;span style="font-family: Times; font-size: 16px;"&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="font-family: Verdana; font-size: 12px;"&gt;
which will let you install the full product. Documentation and samples are all part
of the image so have fun!
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,61b8e49c-f652-4897-a4cf-087b3ac6bb2e.aspx</comments>
      <category>Code</category>
      <category>Tapi</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=b862bda0-ca95-42b9-b557-0f16f15628d6</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,b862bda0-ca95-42b9-b557-0f16f15628d6.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,b862bda0-ca95-42b9-b557-0f16f15628d6.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=b862bda0-ca95-42b9-b557-0f16f15628d6</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
About a year ago, I blogged on using the .NET 2.0 facility <b>SynchronizationContext</b> to
create thread-aware components which could be hosted and would "do the right thing"
for callbacks. Here's the <a href="http://www.julmar.com/blog/mark/PermaLink,guid,78805871-cb7b-4ea4-9be8-a8a1d61a15d8.aspx">Link</a> to
that post. 
</p>
        <p>
Recently, I got an email from a reader who wanted to use that paradigm, but wanted
to be able to suspend the operation for some period of time and then resume it later
on. He asked if there was an easy way to modify the sample I presented, and it turns
out that there is. 
</p>
        <p>
It essentially involves three steps: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <b>1.</b> In the AsyncStateData structure, add a <b>ManualResetEvent</b> object. This
will be used to trigger the pause/resume behavior. It must be initially set as signaled. 
<br /><b><br />
2.</b> In the actual asynchronous operation loop, add the event into the loop condition
by calling <b>event.WaitOne()</b>. Make sure you have released any locks and the code
can safely be halted at that point in the logic otherwise you may create deadlock
scenarios and other difficult debugging issues. 
<br /><b><br />
3.</b> Add a <b>Pause</b> and <b>Continue</b> method into the class which signals
and resets the event. 
</p>
        </blockquote> Modifying my previous code example, here's what I come up with: 
<h4>Step 1: Add the event to AsyncStateDate
</h4><div class="csharpcode"><pre><span class="lnum"> 1: </span><span class="kwrd">class</span> AsyncStateData</pre><pre><span class="lnum"> 2: </span>{</pre><pre><span class="lnum"> 3: </span><span class="kwrd">private</span> ManualResetEvent
pauseEvent = <span class="kwrd">new</span> ManualResetEvent(<span class="kwrd">true</span>);</pre><pre><span class="lnum"> 4: </span> ...</pre><pre><span class="lnum"> 5: </span>}</pre></div><h4>Step 2: Add event into the loop at a safe point
</h4><div class="csharpcode"><pre><span class="lnum"> 1: </span><span class="kwrd">public
partial</span><span class="kwrd">class</span> Calculator</pre><pre><span class="lnum"> 2: </span>{</pre><pre><span class="lnum"> 3: </span><span class="kwrd">private</span><span class="kwrd">void</span> InternalCalculatePi(<span class="kwrd">int</span> digits,
AsyncStateData</pre><pre><span class="lnum"> 4: </span>asyncData)</pre><pre><span class="lnum"> 5: </span> {</pre><pre><span class="lnum"> 6: </span><span class="kwrd">int</span> completedDigits
= 0;</pre><pre><span class="lnum"> 7: </span><span class="kwrd">for</span> (; !asyncData.canceled
&amp;&amp; pauseEvent.WaitOne(-1, <span class="kwrd">true</span>) &amp;&amp;</pre><pre><span class="lnum"> 8: </span>completedDigits
&lt; digits; completedDigits++)</pre><pre><span class="lnum"> 9: </span> { ... }</pre><pre><span class="lnum"> 10: </span> }</pre><pre><span class="lnum"> 11: </span> </pre><pre><span class="lnum"> 12: </span>...</pre><pre><span class="lnum"> 13: </span>}</pre></div><h4>Step 3: Add a Pause and Continue API
</h4><!-- code formatted by http://manoli.net/csharpformat/ --><div class="csharpcode"><pre><span class="lnum"> 1: </span><span class="kwrd">public
partial</span><span class="kwrd">class</span> Calculator</pre><pre><span class="lnum"> 2: </span>{</pre><pre><span class="lnum"> 3: </span><span class="kwrd">public</span><span class="kwrd">void</span> PauseAsync(<span class="kwrd">object</span> asyncTask)</pre><pre><span class="lnum"> 4: </span> {</pre><pre><span class="lnum"> 5: </span> AsyncStateData
asyncData = asyncTask <span class="kwrd">as</span> AsyncStateData;</pre><pre><span class="lnum"> 6: </span><span class="kwrd">if</span> (asyncData
!= <span class="kwrd">null</span> &amp;&amp; asyncData.running == <span class="kwrd">true</span>)</pre><pre><span class="lnum"> 7: </span> asyncData.pauseEvent.Reset();</pre><pre><span class="lnum"> 8: </span> }</pre><pre><span class="lnum"> 9: </span> </pre><pre><span class="lnum"> 10: </span><span class="kwrd">public</span><span class="kwrd">void</span> ContinueAsync(<span class="kwrd">object</span> asyncTask)</pre><pre><span class="lnum"> 11: </span> {</pre><pre><span class="lnum"> 12: </span> AsyncStateData
asyncData = asyncTask <span class="kwrd">as</span> AsyncStateData;</pre><pre><span class="lnum"> 13: </span><span class="kwrd">if</span> (asyncData
!= <span class="kwrd">null</span> &amp;&amp; asyncData.running == <span class="kwrd">true</span>)</pre><pre><span class="lnum"> 14: </span> asyncData.pauseEvent.Set();</pre><pre><span class="lnum"> 15: </span> }</pre><pre><span class="lnum"> 16: </span>...</pre><pre><span class="lnum"> 17: </span>}</pre></div><br /><br />
There are certainly other ways to do this as well, for example, create a dedicated
Thread object instead of using an Async delegate and then call <b>Suspend</b> on the
thread (and <b>Resume</b> to continue). That can be dangerous if you take locks while
running your async operation so the <b>ManualResetEvent</b> is probably a better solution
from that perspective (since you are blocking in a known location vs. just suspending
the thread arbitrarily and potentially holding onto shared resources. 
</body>
      <title>Adding Pause/Resume into SynchronizationContext based components</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,b862bda0-ca95-42b9-b557-0f16f15628d6.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2007/01/17/AddingPauseResumeIntoSynchronizationContextBasedComponents.aspx</link>
      <pubDate>Wed, 17 Jan 2007 16:11:04 GMT</pubDate>
      <description>&lt;p&gt;
&lt;style type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
About a year ago, I blogged on using the .NET 2.0 facility &lt;b&gt;SynchronizationContext&lt;/b&gt; to
create thread-aware components which could be hosted and would "do the right thing"
for callbacks. Here's the &lt;a href="http://www.julmar.com/blog/mark/PermaLink,guid,78805871-cb7b-4ea4-9be8-a8a1d61a15d8.aspx"&gt;Link&lt;/a&gt; to
that post. 
&lt;/p&gt;
&lt;p&gt;
Recently, I got an email from a reader who wanted to use that paradigm, but wanted
to be able to suspend the operation for some period of time and then resume it later
on. He asked if there was an easy way to modify the sample I presented, and it turns
out that there is. 
&lt;/p&gt;
&lt;p&gt;
It essentially involves three steps: 
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;b&gt;1.&lt;/b&gt; In the AsyncStateData structure, add a &lt;b&gt;ManualResetEvent&lt;/b&gt; object. This
will be used to trigger the pause/resume behavior. It must be initially set as signaled. 
&lt;br&gt;
&lt;b&gt;
&lt;br&gt;
2.&lt;/b&gt; In the actual asynchronous operation loop, add the event into the loop condition
by calling &lt;b&gt;event.WaitOne()&lt;/b&gt;. Make sure you have released any locks and the code
can safely be halted at that point in the logic otherwise you may create deadlock
scenarios and other difficult debugging issues. 
&lt;br&gt;
&lt;b&gt;
&lt;br&gt;
3.&lt;/b&gt; Add a &lt;b&gt;Pause&lt;/b&gt; and &lt;b&gt;Continue&lt;/b&gt; method into the class which signals
and resets the event. 
&lt;/p&gt;
&lt;/blockquote&gt; Modifying my previous code example, here's what I come up with: 
&lt;h4&gt;Step 1: Add the event to AsyncStateDate
&lt;/h4&gt;
&lt;div class=csharpcode&gt;&lt;pre&gt;&lt;span class=lnum&gt; 1: &lt;/span&gt;&lt;span class=kwrd&gt;class&lt;/span&gt; AsyncStateData&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 2: &lt;/span&gt;{&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 3: &lt;/span&gt; &lt;span class=kwrd&gt;private&lt;/span&gt; ManualResetEvent
pauseEvent = &lt;span class=kwrd&gt;new&lt;/span&gt; ManualResetEvent(&lt;span class=kwrd&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 4: &lt;/span&gt; ...&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 5: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;h4&gt;Step 2: Add event into the loop at a safe point
&lt;/h4&gt;
&lt;div class=csharpcode&gt;&lt;pre&gt;&lt;span class=lnum&gt; 1: &lt;/span&gt;&lt;span class=kwrd&gt;public partial&lt;/span&gt; &lt;span class=kwrd&gt;class&lt;/span&gt; Calculator&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 2: &lt;/span&gt;{&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 3: &lt;/span&gt; &lt;span class=kwrd&gt;private&lt;/span&gt; &lt;span class=kwrd&gt;void&lt;/span&gt; InternalCalculatePi(&lt;span class=kwrd&gt;int&lt;/span&gt; digits,
AsyncStateData&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 4: &lt;/span&gt;asyncData)&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 5: &lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 6: &lt;/span&gt; &lt;span class=kwrd&gt;int&lt;/span&gt; completedDigits
= 0;&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 7: &lt;/span&gt; &lt;span class=kwrd&gt;for&lt;/span&gt; (; !asyncData.canceled
&amp;amp;&amp;amp; pauseEvent.WaitOne(-1, &lt;span class=kwrd&gt;true&lt;/span&gt;) &amp;amp;&amp;amp;&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 8: &lt;/span&gt;completedDigits
&amp;lt; digits; completedDigits++)&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 9: &lt;/span&gt; { ... }&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 10: &lt;/span&gt; }&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 11: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 12: &lt;/span&gt;...&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 13: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;h4&gt;Step 3: Add a Pause and Continue API
&lt;/h4&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;div class=csharpcode&gt;&lt;pre&gt;&lt;span class=lnum&gt; 1: &lt;/span&gt;&lt;span class=kwrd&gt;public partial&lt;/span&gt; &lt;span class=kwrd&gt;class&lt;/span&gt; Calculator&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 2: &lt;/span&gt;{&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 3: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;void&lt;/span&gt; PauseAsync(&lt;span class=kwrd&gt;object&lt;/span&gt; asyncTask)&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 4: &lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 5: &lt;/span&gt; AsyncStateData
asyncData = asyncTask &lt;span class=kwrd&gt;as&lt;/span&gt; AsyncStateData;&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 6: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (asyncData
!= &lt;span class=kwrd&gt;null&lt;/span&gt; &amp;amp;&amp;amp; asyncData.running == &lt;span class=kwrd&gt;true&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 7: &lt;/span&gt; asyncData.pauseEvent.Reset();&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 8: &lt;/span&gt; }&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 9: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 10: &lt;/span&gt; &lt;span class=kwrd&gt;public&lt;/span&gt; &lt;span class=kwrd&gt;void&lt;/span&gt; ContinueAsync(&lt;span class=kwrd&gt;object&lt;/span&gt; asyncTask)&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 11: &lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 12: &lt;/span&gt; AsyncStateData
asyncData = asyncTask &lt;span class=kwrd&gt;as&lt;/span&gt; AsyncStateData;&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 13: &lt;/span&gt; &lt;span class=kwrd&gt;if&lt;/span&gt; (asyncData
!= &lt;span class=kwrd&gt;null&lt;/span&gt; &amp;amp;&amp;amp; asyncData.running == &lt;span class=kwrd&gt;true&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 14: &lt;/span&gt; asyncData.pauseEvent.Set();&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 15: &lt;/span&gt; }&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 16: &lt;/span&gt;...&lt;/pre&gt;&lt;pre&gt;&lt;span class=lnum&gt; 17: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
There are certainly other ways to do this as well, for example, create a dedicated
Thread object instead of using an Async delegate and then call &lt;b&gt;Suspend&lt;/b&gt; on the
thread (and &lt;b&gt;Resume&lt;/b&gt; to continue). That can be dangerous if you take locks while
running your async operation so the &lt;b&gt;ManualResetEvent&lt;/b&gt; is probably a better solution from that perspective (since you are blocking in a known location vs. just suspending the thread arbitrarily and potentially holding onto shared resources. </description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,b862bda0-ca95-42b9-b557-0f16f15628d6.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>Real World</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=5716861f-5560-40c7-b700-483e0cd80116</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,5716861f-5560-40c7-b700-483e0cd80116.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=5716861f-5560-40c7-b700-483e0cd80116</wfw:commentRss>
      <title>WPF Data Providers</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,5716861f-5560-40c7-b700-483e0cd80116.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2007/01/17/WPFDataProviders.aspx</link>
      <pubDate>Wed, 17 Jan 2007 10:57:58 GMT</pubDate>
      <description>&lt;p&gt;
One of the nifty new features of the WPF platform is the pluggable data providers.&amp;nbsp;
It ships with two out of the box:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;ObjectDataProvider:&lt;/strong&gt;&amp;nbsp;allows you to execute binding expressions
against an object and it's methods&lt;br&gt;
&lt;strong&gt;XmlDataProvider:&lt;/strong&gt; loads an XML data source and makes it available
as a binding source
&lt;/p&gt;
&lt;p&gt;
Both of these derive from the abstract class&amp;nbsp;&lt;strong&gt;System.Data.DataSourceProvider&lt;/strong&gt; which
implements the binding glue (&lt;strong&gt;INotifyPropertyChanged&lt;/strong&gt;) needed for data
binding.&amp;nbsp; A side note here is that you could write your own custom data provider
if you needed to, although if the data is exposed through a .NET object, then the
ObjectDataProvider is probably sufficient.
&lt;/p&gt;
&lt;p&gt;
Using the providers is fairly easy -- let's say we have some XML data that looks like
this:
&lt;/p&gt;
&lt;p&gt;
&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;&lt;font color=blue size=+1&gt;?&lt;/font&gt;xml version&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"1.0"&lt;/font&gt; encoding&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"utf-8"&lt;/font&gt;&lt;font color=blue size=+1&gt;?&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;taxrecords&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Opal
Harrison"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"AL"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$51,466.81"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"27"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Eugene
Black"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"FL"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$13,314.89"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"71"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Opal
Chang"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"NC"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$225,115.15"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"41"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Gary
Waters"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"WI"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$151,788.49"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"39"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Xavier
Davis"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"AK"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$136,344.97"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"66"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Stacy
Harrison"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"TX"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$122,432.82"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"32"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;/taxrecords&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
The goal is to put this data into a ListBox - displaying the fields in the following
format:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Name&lt;br&gt;
&lt;/strong&gt;State, Age, Income
&lt;/p&gt;
&lt;p&gt;
We could clearly do all of this from procedural code -- create an XmlReader object,
load the data and render each XmlNode into the listbox.&amp;nbsp; However, this is the
21st century and so we want to avoid coding as much as we can and utilize the underlying
framework support instead!
&lt;/p&gt;
&lt;p&gt;
We can get the data loaded into a collection source through the XmlDataProvider.&amp;nbsp;
This is easily done in XAML:
&lt;/p&gt;
&lt;font color=#0000ff size=5&gt; 
&lt;p&gt;
&lt;font size=3&gt;&amp;lt;&lt;/font&gt;
&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;XmlDataProvider&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Source&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;largeXmlFile.xml&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;x:Key&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;xmlData&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;XPath&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;/taxrecords&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff size=5&gt;&lt;font size=3&gt; /&amp;gt;&lt;/font&gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font color=#0000ff size=5&gt;&lt;font color=#000000 size=2&gt;This will look for the file
"largeXmlFile.xml", create&amp;nbsp;an XmlDocument and load the file into memory.&amp;nbsp;
Notice we supply an XPath expression as part of this to indicate what we'd like the
data provider to hand us as the collection itself.&amp;nbsp; In this case, we want to
see everything under the node "taxrecords" which is the root of the document.&amp;nbsp;
An interesting facet of this provider is that it performs it's work asynchronously
-- you can see this behavior when you load very large XML files.&amp;nbsp; The UI will
come up first, completely empty and then suddenly be populated with data.&amp;nbsp; The
behavior can be adjusted through the &lt;strong&gt;IsAsynchronous&lt;/strong&gt; property of the
data provider.&amp;nbsp; Setting this to &lt;strong&gt;false&lt;/strong&gt; will delay the display
of the UI until the data is fully available.&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font color=#000000&gt;Another interesting thing about this class is that we can define
the XML data inline within the XAML document.&amp;nbsp; You do this with the &lt;strong&gt;x:XData&lt;/strong&gt; tag:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font color=#000000&gt;&lt;font color=#0000ff size=3&gt;&amp;lt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;XmlDataProvider&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;x:Key&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;xmlData&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;XPath&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;/taxrecords&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff size=5&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &amp;lt;x:Data&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;taxrecords&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry
name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Opal Harrison"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"AL"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$51,466.81"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"27"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;/font&gt;&lt;span class=cch1&gt;&lt;font color=gray&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color=blue size=+1&gt;&amp;lt;&lt;/font&gt;entry
name&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"Eugene Black"&lt;/font&gt; state&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"FL"&lt;/font&gt; income&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"$13,314.89"&lt;/font&gt; age&lt;font color=blue size=+1&gt;=&lt;/font&gt;&lt;font color=purple&gt;"71"&lt;/font&gt; &lt;font color=blue size=+1&gt;/&lt;/font&gt;&lt;font color=blue size=+1&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt;&lt;font color=#0000ff size=5&gt;&lt;font size=3&gt;&lt;span class=cch1&gt;
&lt;br&gt;
&lt;/span&gt;&lt;font color=blue size=+1&gt;&lt;font color=#808080 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&amp;lt;&lt;/font&gt;/taxrecords&lt;font color=blue size=+1&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff size=3&gt;&amp;lt;/x:Data&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font color=#000000&gt;&lt;font color=#0000ff size=3&gt;&lt;font color=#000000&gt;&lt;font color=#0000ff size=3&gt;&amp;lt;/&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;XmlDataProvider&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff size=5&gt;&lt;font size=3&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&gt;&gt; 
&lt;p&gt;
&lt;font color=#0000ff size=5&gt;&lt;font color=#000000 size=2&gt;The next step is to bind this
data to a ListBox control - this is a normal Data Binding expression:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font color=#0000ff size=5&gt;&lt;font color=#0000ff size=5&gt; 
&lt;p&gt;
&lt;font size=3&gt;&amp;lt;&lt;/font&gt;
&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;ListBox&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Name&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;lb1&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Margin&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;10&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;IsSynchronizedWithCurrentItem&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;True&lt;/font&gt;&lt;font color=#000000&gt;" &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;ItemsSource&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
Source={StaticResource xmlData, XPath=entry}}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font color=#0000ff size=5&gt;&lt;font color=#000000 size=2&gt;Notice how we use a new property
of the BindingExpression called &lt;strong&gt;XPath&lt;/strong&gt;.&amp;nbsp; This property allows
you to identify which element(s) you want to load from the XML data source.&amp;nbsp;
It is specific to this data provider and allows for any XPath expression to be supplied.&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff size=5&gt;&lt;font color=#000000 size=2&gt;This
will succesfully load each of the "/taxrecord/entry" nodes into the ListBox, but the
data itself&amp;nbsp;will show&amp;nbsp;up as a blank line.&amp;nbsp; This, of course, is because
the data is really an XmlNode object which the ListBox has no idea how to display.&amp;nbsp;
To fix this, we supply a DataTemplate to render our data:&amp;nbsp;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font color=#0000ff size=5&gt;&lt;font color=#0000ff size=5&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;font size=3&gt;&amp;lt;&lt;/font&gt;
&lt;/font&gt;&lt;font color=#800000 size=3&gt;ListBox.ItemTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;DataTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;FontWeight&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;Bold&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@name}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Orientation&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;Horizontal&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@state}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;, &lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@age}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;, &lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@income}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;DataTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;ListBox.ItemTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font color=#0000ff size=5&gt;&lt;font color=#000000 size=2&gt;Again, we use the XPath property
to define what piece of information we are binding to -- attributes of our entry in
this case.&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff size=5&gt;&lt;font color=#000000 size=2&gt;This
template will give us the format we are looking for:&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;br&gt;
&lt;img src="http://www.julmar.com/blog/mark/content/binary/AsyncDataBind.jpg" border=0&gt;&gt;
&lt;p&gt;
We can add sorting, filtering and grouping using the normal &lt;strong&gt;CollectionViewSource&lt;/strong&gt; support.&amp;nbsp;
Here is a XAML file which will present the above UI complete with sorting by the age
element.&amp;nbsp; Notice how the XPath expression now moves to the CollectionView.&amp;nbsp;
This is because the CollectionViewSource creates a &lt;strong&gt;ListCollectionView &lt;/strong&gt;to
manage the XML nodes because the data provider supports the &lt;strong&gt;IList&lt;/strong&gt; interface.&amp;nbsp;
The binding expression on the listbox is now simply a binding to the collection view.
&lt;/p&gt;
&lt;font color=#0000ff size=5&gt; 
&lt;p&gt;
&lt;font size=3&gt;&amp;lt;&lt;/font&gt;
&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;Window&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Title&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;AsyncDataBind&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Height&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;300&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Width&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;300&lt;/font&gt;&lt;font color=#000000&gt;"&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;xmlns&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/font&gt;&lt;font color=#000000&gt;"&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;xmlns:cm&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;clr-namespace:System.ComponentModel;assembly=WindowsBase&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; 
&lt;br&gt;
&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;xmlns:x&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=3&gt;&amp;lt;&lt;/font&gt;
&lt;/font&gt;&lt;font color=#800000 size=3&gt;Window.Resources&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;XmlDataProvider&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Source&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;largeXmlFile.xml&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;IsAsynchronous&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;True&lt;/font&gt;&lt;font color=#000000&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;x:Key&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;xmlData&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;XPath&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;/taxrecords&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;CollectionViewSource&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;x:Key&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;collView&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Source&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
Source={StaticResource xmlData},XPath=entry}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;CollectionViewSource.SortDescriptions&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;cm:SortDescription&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;PropertyName&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;@age&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Direction&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;Ascending&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;CollectionViewSource.SortDescriptions&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;CollectionViewSource&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;
&lt;br&gt;
&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;Window.Resources&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;Grid&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;Grid.RowDefinitions&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;RowDefinition&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Height&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;*&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;RowDefinition&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Height&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;Auto&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;Grid.RowDefinitions&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=3&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/font&gt;
&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;ListBox&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Name&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;lb1&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Margin&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;10&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;IsSynchronizedWithCurrentItem&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;True&lt;/font&gt;&lt;font color=#000000&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#ff0000&gt;ItemsSource&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
Source={StaticResource collView}}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;ListBox.ItemTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;DataTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;FontWeight&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;Bold&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@name}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Orientation&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;Horizontal&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@state}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;, &lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@age}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;, &lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
XPath=@income}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;DataTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;ListBox.ItemTemplate&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;ListBox&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;Button&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Grid.Row&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;1&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Orientation&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;Horizontal&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt;{Binding
ElementName=lb1, Path=Items.Count}&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;TextBlock&lt;/font&gt;&lt;font color=#0000ff&gt; &lt;/font&gt;&lt;font color=#ff0000&gt;Text&lt;/font&gt;&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;font color=#0000ff&gt; Items&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;StackPanel&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;Button&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;
&lt;br&gt;
&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font color=#800000 size=3&gt;Grid&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;font size=3&gt;&amp;gt;&lt;br&gt;
&lt;/font&gt;&lt;font size=3&gt;&amp;lt;/&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;font color=#800000&gt;Window&lt;/font&gt;&lt;font color=#0000ff&gt;&amp;gt;&gt;
&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;
Data binding in WPF is extremely powerful -- I am constantly amazed at how much procedural
code you can dump in favor of markup with creative bindings.&amp;nbsp; In the next post
I'll talk a bit more about asynchronouus bindings outside of the two data providers.
&lt;/p&gt;
&lt;p&gt;
Until then.. 
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,5716861f-5560-40c7-b700-483e0cd80116.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=643649fc-0467-4f0d-9a95-323ed7ce4298</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,643649fc-0467-4f0d-9a95-323ed7ce4298.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,643649fc-0467-4f0d-9a95-323ed7ce4298.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=643649fc-0467-4f0d-9a95-323ed7ce4298</wfw:commentRss>
      <title>SOS: finding the method bound to an EventHandler&lt;T&gt; with WinDbg.</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,643649fc-0467-4f0d-9a95-323ed7ce4298.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/09/01/SOSFindingTheMethodBoundToAnEventHandlerWithWinDbg.aspx</link>
      <pubDate>Fri, 01 Sep 2006 18:18:41 GMT</pubDate>
      <description>I was preparing a sample memory leak application for an Advanced C# class at Microsoft this past week and debugging through it with SOS.DLL ("Son of Strike").  My prepared application was an ASP.NET application that would leak memory by holding references to the page objects after they had completed their work.  I did this by having the page hook up an event handler to a global event and then never remove the handler.
&lt;br /&gt;
&lt;br /&gt;
This, of course, is bad form because the System.Web.UI.Page object is intended to
be a transient object - it goes away at the end of the request - in production code,
I would really bind the event to a handler in &lt;b&gt;global.asax&lt;/b&gt; instead. But as I
said, this was a sample. 
&lt;br /&gt;
&lt;br /&gt;
So, I was debugging through it prior to the class just to make sure it exhibited the
behavior I was looking for. I run the web page a few times, noted my working set going
up and never coming back down. Next, I used &lt;b&gt;ADPLUS.VBS&lt;/b&gt; to take a hang dump
of the process. I then loaded this dump up into WinDBG and started poking around.
First, I looked at the heap and sure enough I saw a bunch of page objects: 
&lt;br /&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: medium;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;
0:000&gt; .load sos
0:000&gt; !DumpHeap -stat
total 36955 objects
Statistics:
      MT    Count    TotalSize Class Name
7b4ecd7c        1           12 System.Windows.Forms.ButtonInternal.ButtonPopupAdapter
7b481f00        1           12 System.Windows.Forms.LinkLabel+LinkComparer
7b475ca8        1           12 System.Windows.Forms.FormCollection
7b474f8c        1           12 System.Windows.Forms.Layout.DefaultLayout
7b4749e0        1           12 System.Windows.Forms.ClientUtils+WeakRefCollection
7b473ca8        1           12 System.Windows.Forms.Layout.ArrangedElementCollection
7a755834        1           12 System.Diagnostics.PerformanceCounterCategoryType
7a753394        1           12 System.Diagnostics.TraceOptions
7a71a710        1           12 System.Net.TimeoutValidator
.......
00166030      891       169744      Free
054d24d4     3128       187680 System.Web.UI.LiteralControl
&lt;b&gt;0548cbd4
519 197220 ASP.default_aspx &lt;/b&gt;791242ec 1545 297960 System.Collections.Hashtable+bucket[]
79124670 1185 1090500 System.Char[] 79124228 11961 1279380 System.Object[] 790fa3e0
19149 1561392 System.String Total 110069 objects &lt;/pre&gt;
So, next I used &lt;b&gt;DumpHeap&lt;/b&gt; to just look at this specific type by giving it a
metadata token: &lt;pre class="csharpcode"&gt;
0:000&gt; !DumpHeap -mt 0548cbd4        
 Address       MT     Size
.....     
01854ff0 0548cbd4      380     
01860130 0548cbd4      380     
0186b2b4 0548cbd4      380     
018773f8 0548cbd4      380     
01882538 0548cbd4      380     
0188d6bc 0548cbd4      380     
01898840 0548cbd4      380     
018a39c4 0548cbd4      380     
018aeb48 0548cbd4      380     
total 519 objects
Statistics:
      MT    Count    TotalSize Class Name
0548cbd4      519       197220 ASP.default_aspx
Total 519 objects
&lt;/pre&gt;
I then used the &lt;i&gt;very&lt;/i&gt; cool &lt;b&gt;GCRoot&lt;/b&gt; command to determine why a page instance
was still rooted and therefore not collectable. 
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border:thin solid;border-color:black;background-color:lightgrey;padding-top:10px;padding-left:10px;padding-right:10px;padding-bottom:10px;"&gt;
&lt;b&gt;Note: &lt;/b&gt;it appears that GCRoot doesn't work well inside VS.NET 2005 - apparently
the SOS debugging extension is using some debugger API which isn't fully supported
in VS.NET, so you need to familiarize yourself with WinDBG to do this. 
&lt;/div&gt;
 /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;
0:000&gt; !gcroot 018aeb48 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 3a8
Scan Thread 2 OSTHread e8
Scan Thread 3 OSTHread 1a8
Scan Thread 6 OSTHread 7d4
Scan Thread 7 OSTHread 2b4
Scan Thread 8 OSTHread fdc
Scan Thread 9 OSTHread eac
DOMAIN(001E5E08):HANDLE(Pinned):12312f0:Root:0226c498(System.Object[])-&gt;
018af940(System.EventHandler)-&gt;
0186c0ac(System.Object[])-&gt;
018af920(System.EventHandler)-&gt;
018aeb48(ASP.default_aspx)
&lt;/pre&gt;
With this output, I can tell that my default_aspx object is being kept alive through
an EventHandler as I expected. The interesting thing about this output is I cannot
tell which event handler is keeping it alive - i.e. there is nothing in this root
list that points to a specific object holding it other than a object[]. That essentially
means this is a static event and there isn't an actual object around on the heap for
it. This just makes the debugging exercise more interesting - after all if it were
an instance event then I would see the class name at the top of the root list and
we could stop right here. 
&lt;br /&gt;
&lt;br /&gt;
So, my next step is to dump the event handler to try to identify what method it is
wrapping - I could then search the code for this method and find out where it is being
bound. I dump out the &lt;b&gt;EventHandler&lt;/b&gt; object: &lt;pre class="csharpcode"&gt;
0:000&gt; !do 018af920
Name: System.EventHandler
MethodTable: 7910d61c
EEClass: 790c3a7c
Size: 32(0x20) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
790f9c18  40000f9        4        System.Object  0 instance 018aeb48 _target
79109208  40000fa        8 ...ection.MethodBase  0 instance 00000000 _methodBase
790fe160  40000fb        c        System.IntPtr  0 instance 88962888 _methodPtr
790fe160  40000fc       10        System.IntPtr  0 instance        0 _methodPtrAux
790f9c18  4000106       14        System.Object  0 instance 00000000 _invocationList
790fe160  4000107       18        System.IntPtr  0 instance        0 _invocationCount
&lt;/pre&gt;
From this I get the internals of the EventHandler object. It gives me some specific
information: 
&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;_target&lt;/b&gt; is the object the delegate is holding onto - my default_aspx in this
case. The value &lt;i&gt;better&lt;/i&gt; match up with my original object! 
&lt;li&gt;
&lt;b&gt;_methodBase&lt;/b&gt; is used for dynamic code and is null here. 
&lt;li&gt;
&lt;b&gt;_methodPtr&lt;/b&gt; is the method associated with the instance, or possibly a dynamically
generated thunk for static methods. This is what I'm interested in. 
&lt;li&gt;
&lt;b&gt;_methodPtrAux&lt;/b&gt; is used for static methods; this holds the method descriptor
and the &lt;b&gt;_methodPtr&lt;/b&gt; is a dynamically generated block of code to remove the &lt;b&gt;this&lt;/b&gt; reference.
Noting that this is null, I can infer that this is an instance method bound to the
delegate. 
&lt;li&gt;
&lt;b&gt;_invocationList&lt;/b&gt; and &lt;b&gt;_invocationCount&lt;/b&gt; are used for Multicast Delegates
-- these are both zero indicating that this is a single delegate and there is no chain
to follow. 
&lt;/ul&gt;
&lt;br /&gt;
My next step is to try to get a valid method name from the &lt;b&gt;_methodPtr&lt;/b&gt; so I
convert that to hex and pass it into IP2MD. &lt;pre class="csharpcode"&gt;
0:000&gt; !ip2md 0n88962888 
Failed to request MethodData, not in JIT code range
&lt;/pre&gt;
This is a pretty common error and simply means that the method may not have been JITted
yet, or may be a dynamic block of code which never went through the JIT compiler.
In .NET 1.1 we could start dumping method descriptors and trying to match up the address
(DumpClass -md) for this class and it's base class. 
&lt;br /&gt;
&lt;br /&gt;
However, under .NET 2.0 this rarely works anymore - the address doesn't appear to
ever match up to a valid descriptor. However, it clearly is part of the managed heap
due to it's address. So, failing to locate this address, I tried disassembling the
code: &lt;pre class="csharpcode"&gt;
0:000&gt; !u 0n88962888 
Unmanaged code
054d7748 e862289b74      call    mscorwks!LogHelp_TerminateOnAssert+0x3f5f (79e89faf)
054d774d 5e              pop     esi
054d774e cc              int     3
054d774f cc              int     3
054d7750 38c8            cmp     al,cl
054d7752 48              dec     eax
054d7753 05a0774d05      add     eax,54D77A0h
054d7758 0100            add     dword ptr [eax],eax
054d775a 0011            add     byte ptr [ecx],dl
054d775c 0000            add     byte ptr [eax],al
&lt;/pre&gt;
Humph. This doesn't even look like valid code to me.. this looks like random data,
so I dumped it out: &lt;pre class="csharpcode"&gt;
0:000&gt; dd 0n88962888 
054d7748  9b2862e8 cccc5e74&lt;b&gt; 0548c838
054d77a0&lt;/b&gt; 054d7758 11000001 90000000 054d77a0 11000002 054d7768 90000004 00000000
054d77a0 00000000 &lt;/pre&gt;
The third and fourth DWORD look interesting because they appear to fall in the managed
heap as well -- so I began to dump them out trying to figure out what they were. I
found that the first value is a method descriptor: &lt;pre class="csharpcode"&gt;
0:000&gt; !dumpmd 0548c838 
Method Name: _Default.OnDatabaseHasChanged(System.Object, System.EventArgs)
Class: 054ab574
MethodTable: 0548c86c
mdToken: 06000004
Module: 0548c35c
IsJitted: no
m_CodeOrIL: ffffffff
&lt;/pre&gt;
It is the real method bound to the delegate instance. The other DWORD appears to be
an metadata reference to the event owner itself: &lt;pre class="csharpcode"&gt;
0:000&gt; !dumpmt 054d77a0
EEClass: 0551940c
Module: 048ac9ec
Name: DatabaseMonitor
mdToken: 02000002  (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\leakypage\2a399ab5\b1e04c63\App_Code.onwg1zqj.dll)
BaseSize: 0xc
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 8
&lt;/pre&gt;
From here I can see the module that this code is defined in (the dynamically generated
App_Code directory) and the name (&lt;b&gt;DatabaseMonitor&lt;/b&gt;). This gives me enough information
to stop here and begin looking at the code itself - specifically where default.aspx
binds it's OnDatabaseHasChanged method to the DatabaseMonitor static class defined
somewhere in the App_Code directory. If I didn't have the source code available, I
could locate the module and then save it out to a file through the &lt;b&gt;savemodule&lt;/b&gt; command: &lt;pre class="csharpcode"&gt;
0:000&gt; lm m App_Code_onwg1zqj
start    end        module name
04de0000 04de8000   App_Code_onwg1zqj C (no symbols)           
0:000&gt; !savemodule 04de0000 c:\appcode.dll
3 sections in file
section 0 - VA=2000, VASize=504, FileAddr=200, FileSize=600
section 1 - VA=4000, VASize=2c8, FileAddr=800, FileSize=400
section 2 - VA=6000, VASize=c, FileAddr=c00, FileSize=200
&lt;/pre&gt;
I could then ILDasm or Reflector the generated assembly and look for my bug from that. 
&lt;br /&gt;
&lt;br /&gt;
I love SOS and WinDBG.. if only they could match up managed source code to the image I'd abandon VS.NET as a debugger altogether..
</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,643649fc-0467-4f0d-9a95-323ed7ce4298.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>Debugging</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=a080551e-30d1-47d5-b8a4-1007481b9528</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,a080551e-30d1-47d5-b8a4-1007481b9528.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,a080551e-30d1-47d5-b8a4-1007481b9528.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=a080551e-30d1-47d5-b8a4-1007481b9528</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Times New Roman" size="3">I've gotten several questions on this topic
so I thought it might be a good thing to show in a blog.  Recording with TAPI
3.1 is actually pretty easy if you are running on Windows XP or better.  TAPI
3.1 provides some simple filename-based methods to dump the conversation into a .WAV
file.  If you want to control the file, or stream it somewhere else, it's a bit
more difficult and Microsoft provides a decent sample with the platform SDK that does
it.</font>
        </p>
        <p>
          <font face="Times New Roman" size="3">Here's a simple example -- in this scenerio
we will create a new outgoing call, connect it and then setup an outgoing stream to
play a welcome message:</font>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font size="3">
              <font color="#0000ff">TapiCall</font> currCall <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> selectedAddress.CreateCall(numberToDial,
LINEADDRESSTYPES.PhoneNumber, TAPIMEDIATYPES.AUDIO);<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (currCall
!<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
{<br />
   currCall.Connect(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">false</span>);<br /></font>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font size="3">  
playbackTerminal <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> currCall.RequestTerminal(TTerminal.FilePlaybackTerminal,
TAPIMEDIATYPES.AUDIO, TERMINAL_DIRECTION.TD_CAPTURE);<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
if</span> (playbackTerminal !<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
   {<br />
      playbackTerminal.MediaPlayList <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span>[]
{ MESSAGE_PROMPT };<br />
      currCall.SelectTerminalOnCall(playbackTerminal);<br />
   }<br />
}</font>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="2">When
the call is actually connected, then we will start the playbackTerminal stream and
begin recording the conversation - this would typically be done in the TE_CALLSTATE
handler:</font>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font size="3">
                <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (e.State
== CALL_STATE.CS_CONNECTED &amp;&amp; playbackTerminal !<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
// Start the playback message..</span><br />
   playbackTerminal.Start();<br />
   </font>
              <font size="3">
                <font color="#008000">// Begin recording the
conversation - may be half-duplex..<br /></font>   RecordConversation("RecordedMessage.wav");<br /></font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font size="3">}<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">else</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (e.State
== CALL_STATE.CS_DISCONNECTED)<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
// Stop recording when the call terminates.</span><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
if</span> (recordTerminal !<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
      recordTerminal.Stop();<br /><br />
   recordTerminal <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>;<br />
   playbackTerminal <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>;<br />
}<br /></font>
            </span>
          </span>
        </p>
        <p>
          <font face="Times New Roman" size="3">The code for recording the conversation is pretty
simple as well, given a filename, just get a recording terminal and assign it. 
TAPI will take care of creating the file and writing contents into it.</font>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font size="3">
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">private</span>
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> RecordConversation(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span> fileName)<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
// This code only works on XP or better (TAPI 3.1).</span><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
if</span> (currCall !<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
   {<br />
      recordTerminal <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> currCall.RequestTerminal(TTerminal.FileRecordingTerminal,
TAPIMEDIATYPES.MULTITRACK, TERMINAL_DIRECTION.TD_RENDER);<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">     
if</span> (recordTerminal !<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
      {<br />
         recordTerminal.RecordFileName <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> fileName;<br />
         currCall.SelectTerminalOnCall(recordTerminal);<br />
         recordTerminal.Start();<br />
      }<br /><font color="#0000ff">   </font>}<br />
}<br /></font>
          </span>
        </p>
        <p>
          <font face="Times New Roman" size="3">Finis.<br /></font>
        </p>
      </body>
      <title>You can be just like the government and record telephone conversations.. with TAPI 3.1</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,a080551e-30d1-47d5-b8a4-1007481b9528.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/06/19/YouCanBeJustLikeTheGovernmentAndRecordTelephoneConversationsWithTAPI31.aspx</link>
      <pubDate>Mon, 19 Jun 2006 15:41:45 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face="Times New Roman" size=3&gt;I've gotten several questions on this topic so
I thought it might be a good thing to show in a blog.&amp;nbsp; Recording with TAPI 3.1
is actually pretty easy if you are running on Windows XP or better.&amp;nbsp; TAPI 3.1
provides some simple filename-based methods to dump the conversation into a .WAV file.&amp;nbsp;
If you want to control the file, or stream it somewhere else, it's a bit more difficult
and Microsoft provides a decent sample with the platform SDK that does it.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Times New Roman" size=3&gt;Here's a simple example -- in this scenerio we
will create a new outgoing call, connect it and then setup an outgoing stream to play
a welcome message:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=3&gt;&lt;font color=#0000ff&gt;TapiCall&lt;/font&gt; currCall &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; selectedAddress.CreateCall(numberToDial,
LINEADDRESSTYPES.PhoneNumber, TAPIMEDIATYPES.AUDIO);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (currCall
!&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; currCall.Connect(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;false&lt;/span&gt;);&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=3&gt;&amp;nbsp;&amp;nbsp;
playbackTerminal &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; currCall.RequestTerminal(TTerminal.FilePlaybackTerminal,
TAPIMEDIATYPES.AUDIO, TERMINAL_DIRECTION.TD_CAPTURE);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
if&lt;/span&gt; (playbackTerminal !&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; playbackTerminal.MediaPlayList &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt;[]
{ MESSAGE_PROMPT };&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; currCall.SelectTerminalOnCall(playbackTerminal);&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;When
the call is actually connected, then we will start the playbackTerminal stream and
begin recording the conversation - this would typically be done in the TE_CALLSTATE
handler:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=3&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (e.State
== CALL_STATE.CS_CONNECTED &amp;amp;&amp;amp; playbackTerminal !&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
// Start the playback message..&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; playbackTerminal.Start();&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size=3&gt;&lt;font color=#008000&gt;//&amp;nbsp;Begin recording the conversation
- may be&amp;nbsp;half-duplex..&lt;br&gt;
&lt;/font&gt;&amp;nbsp;&amp;nbsp; RecordConversation("RecordedMessage.wav");&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=3&gt;}&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;else&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (e.State
== CALL_STATE.CS_DISCONNECTED)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
// Stop recording when the call terminates.&lt;/span&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
if&lt;/span&gt; (recordTerminal !&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recordTerminal.Stop();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; recordTerminal &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp; playbackTerminal &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;;&lt;br&gt;
}&lt;br&gt;
&lt;/font&gt;
&lt;/p&gt;
&gt; 
&lt;p&gt;
&lt;font face="Times New Roman" size=3&gt;The code for recording the conversation is pretty
simple as well, given a filename, just get a recording terminal and assign it.&amp;nbsp;
TAPI will take care of creating the file and writing contents into it.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=3&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; RecordConversation(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt; fileName)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
// This code only works on XP or better (TAPI 3.1).&lt;/span&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
if&lt;/span&gt; (currCall !&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recordTerminal &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; currCall.RequestTerminal(TTerminal.FileRecordingTerminal,
TAPIMEDIATYPES.MULTITRACK, TERMINAL_DIRECTION.TD_RENDER);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if&lt;/span&gt; (recordTerminal !&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recordTerminal.RecordFileName &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; fileName;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; currCall.SelectTerminalOnCall(recordTerminal);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recordTerminal.Start();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;}&lt;br&gt;
}&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Times New Roman" size=3&gt;Finis.&lt;br&gt;
&lt;/font&gt;
&lt;/p&gt;
&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,a080551e-30d1-47d5-b8a4-1007481b9528.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>Tapi</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=e47f09cc-e893-46a6-aa13-7202d4e50986</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,e47f09cc-e893-46a6-aa13-7202d4e50986.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,e47f09cc-e893-46a6-aa13-7202d4e50986.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=e47f09cc-e893-46a6-aa13-7202d4e50986</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A colleague of mine, <a href="http://blogs.advantaje.com/blog/kevin/Net/2006/04/15/Using-Config-Files-to-Manage-DataDrivenTesting-in-VSTS.html">Kev
Jones</a>, has posted some information on using a detached SQL Server database
for driving VSTS unit tests which works great if you need a full blown SQL implementation. 
However, if all you want is a simple data feed, you can also use an Excel file, and
as it turns out, it's pretty easy to do.
</p>
        <p>
Let's start by stealing Kev's sample, hopefully he won't mind -- say I have a starship
class with a <strong>FirePhotonTorpedo</strong> method:
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">public</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">class</span> Enterprise<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
private</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> torpedosLeft
= 10;<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
public</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> FirePhotonTorpedo(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> count)<br />
   {<br /></span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">     
if</span> (torpedosLeft &lt; count)<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">        
throw</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span> ArgumentException(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"count"</span>);<br /><br />
      torpedosLeft -= count;<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">      //
Instruct bridge officer to "Fire!"</span><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">     
return</span> torpedosLeft;<br />
   }<br />
}</span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">The
equivalent unit test might look something like:</font>
            </span>
          </span>
        </p>
        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="2">
              <p>
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                    <font color="#000000">[TestMethod]</font>
                    <br />
public</span>
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> TestFirePhotonTorpedo()<br />
{<br />
   Enterprise target <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span> Enterprise();<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
int</span> torpedoCount <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> 5;<br />
   <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> expected <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> 5;<br /></span>
              </p>
              <p>
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
int</span> actual <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> target.FirePhotonTorpedo(torpedoCount);<br />
   Assert.AreEqual(expected, actual, <span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"FirePhotonTorpedo
did not return the expected value."</span>);<br />
}<br /></span>
              </p>
            </font>
          </span>
        </span>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">This
code just tests a specific case -- I would also need to write other unit tests for
edge cases and exceptional cases.  I can do this several different ways I could
do this:</font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">1)
Write a unit test for each specific case passing each value and testing the expected
result.<br />
2) Put all the tests into this one unit test function -- asserting each validation
as we go.<br />
3) Pull the input and expected out of a database and run them through
the function.</font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">This
last step, as Kev details can be done from a SQL database - either one reachable by
all the people who might run the unit tests, or as his blog shows from a .MDF file
you check in with the project and then locally attach prior to running the unit tests. 
Hit the link above for the details on that. </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">So,
to make an Excel data-driven test, the first step is to create an Excel document with
columns for each of our pieces of data.  My sample Excel document has the following
columns:</font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <table width="100%" border="0">
                <tbody>
                  <tr>
                  </tr>
                  <font face="Verdana" color="#003300" size="2">
                    <td width="20%">
                      <strong>ID</strong>
                    </td>
                    <td width="80%">
A unique number identifying the row so we can use the Random data driven test</td>
                    <tr>
                      <td>
                        <strong>torpedoCount</strong>
                      </td>
                      <td>
The input for our unit test</td>
                    </tr>
                    <tr>
                      <td>
                        <strong>expected</strong>
                      </td>
                      <td>
The expected result coming out of the function</td>
                    </tr>
                    <tr>
                      <td>
                        <strong>shouldFail</strong>
                      </td>
                      <td>
Whether the function will throw an exception.</td>
                    </tr>
                  </font>
                </tbody>
              </table>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">I
can then enter a single test on each row of the given worksheet.  Here's
a screen shot --</font>
            </span>
          </span>
        </p>
        <p>
          <img src="http://www.julmar.com/blog/mark/content/binary/datadriven-excel1.JPG" border="0" />
        </p>
        <p>
You can create multiple "tables" by adding additional sheets to the worksheet. 
Each sheet can be named as appropriate; I'm naming this one "TorpedoData".
</p>
        <p>
Now, I need to add the appropriate attribute to my test case to indicate that it should
pull the data from a data source and run the method once per row found.  The
key is that <em>any</em> ADO.NET data source can be used.  Here I will specify
my Excel file which is named "UnitTests.xls" and indicate that the table itself is
a particular sheet within the Excel document "TorpedoData":
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                    <font color="#000000">[TestMethod]<br /></font>
                  </span>
                </span>
              </font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                    <font color="#000000">
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                          <font face="Verdana" color="#003300" size="2">
                            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                                <font color="#000000">[DeploymentItem(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"Tests.xls"</span>)] <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
Copies the file to the deployment directory</span></font>
                              </span>
                            </span>
                          </font>
                        </span>
                      </span>
                    </font>
                  </span>
                </span>
              </font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                    <font color="#000000">
                      <br />
                    </font>
                    <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">[DataSource(<br /><span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"System.Data.OleDb"</span>, <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
The provider</span><br /><span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=<strong>'Tests.xls'</strong>;Persist Security Info=False;Extended Properties='Excel
8.0'"</span>,<br /><span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"TorpedoData$"</span>,      <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
The table name, in this case, the sheet name with a '$' appended.</span><br />
DataAccessMethod.Sequential)]  </span>
                    <br />
public</span>
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> TestFirePhotonTorpedo()<br />
{</span>
              </font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <br />
                </span>
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">}<br /></span>
              </font>
            </span>
          </span>
        </p>
        <p>
I also need to update the test case itself to use the data -- we do that through the
TestContext.DataRow property that gives us access to the current row of data from
our data source:
</p>
        <p>
          <font face="Courier New">
            <font color="#0000ff">public</font>
            <font color="#000000">
            </font>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font size="2">void</font>
            </span>
          </font>
          <font face="Courier New" color="#000000"> TestFirePhotonTorpedo()<br />
{</font>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <br />
                  <font size="2">   Enterprise target <font color="#000000"><span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span> Enterprise();<br />
   </font></font>
                </span>
              </font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font size="2">
                    <font color="#000000">
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> torpedoCount <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> Convert.ToInt32(TestContext.DataRow[<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"torpedoCount"</span>]);<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   int</span> expected <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> Convert.ToInt32(TestContext.DataRow[<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"expected"</span>]);<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
bool</span> shouldFail <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> (<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">bool</span>)TestContext.DataRow[<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"shouldFail"</span>];<br /><br />
   TestContext.WriteLine(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"Running
test with TorpedoCount={0}, ExpectedCount={1}, ShouldFail={2}"</span>,<br />
            torpedoCount, expected,
shouldFail);<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
try</span><br />
   {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">     
int</span> actual <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> target.FireTorpedos(torpedoCount);<br />
      Assert.AreEqual(expected, actual, <span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"FireTorpedos
did not return the expected value."</span>);<br />
   }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">  
catch</span> (Exception ex)<br />
   {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">     
if</span> (!shouldFail)<br />
         Assert.Fail(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span>.Format(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"FireTorpedo
threw exception {0}"</span>, ex.Message));<br />
   }<br /></span>
                    </font>
                  </font>
                </span>
              </font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font size="2">
                    <font color="#000000">
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">}</span>
                    </font>
                  </font>
                </span>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font>
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font size="2">
                    <font size="2">
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                      </span>
                    </font>
                  </font>
                </span>
              </font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font size="2">
                    <font color="#000000">
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <font face="Verdana" color="#003300" size="2">So,
here we will grab the data from the current row, converting it as necessary to the
appropriate types, output a test line just to prove that we executed the method more
than once and then run the test.  The test will compare the result with the expected
database result and output a failure if they aren't the same.  If an exception
is thrown, then the <strong>shouldFail </strong>must be true or that will be considered
a failure.</font>
                      </span>
                    </font>
                  </font>
                </span>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font size="2">
                    <font color="#000000">
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <font face="Verdana" color="#003300" size="2">This
approach allows me to run through different scenarios very easily and I can just store
the Excel worksheet right with my unit tests - make sure it's deployed to the target
deployment directory (either through a <strong>DeploymentItem</strong> attribute,
or through the test run configuration).  The size of my table here is about 14K,
compared to the equivalent .MDF file which is over 2M for the same data.  If
I didn't want to hardcode the filenames and such, I can also use an <strong>app.config</strong> file
for the unit test and put the information there - just as Kev details.</font>
                      </span>
                    </font>
                  </font>
                </span>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font size="2">
                    <font color="#000000">
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <font face="Verdana" color="#003300" size="2">Cool
stuff indeed.</font>
                      </span>
                    </font>
                  </font>
                </span>
              </font>
            </span>
          </span>
        </p>
      </body>
      <title>Using Excel for VSTS Data Driven Testing</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,e47f09cc-e893-46a6-aa13-7202d4e50986.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/05/01/UsingExcelForVSTSDataDrivenTesting.aspx</link>
      <pubDate>Mon, 01 May 2006 16:55:40 GMT</pubDate>
      <description>&lt;p&gt;
A colleague of mine, &lt;a href="http://blogs.advantaje.com/blog/kevin/Net/2006/04/15/Using-Config-Files-to-Manage-DataDrivenTesting-in-VSTS.html"&gt;Kev
Jones&lt;/a&gt;, has posted some information on using a detached&amp;nbsp;SQL Server database
for driving VSTS unit tests which works great if you need a full blown SQL implementation.&amp;nbsp;
However, if all you want is a simple data feed, you can also use an Excel file, and
as it turns out, it's pretty easy to do.
&lt;/p&gt;
&lt;p&gt;
Let's start by stealing Kev's sample, hopefully he won't mind -- say I have a starship
class with a &lt;strong&gt;FirePhotonTorpedo&lt;/strong&gt; method:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; Enterprise&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; torpedosLeft
= 10;&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; FirePhotonTorpedo(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; count)&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if&lt;/span&gt; (torpedosLeft &amp;lt; count)&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
throw&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; ArgumentException(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"count"&lt;/span&gt;);&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; torpedosLeft -= count;&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//
Instruct bridge officer to "Fire!"&lt;/span&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
return&lt;/span&gt; torpedosLeft;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;The
equivalent unit test&amp;nbsp;might look something like:&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#000000&gt;[TestMethod]&lt;/font&gt;
&lt;br&gt;
public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; TestFirePhotonTorpedo()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; Enterprise target &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; Enterprise();&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
int&lt;/span&gt; torpedoCount &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 5;&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; expected &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 5;&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
int&lt;/span&gt; actual &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; target.FirePhotonTorpedo(torpedoCount);&lt;br&gt;
&amp;nbsp;&amp;nbsp; Assert.AreEqual(expected, actual, &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"FirePhotonTorpedo
did not return the expected value."&lt;/span&gt;);&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;
&lt;/span&gt;&gt;&lt;/span&gt;&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;This
code just tests a specific case -- I would also need to write other unit tests for
edge cases and exceptional cases.&amp;nbsp; I can do this several different ways I could
do this:&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;1)
Write a unit test for each specific case passing each value and testing the expected
result.&lt;br&gt;
2) Put all the tests into this one unit test function -- asserting each validation
as we go.&lt;br&gt;
3) Pull the&amp;nbsp;input and&amp;nbsp;expected&amp;nbsp;out of a database and run them through
the function.&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;This
last step, as Kev details can be done from a SQL database - either one reachable by
all the people who might run the unit tests, or as his blog shows from a .MDF file
you check in with the project and then locally attach prior to running the unit tests.&amp;nbsp;
Hit the link above for the details on that.&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;So,
to make an Excel data-driven test, the first step is to create an Excel document with
columns for each of our pieces of data.&amp;nbsp; My sample Excel document has the following
columns:&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; 
&lt;table width="100%" border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;font face=Verdana color=#003300 size=2&gt; 
&lt;td width="20%"&gt;
&lt;strong&gt;ID&lt;/strong&gt;&lt;/td&gt;
&lt;td width="80%"&gt;
A unique number identifying the row so we can use the Random data driven test&lt;/td&gt;
&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;torpedoCount&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
The input for our unit test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;expected&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
The expected result coming out of the function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;shouldFail&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
Whether the function will throw an exception.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;I
can then enter&amp;nbsp;a single test on each&amp;nbsp;row of the given worksheet.&amp;nbsp; Here's
a screen shot --&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&gt;&lt;img src="http://www.julmar.com/blog/mark/content/binary/datadriven-excel1.JPG" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
You can create multiple "tables" by adding additional sheets to the worksheet.&amp;nbsp;
Each sheet can be named as appropriate; I'm naming this one "TorpedoData".
&lt;/p&gt;
&lt;p&gt;
Now, I need to add the appropriate attribute to my test case to indicate that it should
pull the data from a data source and run the method once per row found.&amp;nbsp; The
key is that &lt;em&gt;any&lt;/em&gt; ADO.NET data source can be used.&amp;nbsp; Here I will specify
my Excel file which is named "UnitTests.xls" and indicate that the table itself is
a particular sheet within the Excel document "TorpedoData":
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#000000&gt;[TestMethod]&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#000000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#000000&gt;[DeploymentItem(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"Tests.xls"&lt;/span&gt;)] &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
Copies the file to the deployment directory&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#000000&gt;
&lt;br&gt;
&lt;/font&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;[DataSource(&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"System.Data.OleDb"&lt;/span&gt;, &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
The provider&lt;/span&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=&lt;strong&gt;'Tests.xls'&lt;/strong&gt;;Persist Security Info=False;Extended Properties='Excel
8.0'"&lt;/span&gt;,&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"TorpedoData$"&lt;/span&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
The table name, in this case, the sheet name with a '$' appended.&lt;/span&gt;
&lt;br&gt;
DataAccessMethod.Sequential)]&amp;nbsp; &lt;/span&gt;
&lt;br&gt;
public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; TestFirePhotonTorpedo()&lt;br&gt;
{&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;}&lt;br&gt;
&lt;/p&gt;
&gt;&gt;&gt;&gt; 
&lt;p&gt;
I also need to update the test case itself to use the data -- we do that through the
TestContext.DataRow property that gives us access to the current row of data from
our data source:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;public&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt;void&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt; TestFirePhotonTorpedo()&lt;br&gt;
{&lt;/font&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;
&lt;br&gt;
&lt;font size=2&gt;&amp;nbsp;&amp;nbsp; Enterprise target &lt;font color=#000000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; Enterprise();&lt;br&gt;
&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; torpedoCount &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; Convert.ToInt32(TestContext.DataRow[&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"torpedoCount"&lt;/span&gt;]);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&lt;/span&gt; expected &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; Convert.ToInt32(TestContext.DataRow[&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"expected"&lt;/span&gt;]);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
bool&lt;/span&gt; shouldFail &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; (&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;bool&lt;/span&gt;)TestContext.DataRow[&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"shouldFail"&lt;/span&gt;];&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; TestContext.WriteLine(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"Running
test with TorpedoCount={0}, ExpectedCount={1}, ShouldFail={2}"&lt;/span&gt;,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; torpedoCount, expected,
shouldFail);&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
try&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
int&lt;/span&gt; actual &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; target.FireTorpedos(torpedoCount);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.AreEqual(expected, actual, &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"FireTorpedos
did not return the expected value."&lt;/span&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;
catch&lt;/span&gt; (Exception ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if&lt;/span&gt; (!shouldFail)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.Fail(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt;.Format(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"FireTorpedo
threw exception {0}"&lt;/span&gt;, ex.Message));&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt;&lt;font size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;So,
here we will grab the data from the current row, converting it as necessary to the
appropriate types, output a test line just to prove that we executed the method more
than once and then run the test.&amp;nbsp; The test will compare the result with the expected
database result and output a failure if they aren't the same.&amp;nbsp; If an exception
is thrown, then the &lt;strong&gt;shouldFail &lt;/strong&gt;must be true or that will be considered
a failure.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;This
approach allows me to run through different scenarios very easily and I can just store
the Excel worksheet right with my unit tests - make sure it's deployed to the target
deployment directory (either through a &lt;strong&gt;DeploymentItem&lt;/strong&gt; attribute,
or through the test run configuration).&amp;nbsp; The size of my table here is about 14K,
compared to the equivalent .MDF file which is over 2M for the same data.&amp;nbsp; If
I didn't want to hardcode the filenames and such, I can also use an &lt;strong&gt;app.config&lt;/strong&gt; file
for the unit test and put the information there - just as Kev details.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Cool
stuff indeed.&lt;/font&gt;
&lt;/p&gt;
&gt;&gt;&gt;&gt;&gt;&gt;&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,e47f09cc-e893-46a6-aa13-7202d4e50986.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
      <category>Enterprise</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=78805871-cb7b-4ea4-9be8-a8a1d61a15d8</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,78805871-cb7b-4ea4-9be8-a8a1d61a15d8.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,78805871-cb7b-4ea4-9be8-a8a1d61a15d8.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=78805871-cb7b-4ea4-9be8-a8a1d61a15d8</wfw:commentRss>
      <title>Creating synchronization sensitive components</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,78805871-cb7b-4ea4-9be8-a8a1d61a15d8.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/20/CreatingSynchronizationSensitiveComponents.aspx</link>
      <pubDate>Mon, 20 Mar 2006 22:42:45 GMT</pubDate>
      <description>&lt;p&gt;
One issue that's always a struggle with building reusable components is managing asynchronous
operations. The problem is that depending on the type of application that is going
to use the component, the thread used for callbacks and events may or may not be important.
For example, with Console based applications, callbacks on different threads might
be ok - at least as long as the application itself ensures thread safety. But, with
a Windows Forms application, threading is critical - you are not allowed to touch
UI controls from any thread other than the main one and so we end up with the &lt;strong&gt;Control.BeginInvoke&lt;/strong&gt; logic
in each of our callbacks which sucks.
&lt;/p&gt;
&lt;p&gt;
Enter the Synchronization Context - a new feature of .NET 2.0. Here's how it works:
&lt;/p&gt;
&lt;p&gt;
You derive your component from &lt;strong&gt;System.ComponentModel.Component.Component &lt;/strong&gt;and
provide your typical asynchronous function -- in this example, we will build a PiCalculator:
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;class&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;PiCalculator&lt;/font&gt;&lt;font size=2&gt; : &lt;/font&gt;&lt;font color=#008080 size=2&gt;Component&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;{&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; public&lt;/span&gt; PiCalculator();&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; CalculatePi(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; digits, &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; stateData);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; CancelAsync(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; asyncTask);&lt;br&gt;
}&lt;/span&gt;&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Here,
what we've done is create a new component with a default constructor and a method
called &lt;strong&gt;CalculatePi&lt;/strong&gt; which takes the number of digits, an optional
piece of state data and returns an object. With this component, I'd like to have multiple
outstanding asynchronous operations and so I need some way to track each one to identify
it when it completes, and also to cancel it if it runs too long.&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Microsoft's
general pattern for this is to use the &lt;strong&gt;stateData&lt;/strong&gt; parameter and have
the application pass in some unique value to identify the request. &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;This
is an ok way to do it, but it puts several restrictions on our implementation:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;1)
The state data must be supplied&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;2)
The state data must be unique for each operation&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;In
addition, there's the possibility of a race condition if I re-use the state data after
canceling an operation. So, to avoid all of these issues, I have the component return
the task identifier as part of the request - this is the &lt;strong&gt;object&lt;/strong&gt; return
value coming back from &lt;strong&gt;CalculatePi&lt;/strong&gt;. I can then use that object to
identify the results, and I can pass it into the component's &lt;strong&gt;CancelAsync&lt;/strong&gt; method
to cancel a pending request.&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;So,
how do I get my results? Through a delegate callback of course! I need to create a
delegate signature that uses it. The general EventHandler callback signature is: &lt;strong&gt;void
Method(object sender, EventArgs e) &lt;/strong&gt;so, we'll use a derivative of this as
our delegate:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; 
&lt;p&gt;
&lt;font size=2&gt;&lt;font color=#0000ff&gt;public&lt;/font&gt; &lt;font color=#0000ff&gt;delegate&lt;/font&gt; &lt;font color=#0000ff&gt;void&lt;/font&gt; &lt;font color=#008080&gt;PiCalculationCompletedEventHandler&lt;/font&gt;(&lt;font color=#0000ff&gt;object&lt;/font&gt; sender, &lt;font color=#008080&gt;PiCalculationEventArgs&lt;/font&gt; e);&lt;/font&gt;
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Then
we'll create the class which will be used to report the results. The class is pretty
simple - just a data holder really:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/font&gt;&lt;font size=2&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;class&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;PiCalculationEventArgs&lt;/font&gt;&lt;font size=2&gt; : &lt;/font&gt;&lt;font color=#008080 size=2&gt;EventArgs&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; _digits;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; _value;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;bool&lt;/font&gt;&lt;font size=2&gt; _canceled;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; _stateData;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; _taskId;&lt;br&gt;
&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; TaskId&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; get&lt;/font&gt;&lt;font size=2&gt; { &lt;/font&gt;&lt;font color=#0000ff size=2&gt;return&lt;/font&gt;&lt;font size=2&gt; _taskId;
}&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt; }
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; State&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; get&lt;/font&gt;&lt;font size=2&gt; { &lt;/font&gt;&lt;font color=#0000ff size=2&gt;return&lt;/font&gt;&lt;font size=2&gt; _stateData;
}&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt; }&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;bool&lt;/font&gt;&lt;font size=2&gt; Canceled&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; get&lt;/font&gt;&lt;font size=2&gt; { &lt;/font&gt;&lt;font color=#0000ff size=2&gt;return&lt;/font&gt;&lt;font size=2&gt; _canceled;
}&lt;br&gt;
}&lt;/font&gt;&lt;font size=2&gt;&gt;
&lt;/font&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; Digits&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;get&lt;/font&gt;&lt;font size=2&gt; { &lt;/font&gt;&lt;font color=#0000ff size=2&gt;return&lt;/font&gt;&lt;font size=2&gt; _digits;
}&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;}&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; Result&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; get&lt;/font&gt;&lt;font size=2&gt; { &lt;/font&gt;&lt;font color=#0000ff size=2&gt;return&lt;/font&gt;&lt;font size=2&gt; _value;
}&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt; }&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; internal&lt;/font&gt;&lt;font size=2&gt; PiCalculationEventArgs(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; taskId, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; digits, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; value, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; stateData, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;bool&lt;/font&gt;&lt;font size=2&gt; canceled)&lt;br&gt;
{&lt;br&gt;
_digits = digits;&lt;br&gt;
_value = value;&lt;br&gt;
_canceled = canceled;&lt;br&gt;
_stateData = stateData;&lt;br&gt;
_taskId = taskId;&lt;br&gt;
}&lt;br&gt;
}&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Now
we can implement out component. First, we'll add a &lt;em&gt;Completed&lt;/em&gt; event:&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;event&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;PiCalculationCompletedEventHandler&lt;/font&gt;&lt;font size=2&gt; CalculationComplete;&lt;/font&gt;&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;font size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;This
will be used by the application to hook into the results of our component's calculation.
The next part is the key to all of this - &lt;strong&gt;AsyncOperation&lt;/strong&gt;. The &lt;strong&gt;AsyncOperation&lt;/strong&gt; class
is new to 2.0 and provides the facility to perform callbacks on the appropriate thread.
Essentially, it acts as a callback mediator - detecting the type of thread it was
created on and then providing the appropriate marshaling code for it's internal delegate.
You utilize the callback through a new delegate type -- &lt;strong&gt;SendOrPostCallback&lt;/strong&gt;.
We tie our callback to this delegate type and it will marshal us to the correct threading
model. We can then execute our own internal &lt;strong&gt;CalculationComplete&lt;/strong&gt; event.
Here's the basic skeleton: First, we will create an internal contained class which
will be used to track the request. This will actually be the object type we return
from the &lt;strong&gt;CalculatePi&lt;/strong&gt; method:&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font face=Verdana color=#003300 size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
class
&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncStateData&lt;/font&gt;&lt;font size=2&gt; 
&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncOperation&lt;/font&gt;&lt;font size=2&gt; asyncOperation;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;volatile&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;bool&lt;/font&gt;&lt;font size=2&gt; canceled
= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font size=2&gt;;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;volatile&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;bool&lt;/font&gt;&lt;font size=2&gt; running
= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;true&lt;/font&gt;&lt;font size=2&gt;;&lt;br&gt;
&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font color=#0000ff size=2&gt; public&lt;/font&gt;&lt;font size=2&gt; AsyncStateData(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; stateData) 
&lt;br&gt;
{ 
&lt;br&gt;
asyncOperation = &lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncOperationManager&lt;/font&gt;&lt;font size=2&gt;.CreateOperation(stateData); 
&lt;br&gt;
}&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;&lt;font face=Verdana color=#003300&gt;Notice the call to &lt;strong&gt;AsyncOperationManager.CreateOperation&lt;/strong&gt;?
This is where we create our &lt;strong&gt;AsyncOperation&lt;/strong&gt; class and this factory
creator is the context detector. We will have an &lt;strong&gt;AsyncOperation&lt;/strong&gt; for
each event we intend to fire back into the client - in our case one for each Pi calculation.
But, I could also create a single instance for the client as well - this is actually
what is done in the ITapi3 component to allow it to be integrated onto a Windows Form
even though events are being received on a background thread. The Tapi events are
always fired on the appropriate thread - the background one for non-WinForms apps
and the UI thread for WinForms apps.&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;&lt;font face=Verdana color=#003300&gt;Next, we will create our internal callback
- this is the callback that will actually be fired internally and then call the real
application event, so we'll hook that up with an anonymous delegate in the constructor
of our component:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font size=2&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;SendOrPostCallback&lt;/font&gt;&lt;font size=2&gt; completionMethodDelegate;&gt;
&lt;/font&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; PiCalculator()&lt;br&gt;
{&lt;br&gt;
completionMethodDelegate = &lt;/font&gt;&lt;font color=#0000ff size=2&gt;delegate&lt;/font&gt;&lt;font size=2&gt;(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; evt)&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#008000 size=2&gt;// Called on the synchronization thread.&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (CalculationComplete != &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt;)&lt;br&gt;
CalculationComplete(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;this&lt;/font&gt;&lt;font size=2&gt;, (&lt;/font&gt;&lt;font color=#008080 size=2&gt;PiCalculationEventArgs&lt;/font&gt;&lt;font size=2&gt;)evt);&lt;br&gt;
};&lt;br&gt;
}&gt;
&lt;p&gt;
&lt;font face=Verdana color=#003300&gt;Now, let's implement our CalculatePi method - it's
pretty simple, we'll use an asynch delegate to our internal calculator, invoke it
and return the &lt;strong&gt;AsyncStateData &lt;/strong&gt;structure we create to identify each
task submitted to the component. Then the calculation will be performed on a thread
pool thread and we'll callback to the client when it is finished.&lt;/font&gt;
&lt;/font&gt;&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; CalculatePi(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; digits, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; stateData)&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt; PiDelegate&lt;/font&gt;&lt;font size=2&gt; piDel = InternalCalculatePi;&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncStateData&lt;/font&gt;&lt;font size=2&gt; asyncData = &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncStateData&lt;/font&gt;&lt;font size=2&gt;(stateData);&lt;br&gt;
piDel.BeginInvoke(digits, asyncData, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;delegate&lt;/font&gt;&lt;font size=2&gt;(&lt;/font&gt;&lt;font color=#008080 size=2&gt;IAsyncResult&lt;/font&gt;&lt;font size=2&gt; ar)
{ piDel.EndInvoke(ar); }, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt;);&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;return&lt;/font&gt;&lt;font size=2&gt; asyncData;&lt;br&gt;
}&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=2&gt;&lt;font color=#003300&gt;&lt;font face=Verdana&gt;CancelAsync is pretty simple too
-- it will simply set the &lt;strong&gt;Canceled &lt;/strong&gt;flag of the request:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;public&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;font size=2&gt; CancelAsync(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; asyncTask)&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncStateData&lt;/font&gt;&lt;font size=2&gt; asyncData = asyncTask &lt;/font&gt;&lt;font color=#0000ff size=2&gt;as&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncStateData&lt;/font&gt;&lt;font size=2&gt;;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (asyncData != &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt; &amp;&amp;
asyncData.running == &lt;/font&gt;&lt;font color=#0000ff size=2&gt;true&lt;/font&gt;&lt;font size=2&gt;)&lt;br&gt;
asyncData.canceled = &lt;/font&gt;&lt;font color=#0000ff size=2&gt;true&lt;/font&gt;&lt;font size=2&gt;;&lt;br&gt;
}&gt;
&lt;p&gt;
&lt;font size=2&gt;&lt;font color=#003300&gt;&lt;font face=Verdana&gt;Now, we need to implement our
PiCalculator. We're going to cheese out here and just "pretend" to calculate Pi since
that wasn't really the point of this component :-) We'll define a delegate to use
for the asynch execution and then implement our function:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&lt;/font&gt; 
&lt;p&gt;
&lt;font color=#0000ff size=2&gt;private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;delegate&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;PiDelegate&lt;/font&gt;&lt;font size=2&gt;(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; digits, &lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncStateData&lt;/font&gt;&lt;font size=2&gt; asyncData);&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;private&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;font size=2&gt; InternalCalculatePi(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; digits, &lt;/font&gt;&lt;font color=#008080 size=2&gt;AsyncStateData&lt;/font&gt;&lt;font size=2&gt; asyncData)&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; string&lt;/font&gt;&lt;font size=2&gt; PI_DIGITS = &lt;/font&gt;&lt;font color=#800000 size=2&gt;"3.141592637309238932482438234724782347234"&lt;/font&gt;&lt;font size=2&gt;;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (digits &gt; PI_DIGITS.Length
- 2)&lt;br&gt;
digits = PI_DIGITS.Length - 2;&lt;br&gt;
&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font color=#008000 size=2&gt; // This would be a real calculator here..&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;int&lt;/font&gt;&lt;font size=2&gt; completedDigits = 0;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;for&lt;/font&gt;&lt;font size=2&gt;&lt; digits; completedDigits++)&lt;BR&gt; (;
!asyncData.canceled &amp;&amp; completedDigits {&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt;Thread&lt;/font&gt;&lt;font size=2&gt;.Sleep(1000);&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
asyncData.running = 
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font size=2&gt;;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; data = PI_DIGITS.Substring(0,
completedDigits + 2);&lt;br&gt;
asyncData.asyncOperation.PostOperationCompleted(&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;completionMethodDelegate,&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;PiCalculationEventArgs&lt;/font&gt;&lt;font size=2&gt;(asyncData,
digits, data, asyncData.asyncOperation.UserSuppliedState, asyncData.canceled));&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;}&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font face=Verdana color=#003300&gt;The key to the callback is the invocation of the &lt;strong&gt;PostOperationCompleted&lt;/strong&gt; method
from the &lt;strong&gt;AsyncOperation&lt;/strong&gt; instance we created. It is what calls our
handler which will in turn call the client. Once &lt;strong&gt;PostOperationCompleted&lt;/strong&gt; is
called, no further work may be done with the &lt;strong&gt;AsyncOperation&lt;/strong&gt;. So,
it's not appropriate for progress reporting - instead you can use &lt;strong&gt;PostOperateration&lt;/strong&gt; for
that which allows for multiple calls. &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Verdana color=#003300&gt;Now, when using this component, we can simply call
it as expected:&lt;/font&gt;
&lt;/p&gt;
&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
static
&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;font size=2&gt; Main(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt;[]
args)&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt; ArrayList&lt;/font&gt;&lt;font size=2&gt; taskIds = &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;ArrayList&lt;/font&gt;&lt;font size=2&gt;();&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt; PiCalculator&lt;/font&gt;&lt;font size=2&gt; piCalc = &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;PiCalculator&lt;/font&gt;&lt;font size=2&gt;();&lt;br&gt;
piCalc.CalculationComplete += &lt;/font&gt;&lt;font color=#0000ff size=2&gt;delegate&lt;/font&gt;&lt;font size=2&gt;(&lt;font color=#0000ff&gt;object&lt;/font&gt; sender, &lt;font color=#008080&gt;PiCalculationEventArgs&lt;/font&gt;&lt;font size=2&gt; e&lt;/font&gt;)&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#008080 size=2&gt; Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"[{0}]
{1} = {2}, Canceled = {3}"&lt;/font&gt;&lt;font size=2&gt;, 
&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt;Thread&lt;/font&gt;&lt;font size=2&gt;.CurrentThread.ManagedThreadId,
e.Digits, e.Result, e.Canceled);&lt;br&gt;
&lt;/font&gt;&lt;/font&gt; }&lt;font size=2&gt; 
&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt; s &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;font size=2&gt; args)&lt;br&gt;
{&lt;br&gt;
taskIds.Add(piCalc.CalculatePi(&lt;/font&gt;&lt;font color=#008080 size=2&gt;Convert&lt;/font&gt;&lt;font size=2&gt;.ToInt32(s),
s));&lt;br&gt;
}&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt; Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Waiting
for results .. press ENTER to cancel."&lt;/font&gt;&lt;font size=2&gt;);&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.ReadLine();&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; task &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;font size=2&gt; taskIds)&lt;br&gt;
{&lt;br&gt;
piCalc.CancelAsync(task);&lt;br&gt;
}&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt; Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Press
ENTER to terminate"&lt;/font&gt;&lt;font size=2&gt;);&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.ReadLine();&lt;br&gt;
}&lt;/font&gt;&gt;
&lt;font size=2&gt;&lt;font color=#0000ff&gt; 
&lt;p&gt;
&lt;font face=Verdana color=#003300&gt;Here's the output:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Waiting for results .. press ENTER to cancel.&lt;br&gt;
[3] 10 = 3.1415926373, Canceled = False&lt;br&gt;
[4] 11 = 3.14159263730, Canceled = False&lt;br&gt;
[5] 14 = 3.14159263730923, Canceled = False&lt;br&gt;
[5] 15 = 3.141592637309238, Canceled = False&lt;br&gt;
[5] 17 = 3.14159263730923893, Canceled = False
&lt;/p&gt;
&lt;p&gt;
Press ENTER to terminate&lt;br&gt;
[5] 20 = 3.1415926373092389324, Canceled = True
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Verdana color=#003300&gt;Not real exciting right? Notice the thread id in
the [brackets] is different for some of the callbacks. This indicates we are getting
called back on different threads - certainly not the main thread which is waiting
for console input. The cool part of this component is that &lt;em&gt;I can use it exactly
the same way in a Windows Forms application!&lt;/em&gt; So, I don't have to &lt;em&gt;know&lt;/em&gt; that
the callback is on a different thread! I don't have to worry about doing a &lt;strong&gt;BeginInvoke&lt;/strong&gt; or &lt;strong&gt;Invoke&lt;/strong&gt; to
get back to the UI thread. So, here's an example WinForm application:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;/font&gt;&lt;/span&gt;&gt;&gt;&gt;&gt;&gt;&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;public&lt;/span&gt; partial &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; CalcPiTestForm
: Form&lt;br&gt;
{&lt;br&gt;
ArrayList _pendingTasks &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; ArrayList();&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; public&lt;/span&gt; CalcPiTestForm()&lt;br&gt;
{&lt;br&gt;
InitializeComponent();&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; CalcPiTestForm_Load(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
EventArgs e)&lt;br&gt;
{&lt;br&gt;
piCalculator1.CalculationComplete += &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; UserMath.PiCalculationCompletedEventHandler(piCalculator1_CalculationComplete);&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; void&lt;/span&gt; piCalculator1_CalculationComplete(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
UserMath.PiCalculationEventArgs e)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; lock&lt;/span&gt;(_pendingTasks)&lt;br&gt;
{&lt;br&gt;
_pendingTasks.Remove(e.TaskId);&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; //
No need to do BeginInvoke here!!&lt;/span&gt;
&lt;br&gt;
listBox1.Items.Add(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt;.Format(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"[{0}]
{1} = {2}, Canceled = {3}"&lt;/span&gt;,&lt;br&gt;
System.Threading.Thread.CurrentThread.ManagedThreadId, e.Digits, e.Result, e.Canceled));&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; btnCalculate_Click(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
EventArgs e)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; if&lt;/span&gt; (maskedTextBox1.Text.Length
&gt; 0)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; lock&lt;/span&gt;(_pendingTasks)&lt;br&gt;
_pendingTasks.Add(piCalculator1.CalculatePi(Convert.ToInt32(maskedTextBox1.Text)));&lt;br&gt;
}&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; btnCancel_Click(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
EventArgs e)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; lock&lt;/span&gt;(_pendingTasks)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; foreach&lt;/span&gt; (&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; task &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;in&lt;/span&gt; _pendingTasks)&lt;br&gt;
piCalculator1.CancelAsync(task);&lt;br&gt;
}&lt;br&gt;
}&lt;br&gt;
}&lt;/span&gt;&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;/span&gt; 
&lt;/p&gt;
&lt;img border="0" src="http://www.julmar.com/blog/mark/content/binary/untitled.bmp"&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Notice
the output here -- we haven't done anything special with the component's callbacks,
but now the callback is &lt;em&gt;always&lt;/em&gt; on thread [1]. This is the magic of &lt;strong&gt;AsyncOperation&lt;/strong&gt; and
synchronization contexts. Now go out there and write some thread-aware components!
If you'd like this entire sample, here is the project: &lt;a href="http://www.julmar.com/samples/asyncop.zip"&gt;http://www.julmar.com/samples/asyncop.zip&lt;/a&gt;&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,78805871-cb7b-4ea4-9be8-a8a1d61a15d8.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=1c54dd41-4f8d-43ed-9683-ec790c169346</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,1c54dd41-4f8d-43ed-9683-ec790c169346.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,1c54dd41-4f8d-43ed-9683-ec790c169346.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=1c54dd41-4f8d-43ed-9683-ec790c169346</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I love anonymous delegates - I think they are extremely useful and allow me to solve
some problems in very elegant ways.  However, once you really get into them,
you start to see the dark side of anonymous delegates and that is unregistration.
</p>
        <p>
Here's the basic problem: when binding an instance delegate to an event to handle
some activity, the delegate will cache off the instance reference - thereby keeping
the reference alive.  So for example, if I had a form which wanted to process
some activity from an object:
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">class</span> Publisher<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   public</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">event</span> EventHandler
OnEvent;<br />
   ...<br />
}<br /></span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">class</span> MainForm
: Form<br />
{<br />
   Publisher _pub = new Publisher();</span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <br />
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   void</span> ActivateChildForm() <br />
   {<br />
      ChildForm f = new ChildForm(_pub);<br />
      f.Show();<br /></span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   }<br />
}<br /></span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">class</span> ChildForm
: Form<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   public</span> ChildForm(Publisher
pub) <br />
   {<br />
      pub.OnEvent += ProcessEvent;<br />
   }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   void</span> ProcessEvent(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">object</span> sender,
EventArgs e)<br />
   {<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"><font color="#000000">      listBox1.Items.Add("Event
was fired!");</font>      </span><br />
   }<br />
}</span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="2">When
the ChildForm instance is closed, the form won't be collected because the Publisher
(_pub) is holding a reference to it.  This is easily fixed by adding some code
into the FormClosing event:</font>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">class</span> ChildForm
: Form<br />
{<br /></span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   Publisher
_pub;<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   public</span> ChildForm(Publisher
pub)<br />
   {<br />
      _pub <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> pub;<br />
      _pub.OnEvent += ProcessEvent;<br />
   }<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   void</span> FormClosing(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">object</span> sender,
FormClosingEventArgs e)<br />
   {<br />
      _pub.OnEvent -= ProcessEvent; <br />
   }<br />
}</span>
          </span>
        </p>
        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          </span>
        </span>
        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          <p>
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">Now,
the form will be cleaned up when it's closed.  This is pretty standard stuff,
and most people that have been using .NET for a while know all this.  Here's
the rub: with .NET 2.0, we can simplify the code using anonymous delegates which are
really helpful for these single-line processing event handling functions.  So,
I could recode my handler as:</font>
            </span>
          </p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="2">
              <p>
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">class</span> ChildForm
: Form<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   public</span> ChildForm(Publisher
pub) <br />
   {<br />
      pub.OnEvent += delegate { listBox1.Items.Add("Event
was fired!"); }<br />
      this.OnClosing += delegate { pub.OnEvent -= <strong><font face="Arial" color="#ff0000">?????</font></strong> }</span>
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <br />
   }<br />
}</span>
              </p>
              <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                <p>
                  <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                    <font face="Verdana" color="#003300" size="2">The
issue is that I don't have a reference to the delegate as it's typed.  Under
the covers, the C# compiler has generated a temporary function (or possibly even pulled
it out to a separate inner class) and there's no way for me to get to the underlying
function.  So, what can I do?  Well, the easiest thing to do is to save
off the function:</font>
                  </span>
                </p>
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font face="Verdana" color="#003300" size="2">
                    <p>
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">class</span> ChildForm
: Form<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   public</span> ChildForm(Publisher
pub) <br />
   {<br /></span>
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">      EventHandler
eh = delegate { listBox1.Items.Add("Event was fired!"); }<br />
       <br />
      pub.OnEvent += eh;       
<br />
      </span>
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">this.OnClosing
+= delegate { pub.OnEvent -= eh; }</span>
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <br />
   }<br />
}</span>
                    </p>
                    <p>
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                          <font face="Verdana" color="#003300" size="2">Now
my code will function properly -- and is significantly reduced in size. 
Of course, I've lost the benefit of being able to hook up events through VS.NET because
it always generates seperate functions and I would need to cache off the Publisher
instance as well as my delegate in that case. </font>
                        </span>
                      </span>
                    </p>
                    <p>
                      <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                          <font face="Verdana" color="#003300" size="2">So,
rule #1, always unregister the event when you are finished.  Rule #2, remember
that anonymous delegates may be keep your instance alive so unregister them as well, <em>unless</em> the
event is to be hooked up throughout the lifetime of the application.</font>
                        </span>
                      </span>
                    </p>
                  </font>
                </span>
              </span>
            </font>
          </span>
        </span>
      </body>
      <title>Remember to unregister your anonymous delegate!</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,1c54dd41-4f8d-43ed-9683-ec790c169346.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/17/RememberToUnregisterYourAnonymousDelegate.aspx</link>
      <pubDate>Fri, 17 Mar 2006 16:56:40 GMT</pubDate>
      <description>&lt;p&gt;
I love anonymous delegates - I think they are extremely useful and allow me to solve
some problems in very elegant ways.&amp;nbsp; However, once you really get into them,
you start to see the dark side of anonymous delegates and that is unregistration.
&lt;/p&gt;
&lt;p&gt;
Here's the basic problem: when binding an instance delegate to an event to&amp;nbsp;handle
some&amp;nbsp;activity, the delegate will cache off the instance reference - thereby keeping
the reference alive.&amp;nbsp; So for example, if I had a form which wanted to process
some activity from an object:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; Publisher&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;event&lt;/span&gt; EventHandler
OnEvent;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br&gt;
}&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; MainForm
: Form&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;Publisher&amp;nbsp;_pub = new Publisher();&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&lt;/span&gt; ActivateChildForm()&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChildForm f = new ChildForm(_pub);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.Show();&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;
&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; ChildForm
: Form&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&lt;/span&gt; ChildForm(Publisher
pub)&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pub.OnEvent += ProcessEvent;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&lt;/span&gt; ProcessEvent(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
EventArgs e)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;listBox1.Items.Add("Event
was&amp;nbsp;fired!");&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;When
the ChildForm instance is closed, the form won't be collected because the Publisher
(_pub) is holding a reference to it.&amp;nbsp; This is easily fixed by adding some code
into the FormClosing event:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; ChildForm
: Form&lt;br&gt;
{&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Publisher
_pub;&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&lt;/span&gt; ChildForm(Publisher
pub)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_pub &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; pub;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_pub.OnEvent += ProcessEvent;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&lt;/span&gt; FormClosing(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
FormClosingEventArgs e)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_pub.OnEvent -= ProcessEvent;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Now,
the form will be cleaned up when it's closed.&amp;nbsp; This is pretty standard stuff,
and most people that have been using .NET for a while know all this.&amp;nbsp; Here's
the rub: with .NET 2.0, we can simplify the code using anonymous delegates which are
really helpful for these single-line processing event handling functions.&amp;nbsp; So,
I could recode my handler as:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; ChildForm
: Form&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&lt;/span&gt; ChildForm(Publisher
pub)&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pub.OnEvent +=&amp;nbsp;delegate { listBox1.Items.Add("Event
was&amp;nbsp;fired!"); }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.OnClosing += delegate { pub.OnEvent -= &lt;strong&gt;&lt;font face=Arial color=#ff0000&gt;?????&lt;/font&gt;&lt;/strong&gt; }&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;The
issue is that I don't have a reference to the delegate as it's typed.&amp;nbsp; Under
the covers, the C# compiler has generated a temporary function (or possibly even pulled
it out to&amp;nbsp;a separate inner class) and there's no way for me to get to the underlying
function.&amp;nbsp; So, what can I do?&amp;nbsp; Well, the easiest thing to do is to save
off the function:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;class&lt;/span&gt; ChildForm
: Form&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&lt;/span&gt; ChildForm(Publisher
pub)&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EventHandler
eh = delegate { listBox1.Items.Add("Event was&amp;nbsp;fired!"); }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pub.OnEvent += eh;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;this.OnClosing
+= delegate { pub.OnEvent -= eh;&amp;nbsp;}&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Now
my code will&amp;nbsp;function properly -- and is significantly reduced in size.&amp;nbsp;
Of course, I've lost the benefit of being able to hook up events through VS.NET&amp;nbsp;because
it always generates seperate functions and I would need to cache off the Publisher
instance as&amp;nbsp;well as&amp;nbsp;my delegate in that case.&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;So,
rule #1, always unregister the event when you are finished.&amp;nbsp; Rule #2, remember
that anonymous delegates may be keep your instance alive so unregister them as well, &lt;em&gt;unless&lt;/em&gt; the
event is to be hooked up throughout the lifetime of the application.&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,1c54dd41-4f8d-43ed-9683-ec790c169346.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=7513eebc-2aed-4ff4-a1db-744ded447cc3</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,7513eebc-2aed-4ff4-a1db-744ded447cc3.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,7513eebc-2aed-4ff4-a1db-744ded447cc3.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=7513eebc-2aed-4ff4-a1db-744ded447cc3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've posted a new version of ATAPI.NET which supports consultation transfers and a
simple phone sample that shows off how to use the features.  In addtiion, this
version of ATAPI.NET has a couple of bug fixes that were rolled in from a production
project over the past couple of weeks to fix some weird startup/shutdown issues when
a LINE_REINIT is reported by TAPI.  You can get the new code from our samples
link -- <a href="http://www.julmar.com/samples.htm">http://www.julmar.com/samples.htm</a></p>
        <p>
 
</p>
      </body>
      <title>Updated ATAPI samples and assembly</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,7513eebc-2aed-4ff4-a1db-744ded447cc3.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/17/UpdatedATAPISamplesAndAssembly.aspx</link>
      <pubDate>Fri, 17 Mar 2006 15:59:23 GMT</pubDate>
      <description>&lt;p&gt;
I've posted a new version of ATAPI.NET which supports consultation transfers and a
simple phone sample that shows off how to use the features.&amp;nbsp; In addtiion, this
version of ATAPI.NET has a couple of bug fixes that were rolled in from a production
project over the past couple of weeks to fix some weird startup/shutdown issues when
a LINE_REINIT is reported by TAPI.&amp;nbsp; You can get the new code from our samples
link -- &lt;a href="http://www.julmar.com/samples.htm"&gt;http://www.julmar.com/samples.htm&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,7513eebc-2aed-4ff4-a1db-744ded447cc3.aspx</comments>
      <category>Code</category>
      <category>Tapi</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=e1ebbee2-20ed-4541-af2c-417d4dea110e</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,e1ebbee2-20ed-4541-af2c-417d4dea110e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,e1ebbee2-20ed-4541-af2c-417d4dea110e.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=e1ebbee2-20ed-4541-af2c-417d4dea110e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Forwarding lines with ATAPI.NET is simple and easy (assuming, of course, that the
underlying TSP supports it).
</p>
        <p>
The first step is knowing whether a given line device even <em>supports</em> forwarding. 
This is trivial:
</p>
        <font color="#008080" size="2">
          <p>
            <font face="Courier New">TapiManager</font>
          </p>
        </font>
        <font face="Courier New">
          <font color="#000000" size="2"> mgr = </font>
          <font color="#0000ff" size="2">new</font>
          <font color="#000000" size="2">
          </font>
          <font color="#008080" size="2">TapiManager</font>
          <font color="#000000" size="2">(</font>
          <font color="#800000" size="2">"ForwardingTest"</font>
          <font size="2">
            <font color="#000000">);</font>
          </font>
        </font>
        <font size="2">
          <p>
          </p>
        </font>
        <font face="Courier New">
          <font color="#0000ff" size="2">foreach</font>
          <font size="2"> (</font>
          <font color="#008080" size="2">TapiLine</font>
          <font size="2"> line </font>
          <font color="#0000ff" size="2">in</font>
        </font>
        <font face="Courier New">
          <font size="2"> mgr.Lines)<br />
{<br />
   </font>
          <font color="#0000ff" size="2">if</font>
        </font>
        <font size="2">
          <font face="Courier New"> (line.Capabilities.SupportsForwarding)<br />
   {<br />
      <font color="#008080" size="2">Console</font><font size="2">.WriteLine(</font><font color="#800000" size="2">"Line
{0} supports forwarding!"</font></font>
          <font face="Courier New">
            <font size="2">, line.Name);<br /></font>   }<br />
}</font>
        </font>
        <p>
          <font size="2">Once we've identified a specific line, we can look at each address
and get more information such as the <em>types</em> of forwarding supported. 
For example, we might be able to forward to different numbers based on specific conditions
such as whether the call goes unanswered vs. whether the address is in use and returning
a busy signal.  We might also be able to forward specific inbound callers (very
useful to get rid of your bosses calls).  We can get this information from the <strong>Capabilities</strong> of
the <strong>TapiAddress</strong> object:
</font>
        </p>
        <p>
          <font face="Courier New">
            <font color="#0000ff" size="2">foreach</font>
            <font size="2"> (</font>
            <font color="#008080" size="2">TapiAddress</font>
            <font size="2"> addr </font>
            <font color="#0000ff" size="2">in</font>
          </font>
          <font face="Courier New">
            <font size="2"> line.Addresses)<br />
{<br />
   </font>
            <font color="#008080" size="2">Console</font>
            <font size="2">.WriteLine(</font>
            <font color="#800000" size="2">"Forwarding
modes supported on {0} are {1}"</font>
          </font>
          <font face="Courier New" size="2">,
addr.Address, addr.Capabilities.SupportedForwardingModes);<br /></font>
          <font size="2">
            <font face="Courier New">}</font>
          </font>
        </p>
        <p>
We can also retrieve any existing forwarding information through the <strong>Status</strong> of
the <strong>TapiAddress</strong>:
</p>
        <p>
          <font face="Courier New">
            <font color="#0000ff" size="2">foreach</font>
            <font size="2"> (</font>
            <font color="#008080" size="2">ForwardInfo</font>
            <font size="2"> fwd </font>
            <font color="#0000ff" size="2">in</font>
          </font>
          <font face="Courier New">
            <font size="2"> addr.Status.ForwardingInformatioin)<br />
   </font>
            <font color="#008080" size="2">Console</font>
            <font size="2">.WriteLine(</font>
            <font color="#800000" size="2">"\t{0}
to {1}:{2}"</font>
          </font>
          <font size="2">
            <font face="Courier New">, fwd.ForwardMode,
fwd.DestinationAddressType, fwd.DestinationAddress);</font>
          </font>
        </p>
        <p>
This outputs: "Unconditional to PhoneNumber:1234" on a forwarded line I setup.
</p>
        <p>
Finally, the big question is how to change the forwarding information, this is pretty
easy as well.  You can set forwarding information on two levels, the entire line
(which impacts all addresses), or a specific address.  This is done through two
methods present on both <strong>TapiAddress</strong> and <strong>TapiLine </strong>which
are <strong>Forward </strong>and <strong>CancelForward</strong>.  So, to cancel
all forwarding in effect on every line we could do the following:
</p>
        <font size="2">
          <p>
          </p>
        </font>
        <font face="Courier New">
          <font color="#008080" size="2">Console</font>
          <font size="2">.WriteLine(</font>
          <font color="#800000" size="2">"Canceling
all forwards:"</font>
        </font>
        <font face="Courier New">
          <font size="2">);<br /></font>
          <font color="#0000ff" size="2">foreach</font>
          <font size="2"> (</font>
          <font color="#008080" size="2">TapiLine</font>
          <font size="2"> line </font>
          <font color="#0000ff" size="2">in</font>
        </font>
        <font face="Courier New">
          <font size="2"> mgr.Lines)<br />
{<br />
   </font>
          <font color="#0000ff" size="2">if</font>
        </font>
        <font face="Courier New" size="2"> (line.Capabilities.SupportsForwarding)<br />
   {<br />
      </font>
        <font face="Courier New" color="#0000ff" size="2">try<br />
      </font>
        <font face="Courier New">
          <font size="2">{<br />
         line.CancelForward();<br />
      }<br />
      </font>
          <font color="#0000ff" size="2">catch</font>
          <font size="2"> (</font>
          <font color="#008080" size="2">TapiException</font>
        </font>
        <font face="Courier New">
          <font size="2"> ex)<br />
      {<br />
         </font>
          <font color="#008080" size="2">Console</font>
          <font size="2">.WriteLine(</font>
          <font color="#800000" size="2">"{0}
- {1}"</font>
        </font>
        <font size="2">
          <font face="Courier New">, line, ex.Message);<br />
      }<br />
   }<br />
}</font>
          <p>
Or, to setup the forwarding as above, I can issue a call to the <strong>Forward</strong> method:
</p>
          <font size="2">
            <p>
            </p>
          </font>
          <font face="Courier New">
            <font color="#008080" size="2">ForwardInfo</font>
            <font size="2">[]
fwdInfo = </font>
            <font color="#0000ff" size="2">new</font>
            <font size="2">
            </font>
            <font color="#008080" size="2">ForwardInfo</font>
          </font>
          <font face="Courier New">
            <font size="2">[]
{<br />
      </font>
            <font color="#0000ff" size="2">new</font>
            <font size="2">
            </font>
            <font color="#008080" size="2">ForwardInfo</font>
            <font size="2">(</font>
            <font color="#008080" size="2">ForwardingMode</font>
            <font size="2">.Unconditional,
0, </font>
            <font color="#800000" size="2">"1234"</font>
          </font>
          <font size="2">
            <font face="Courier New">)<br />
};</font>
            <p>
            </p>
          </font>
          <font face="Courier New">
            <font color="#0000ff" size="2">foreach</font>
            <font size="2"> (</font>
            <font color="#008080" size="2">TapiLine</font>
            <font size="2"> line </font>
            <font color="#0000ff" size="2">in</font>
          </font>
          <font face="Courier New">
            <font size="2"> mgr.Lines)<br />
{<br />
   </font>
            <font color="#0000ff" size="2">if</font>
          </font>
          <font face="Courier New" size="2"> (line.Capabilities.SupportsForwarding)<br />
   {<br />
      </font>
          <font face="Courier New" color="#0000ff" size="2">try<br />
      </font>
          <font face="Courier New">
            <font size="2">{<br />
         line.Forward(fwdInfo, 5, </font>
            <font color="#0000ff" size="2">null</font>
          </font>
          <font face="Courier New">
            <font size="2">);<br />
      }<br />
      </font>
            <font color="#0000ff" size="2">catch</font>
            <font size="2"> (</font>
            <font color="#008080" size="2">TapiException</font>
          </font>
          <font face="Courier New">
            <font size="2"> ex)<br />
      {<br />
         </font>
            <font color="#008080" size="2">Console</font>
            <font size="2">.WriteLine(</font>
            <font color="#800000" size="2">"{0}
- {1}"</font>
          </font>
          <font size="2">
            <font face="Courier New">, line.Name, ex.Message);<br />
      }<br />
   }<br />
}</font>
            <p>
The <strong>ForwardInfo</strong> class describes a single forwarding instruction and
you pass an array of these info the <strong>Forward</strong> method to indicate how
things are to be managed.  Exceptions need to be handled because the TAPI service
provider might not allow the particular forwarding at this point in time, or the destination
might not be allowed, etc.
</p>
            <p>
Under the covers this will issue a <strong>lineForward</strong> request with a <strong>LINEFORWARDLIST</strong> setup
for each of the <strong>ForwardInfo</strong> structures.
</p>
            <p>
That about covers it!  Ping me with any questions if you want.
</p>
            <p>
 
</p>
          </font>
        </font>
      </body>
      <title>Fun with forwarding..</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,e1ebbee2-20ed-4541-af2c-417d4dea110e.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/15/FunWithForwarding.aspx</link>
      <pubDate>Wed, 15 Mar 2006 20:43:58 GMT</pubDate>
      <description>&lt;p&gt;
Forwarding lines with ATAPI.NET is simple and easy (assuming, of course, that the
underlying TSP supports it).
&lt;/p&gt;
&lt;p&gt;
The first step is knowing whether a given line device even &lt;em&gt;supports&lt;/em&gt; forwarding.&amp;nbsp;
This is trivial:
&lt;/p&gt;
&lt;font color=#008080 size=2&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;TapiManager&lt;/font&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#000000 size=2&gt; mgr = &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font color=#000000 size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiManager&lt;/font&gt;&lt;font color=#000000 size=2&gt;(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"ForwardingTest"&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;);&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiLine&lt;/font&gt;&lt;font size=2&gt; line &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; mgr.Lines)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt; (line.Capabilities.SupportsForwarding)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Line
{0} supports forwarding!"&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;, line.Name);&lt;br&gt;
&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/font&gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=2&gt;Once we've identified a specific line, we can look at each address and
get more information such as the &lt;em&gt;types&lt;/em&gt; of forwarding supported.&amp;nbsp; For
example, we might be able to forward to different numbers based on specific conditions
such as whether the call goes unanswered vs. whether the address is in use and returning
a busy signal.&amp;nbsp; We might also be able to forward specific inbound callers (very
useful to get rid of your bosses calls).&amp;nbsp; We can get this information from the &lt;strong&gt;Capabilities&lt;/strong&gt; of
the &lt;strong&gt;TapiAddress&lt;/strong&gt; object:
&lt;/p&gt;
&lt;p&gt;
&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiAddress&lt;/font&gt;&lt;font size=2&gt; addr &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; line.Addresses)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Forwarding
modes supported on&amp;nbsp;{0} are {1}"&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt;,
addr.Address, addr.Capabilities.SupportedForwardingModes);&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
We can also retrieve any existing forwarding information through the &lt;strong&gt;Status&lt;/strong&gt; of
the &lt;strong&gt;TapiAddress&lt;/strong&gt;:&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;ForwardInfo&lt;/font&gt;&lt;font size=2&gt; fwd &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; addr.Status.ForwardingInformatioin)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"\t{0}
to {1}:{2}"&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;, fwd.ForwardMode,
fwd.DestinationAddressType, fwd.DestinationAddress);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
This outputs: "Unconditional to PhoneNumber:1234" on a forwarded line I setup.
&lt;/p&gt;
&lt;p&gt;
Finally, the big question is how to change the forwarding information, this is pretty
easy as well.&amp;nbsp; You can set forwarding information on two levels, the entire line
(which impacts all addresses), or a specific address.&amp;nbsp; This is done through two
methods present on both &lt;strong&gt;TapiAddress&lt;/strong&gt; and &lt;strong&gt;TapiLine &lt;/strong&gt;which
are &lt;strong&gt;Forward &lt;/strong&gt;and &lt;strong&gt;CancelForward&lt;/strong&gt;.&amp;nbsp; So, to cancel
all forwarding in effect on every line we could do the following:
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Canceling
all forwards:"&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;);&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiLine&lt;/font&gt;&lt;font size=2&gt; line &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; mgr.Lines)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt; (line.Capabilities.SupportsForwarding)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font face="Courier New" color=#0000ff size=2&gt;try&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line.CancelForward();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;catch&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiException&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"{0}
- {1}"&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;, line, ex.Message);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/font&gt;&gt;
&lt;p&gt;
Or, to setup the forwarding as above, I can issue a call to the &lt;strong&gt;Forward&lt;/strong&gt; method:
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#008080 size=2&gt;ForwardInfo&lt;/font&gt;&lt;font size=2&gt;[]
fwdInfo = &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;ForwardInfo&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;[]
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;ForwardInfo&lt;/font&gt;&lt;font size=2&gt;(&lt;/font&gt;&lt;font color=#008080 size=2&gt;ForwardingMode&lt;/font&gt;&lt;font size=2&gt;.Unconditional,
0, &lt;/font&gt;&lt;font color=#800000 size=2&gt;"1234"&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;)&lt;br&gt;
};&lt;/font&gt;&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiLine&lt;/font&gt;&lt;font size=2&gt; line &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; mgr.Lines)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt; (line.Capabilities.SupportsForwarding)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font face="Courier New" color=#0000ff size=2&gt;try&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;line.Forward(fwdInfo, 5, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;catch&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiException&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"{0}
- {1}"&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;, line.Name, ex.Message);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/font&gt;&gt;
&lt;p&gt;
The &lt;strong&gt;ForwardInfo&lt;/strong&gt; class describes a single forwarding instruction and
you pass an array of these info the &lt;strong&gt;Forward&lt;/strong&gt; method to indicate how
things are to be managed.&amp;nbsp; Exceptions need to be handled because the TAPI service
provider might not allow the particular forwarding at this point in time, or the destination
might not be allowed, etc.
&lt;/p&gt;
&lt;p&gt;
Under the covers this will issue a &lt;strong&gt;lineForward&lt;/strong&gt; request with a &lt;strong&gt;LINEFORWARDLIST&lt;/strong&gt; setup
for each of the &lt;strong&gt;ForwardInfo&lt;/strong&gt; structures.
&lt;/p&gt;
&lt;p&gt;
That about covers it!&amp;nbsp; Ping me with any questions if you want.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;/font&gt;&lt;/font&gt;&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,e1ebbee2-20ed-4541-af2c-417d4dea110e.aspx</comments>
      <category>Code</category>
      <category>Tapi</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=f733e261-5d39-4ca1-be1a-c422f3cf1f1b</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,f733e261-5d39-4ca1-be1a-c422f3cf1f1b.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,f733e261-5d39-4ca1-be1a-c422f3cf1f1b.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=f733e261-5d39-4ca1-be1a-c422f3cf1f1b</wfw:commentRss>
      <title>Handling "Unhandled Exceptions" in .NET 2.0</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,f733e261-5d39-4ca1-be1a-c422f3cf1f1b.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/13/HandlingUnhandledExceptionsInNET20.aspx</link>
      <pubDate>Mon, 13 Mar 2006 18:07:55 GMT</pubDate>
      <description>&lt;p&gt;
I got hit with this problem from two separate clients last week - a .NET 1.1 application
ported to .NET 2.0 is now terminating abruptly for no apparent reason.&amp;nbsp; Well,
of course there's a reason - and it's that both applications had "hidden" exceptions
being thrown in some background thread that weren't being caught.&amp;nbsp; Under .NET
1.1, the CLR&amp;nbsp;would print any exceptions that occurred on threadpool threads to
the console and then return the thread to the pool.&amp;nbsp; In addition, the CLR would
silently eat any&amp;nbsp;exception thrown on the finalizer thread&amp;nbsp;(again printing
the stack trace to the console).&amp;nbsp; Under .NET 2.0, the behavior has changed and
it will cause the AppDomain to be unloaded (yikes!).&amp;nbsp; So, for example:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="COLOR: #0000cc; FONT-FAMILY: 'Courier New'"&gt;class&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&lt;font color=#008080&gt;BadClass&lt;/font&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;{&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;~&lt;font color=#008080&gt;BadClass&lt;/font&gt;()&lt;br&gt;
&amp;nbsp; {&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #0000cc; FONT-FAMILY: 'Courier New'"&gt;throw&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt; &lt;/span&gt;&lt;span style="COLOR: #0000cc; FONT-FAMILY: 'Courier New'"&gt;new&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt; Exception(&lt;/span&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'; mso-color-index: 3"&gt;"I'm
Bad"&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;);&amp;nbsp;&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;} &lt;/span&gt;
&lt;/p&gt;
&lt;div class=O v:shape="_x0000_s1026"&gt;
&lt;div&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style="COLOR: #0000cc; FONT-FAMILY: 'Courier New'"&gt;class&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt; &lt;font color=#008080&gt;BadClass&lt;/font&gt;
&lt;br&gt;
{ &lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #0000cc; FONT-FAMILY: 'Courier New'"&gt;static&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt; &lt;/span&gt;&lt;span style="COLOR: #0000cc; FONT-FAMILY: 'Courier New'"&gt;void&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt; Main()&lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp; {&lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;/span&gt;&lt;span style="COLOR: #0000cc; FONT-FAMILY: 'Courier New'"&gt;&lt;font face="Courier New" color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt; (;
;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;BadClass&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;();&lt;/font&gt;&lt;/font&gt;
&lt;/div&gt;
&gt; 
&lt;div&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;} &lt;/span&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;} &lt;/span&gt;
&lt;/div&gt;
&lt;div style="mso-line-spacing: '100 50 0'"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The above code&amp;nbsp;would run forever under CLR 1.1, but will terminate immediately
when run under CLR 2.0 with an unhandled exception.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;Unhandled Exception: System.Exception: I'm bad&lt;br&gt;
&amp;nbsp;&amp;nbsp; at BadClass.Finalize() in W:\Projects\TestApp\TestApp\Program.cs:line&amp;nbsp;11&lt;br&gt;
&lt;/font&gt;
&lt;br&gt;
There are a couple of ways to deal with this - the best is to do all your testing
and close the holes.&amp;nbsp; You really shouldn't have unhandled exceptions loose in
your program.&amp;nbsp; But for a really large program, or one where you don't know where
the exception is happening, Microsoft has given you a couple of options.&amp;nbsp; The
first one is the &lt;strong&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;&amp;lt;&lt;/font&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;legacyUnhandledExceptionPolicy&lt;font color=#0000ff&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR: fuchsia; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt; tag
which you can put into your &lt;strong&gt;app.config&lt;/strong&gt; file:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;/span&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'" &amp;lt;&lt;B&gt;configuration&gt;&lt;/span&gt;&lt;strong&gt;&lt;span&gt;&amp;gt;&amp;nbsp;&lt;br&gt;
&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;runtime&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span&gt;&amp;gt;&amp;nbsp;&lt;br&gt;
&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;legacyUnhandledExceptionPolicy&lt;/span&gt;&lt;span style="COLOR: fuchsia; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: red; FONT-FAMILY: 'Courier New'"&gt;enabled&lt;/span&gt;&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;="1"&lt;/span&gt;&lt;span style="COLOR: fuchsia; FONT-FAMILY: 'Courier New'"&gt; &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;/&amp;gt;&amp;nbsp;&lt;br&gt;
&lt;/span&gt;&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt; B&gt;&lt;/span&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;runtime&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;gt; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&lt; B&gt;&lt;/span&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;lt;&lt;/span&gt;configuration&lt;/span&gt;&lt;span style="COLOR: blue; FONT-FAMILY: 'Courier New'"&gt;&amp;gt; &lt;/span&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;div style="mso-line-spacing: '100 50 0'"&gt;This will essentially revert the CLR to
the 1.1 behavior.&amp;nbsp; Consider it a short-term fix&amp;nbsp;because it will ultimately
mask issues with your application that are really bugs.
&lt;/div&gt;
&lt;div style="mso-line-spacing: '100 50 0'"&gt;&amp;nbsp;
&lt;/div&gt;
&lt;div style="mso-line-spacing: '100 50 0'"&gt;Along with the above, you can also be notified
about unhandled exceptions prior to the AppDomain being unloaded.&amp;nbsp; This is done
through several different methods based on the type of application.&amp;nbsp; The first
basic method is through the&amp;nbsp;AppDomain.UnhandledException event which is raised
for Console applications:
&lt;/div&gt;
&lt;div style="mso-line-spacing: '100 50 0'"&gt;&lt;font color=#0000ff size=2&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;
&lt;br&gt;
static&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font color=#000000 size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;font color=#000000 size=2&gt; Main(&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;)&lt;br&gt;
&lt;/font&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;AppDomain&lt;/font&gt;&lt;font size=2&gt;.CurrentDomain.UnhandledException
+= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;delegate&lt;/font&gt;&lt;font size=2&gt;(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; sender, &lt;/font&gt;&lt;font color=#008080 size=2&gt;UnhandledExceptionEventArgs&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font size=2&gt; e)&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"{0}
- IsTerminating = {1}"&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt;&lt;strong&gt;,
e.ExceptionObject.ToString(), e.IsTerminating);&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;};&lt;/strong&gt;&lt;/font&gt;
&lt;/div&gt;
&lt;div style="mso-line-spacing: '100 50 0'"&gt;
&lt;p&gt;
&gt;&lt;font face="Courier New" color=#0000ff size=2&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&lt;/strong&gt;&lt;/font&gt;&lt;strong&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt; (;
;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;BadClass&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;font size=2&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;();&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;}&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;font size=2&gt;In this case, the application will still
be terminated, &lt;em&gt;but&lt;/em&gt;&lt;/font&gt; we will now get notified right before termination.&amp;nbsp;
This allows our application to log the error (using the nifty &lt;strong&gt;System.Diagnostics.TraceSource&lt;/strong&gt; support
or through the EventLog) so we at least know what happened.
&lt;/p&gt;
&lt;p&gt;
For Windows Forms applications, things are a little different -- instead of the &lt;strong&gt;AppDomain.UnhandledException&lt;/strong&gt; event
being raised, the Windows Forms infrastructure will raise the &lt;strong&gt;Application.ThreadException&lt;/strong&gt; event
for exceptions that occur on the primary thread.&amp;nbsp;&amp;nbsp; The default behavior
for this handler is to display the friendly &lt;strong&gt;System.Windows.Forms.ThreadException&lt;/strong&gt; dialog:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;img src="http://www.julmar.com/blog/mark/content/binary/unhandled_exception.bmp" border=0&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
If the exception occurs in the primary (message pumping) thread, the user will see
the above dialog box and be given the choice to terminate the application or not.&amp;nbsp;
The code behind it looks something like:
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;font size=2&gt; Application_ThreadException(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; sender, &lt;/font&gt;&lt;font color=#008080 size=2&gt;ThreadExceptionEventArgs&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt;&lt;strong&gt; e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#0000ff size=2&gt;&lt;strong&gt;try&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt;&lt;strong&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font color=#008000 size=2&gt;//
Call user override&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#0000ff size=2&gt;this&lt;/font&gt;&lt;font size=2&gt;.threadExceptionHandler
!= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font size=2&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;this&lt;/font&gt;&lt;font size=2&gt;.threadExceptionHandler(&lt;/font&gt;&lt;font color=#008080 size=2&gt;Thread&lt;/font&gt;&lt;font size=2&gt;.CurrentThread, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;ThreadExceptionEventArgs&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt;&lt;strong&gt;(e.Exception));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#0000ff size=2&gt;&lt;strong&gt;else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font size=2&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;using&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;ThreadExceptionDialog&lt;/font&gt;&lt;font size=2&gt; excptDlg
= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;ThreadExceptionDialog&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font size=2&gt;(e.Exception))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;DialogResult&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font size=2&gt; result
= excptDlg.ShowDialog();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (result
== &lt;/font&gt;&lt;font color=#008080 size=2&gt;DialogResult&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font size=2&gt;.Abort)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Application&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" size=2&gt;&lt;strong&gt;.Exit();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#0000ff size=2&gt;&lt;strong&gt;catch&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/strong&gt;&lt;/font&gt;&gt;
&lt;/font&gt; 
&lt;p&gt;
That's great for the main thread, but if the exception occurs in a secondary thread,
then the application will still&amp;nbsp;be terminated after raising the &lt;strong&gt;AppDomain.UnhandledException&lt;/strong&gt; event.&amp;nbsp;
So, for non-UI threads, you must still register the unhandled exception handler on
the AppDomain, log the failure and then watch your application die.&amp;nbsp; Having two
handlers can be a pain and if you want to have the application terminate on &lt;em&gt;any&lt;/em&gt; unhandled
exception, you&amp;nbsp;can&amp;nbsp;direct Windows Forms to &lt;em&gt;not&lt;/em&gt; catch primary thread
exceptions automatically by using the &lt;strong&gt;Application.SetUnhandledExceptionBehavior&lt;/strong&gt; method: 
&lt;/p&gt;
&lt;font color=#008080 size=2&gt;&lt;font face="Courier New"&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;font color=#000000&gt;&lt;strong&gt;[&lt;/strong&gt;&lt;/font&gt;
&lt;/font&gt;&lt;font color=#000000 size=2&gt;&lt;strong&gt;STAThread&lt;/strong&gt;&lt;/font&gt;&lt;strong&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;]&lt;/font&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;static&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;/strong&gt;&lt;font size=2&gt;&lt;strong&gt; &lt;/strong&gt;&lt;font color=#000000&gt;&lt;strong&gt;Main()&lt;br&gt;
&lt;/strong&gt;&lt;/font&gt;&lt;font color=#000000&gt;&lt;strong&gt;{&lt;br&gt;
&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;strong&gt;&lt;font color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#000000&gt;Application&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000 size=2&gt;&lt;font color=#000000&gt;.&lt;/font&gt;SetUnhandledExceptionMode(&lt;/font&gt;&lt;font color=#000000 size=2&gt;UnhandledExceptionMode&lt;/font&gt;&lt;/strong&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;&lt;strong&gt;.ThrowException&lt;/strong&gt;&lt;/font&gt;&lt;font color=#000000&gt;&lt;strong&gt;);&lt;br&gt;
&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;strong&gt;&lt;font color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#000000&gt;Application&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000 size=2&gt;.Run(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;Form1&lt;/font&gt;&lt;/strong&gt;&lt;font size=2&gt;&lt;strong&gt;&lt;font color=#000000&gt;());&lt;br&gt;
&lt;/font&gt;&lt;font color=#000000&gt;}&lt;/font&gt;&lt;/strong&gt;&gt;
&lt;p&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font size=2&gt;&lt;font color=#000000&gt;The above line will cause exceptions
thrown in the main thread to be unhandled - thereby triggering the &lt;strong&gt;AppDomain.UnhandledException&lt;/strong&gt; event.&lt;/font&gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=2&gt;&lt;font color=#000000&gt;For ASP.NET applications, things are also a bit different.&amp;nbsp;
First, be aware that any exception thrown during a Page request (the normal Page rendering
process) will be handled automatically by ASP.NET and rendered back to the client
based on the error settings in web.config.&amp;nbsp; If I throw an exception while rendering
the page, then I'll get an HTML response like:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font size=2&gt;&lt;span&gt; 
&lt;h1&gt;&lt;font size=4&gt;&lt;font color=#ff0000&gt;Server Error in '/TestWebSite' Application.&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font size=3&gt;&lt;i&gt;&lt;font color=#a52a2a&gt;Bye, Bye!&lt;/font&gt;&lt;/i&gt; 
&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;
&lt;/span&gt;&lt;font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif "&gt;&lt;font size=2&gt;Description:
An unhandled exception occurred during the execution of the current web request. Please
review the stack trace for more information about the error and where it originated
in the code. &lt;/font&gt;&lt;/font&gt;&gt;
&lt;p&gt;
The important thing here is that the AppDomain &lt;em&gt;&lt;u&gt;continues to run&lt;/u&gt;&lt;/em&gt;.&amp;nbsp;&amp;nbsp;I
can&amp;nbsp;tell ASP.NET to redirect to a specific page through the &lt;font color=#ff0000&gt;&lt;strong&gt;&lt;font color=#0000ff&gt;&amp;lt;&lt;/font&gt;customErrors&lt;/strong&gt;&lt;/font&gt;&lt;font color=#0000ff&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt; &lt;/font&gt;&lt;font color=#000000&gt;section
of the web.config.&amp;nbsp; Or, &lt;/font&gt;I can catch these exceptions and handle them myself
through the global.asax &lt;strong&gt;Application_Error&lt;/strong&gt; method (which is hooking
the &lt;strong&gt;HttpApplication.Error&lt;/strong&gt; event):
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt; Application_Error(&lt;font color=#0000ff&gt;object&lt;/font&gt; sender, &lt;font color=#008080&gt;EventArgs&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt; e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#008080&gt;Exception&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;strong&gt;&lt;font face="Courier New"&gt; ex
= Server.GetLastError();&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Context.ClearError();&lt;/font&gt;&lt;/strong&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font color=#008000&gt;&amp;nbsp;
// Stop default error reporting&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;Response.Write(&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#800000&gt;&lt;strong&gt;"Application
Error:"&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;Response.Write(&lt;/strong&gt;&lt;font color=#800000&gt;&lt;strong&gt;"&lt;/strong&gt;&lt;strong&gt;"&lt;/strong&gt;&lt;/font&gt;&lt;strong&gt; +
Server.HtmlEncode(ex.ToString()) + &lt;/strong&gt;&lt;font color=#800000&gt;&lt;strong&gt;"&lt;/strong&gt;&lt;strong&gt;"&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;);&lt;br&gt;
}&lt;/strong&gt;&lt;/font&gt; 
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
A more&amp;nbsp;popular way to display errors is to cache off the last error in a session
variable and then&amp;nbsp;execute &lt;strong&gt;Server.Transfer&lt;/strong&gt; to some error.aspx
page:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;strong&gt;&lt;font color=#0000ff&gt;void&lt;/font&gt; Application_Error(&lt;font color=#0000ff&gt;object&lt;/font&gt; sender, &lt;font color=#008080&gt;EventArgs&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt; e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#008080&gt;Exception&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;strong&gt;&lt;font face="Courier New"&gt; ex
= Server.GetLastError();&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Session["LastException"] = ex;&lt;/font&gt;&lt;/strong&gt;&lt;font face="Courier New"&gt;&lt;font color=#008000&gt;
&lt;br&gt;
&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;strong&gt;Server.Transfer("myerrorpage.aspx");&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;
&lt;br&gt;
&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Unfortunately, just like Windows Forms, if an unhandled exception occurs on a separate
thread (such as a Threadpool thread), or outside the request processing framework,
then the AppDomain is terminated.&amp;nbsp; This has significant consequences for ASP.NET
applications - because the website itself is cycled.&amp;nbsp; This means you have lost
session state and your users are going to notice the website outage.&amp;nbsp; Most of
the time, there isn't much information to work off of -- you end up with a cryptic
Event Log entry like:
&lt;/p&gt;
&lt;font face="Courier New"&gt; 
&lt;p&gt;
&lt;strong&gt;EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.1830, P3 4333d6f1, P4 app_web_5hu0gabf,
P5 0.0.0.0, P6 4415a8be, P7 7, P8 a, P9 system.exception, P10 NIL.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Verdana&gt;In order to get more information, we need to hook the&lt;strong&gt; AppDomain.UnhandledException&lt;/strong&gt; event
and then log the information, just like we have for Windows Forms and Console applications.&amp;nbsp;
We could put a handler into our global.asax, but that would only handle that one web
application.&amp;nbsp; It would be better to create a new HTTP Module with the event handler
and hook that up through the web.config.&amp;nbsp; Luckily for me, Microsoft has already
published a KB article which shows off this exact solution - &lt;a href="http://support.microsoft.com/?id=911816"&gt;http://support.microsoft.com/?id=911816&lt;/a&gt;.&amp;nbsp;
In this article, Microsoft details creating a new HttpModule class which will log
the exception information to the event log so you will know exactly where the exception
occurred and can provide your own exception handling.&amp;nbsp; Unfortunately, without
the above &lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/font&gt;&lt;span style="COLOR: maroon; FONT-FAMILY: 'Courier New'"&gt;&lt;strong&gt;legacyUnhandledExceptionPolicy&lt;/strong&gt;&lt;font color=#0000ff&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt; &lt;/font&gt;&lt;font face=Verdana color=#000000&gt;entry,
the website will still be cycled.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;/div&gt;
&lt;p&gt;
Bottom line is: be aware of this new, breaking change -- look for places where you
might not be handling exceptions properly and implement good audit trail mechanisms
to log failures when/if they occur.&amp;nbsp; This will allow you to find and fix issues
before they become production problems as you port your legacy code over to .NET 2.0!
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,f733e261-5d39-4ca1-be1a-c422f3cf1f1b.aspx</comments>
      <category>.NET</category>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=3a275fbf-e292-4017-a783-5b40dc1f0ec7</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,3a275fbf-e292-4017-a783-5b40dc1f0ec7.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,3a275fbf-e292-4017-a783-5b40dc1f0ec7.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=3a275fbf-e292-4017-a783-5b40dc1f0ec7</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
So, a question was asked "How do I determine what's happening in the TAPI3 wrapper"? 
The answer is you turn on the internal trace source -- ITapi3 was built with a build
in tracing facility to tell you when it had any underlying interface or COM failures
and it's easy to activate.  First, add an <strong>Application Configuration File</strong> to
your project.  Open that file and add the following lines:
</p>
        <font size="2">
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font color="#0000ff" size="2">
              <p>
&lt;?
</p>
            </font>
            <font color="#800000" size="2">xml</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">version</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">1.0</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">encoding</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">utf-8</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2"> ?&gt;<br />
&lt;</font>
            <font color="#800000" size="2">configuration</font>
            <font color="#0000ff" size="2">&gt;<br />
   &lt;</font>
            <font color="#800000" size="2">system.diagnostics</font>
            <font color="#0000ff" size="2">&gt;<br />
      &lt;</font>
            <font color="#800000" size="2">sources</font>
            <font color="#0000ff" size="2">&gt;<br />
         &lt;</font>
            <font color="#800000" size="2">source</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">name</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">ITapiTrace</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">switchName</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">tapiSwitch</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">switchType</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">System.Diagnostics.SourceSwitch</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">&gt;<br />
            &lt;</font>
            <font color="#800000" size="2">listeners</font>
            <font color="#0000ff" size="2">&gt;<br />
               </font>
            <font color="#0000ff" size="2">&lt;</font>
            <font color="#800000" size="2">add</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">name</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">MyTraceLog</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">type</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">System.Diagnostics.TextWriterTraceListener</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">initializeData</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">MyTrace.txt</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2"> /&gt;<br />
            &lt;/</font>
            <font color="#800000" size="2">listeners</font>
            <font color="#0000ff" size="2">&gt;<br />
         &lt;/</font>
            <font color="#800000" size="2">source</font>
            <font color="#0000ff" size="2">&gt;<br />
      &lt;/</font>
            <font color="#800000" size="2">sources</font>
            <font color="#0000ff" size="2">&gt;<br />
      &lt;</font>
            <font color="#800000" size="2">switches</font>
            <font color="#0000ff" size="2">&gt;<br />
         &lt;</font>
            <font color="#800000" size="2">add</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">name</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">tapiSwitch</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">
            </font>
            <font color="#ff0000" size="2">value</font>
            <font color="#0000ff" size="2">=</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2">All</font>
            <font size="2">"</font>
            <font color="#0000ff" size="2"> /&gt;<br />
      &lt;/</font>
            <font color="#800000" size="2">switches</font>
            <font color="#0000ff" size="2">&gt;<br />
   &lt;/</font>
            <font color="#800000" size="2">system.diagnostics</font>
            <font color="#0000ff" size="2">&gt;<br />
&lt;/</font>
            <font color="#800000" size="2">configuration</font>
            <font color="#0000ff" size="2">&gt;</font>
            <p>
              <font face="Verdana" color="#000000" size="2">This will create a file called "MyTrace.txt"
in your working directory.  The important line is the <strong>source</strong> tag
which identifies the internal <strong>TraceSource</strong> object used by the ITapi3
library.  Inside this file will be the internal TAPI3 calls being made for your
application.  As an example, the following trace shows me that several underlying
COM errors occurred in the running of a simple TAPI3 application -- it was unable
to retrieve the ITTerminal interface from the <strong>ITAddressEvent</strong> interface
(which actually isn't really an error), failed to open the line (because Unimodem
won't allow the media type VOICE to be passed for my modem), and failed to set the
play list for this MSP -- [<font face="Courier New">0x80040216</font><font face="Verdana">]
is actually a DirectShow error [VFW_E_NOT_FOUND].</font></font>
            </p>
            <p>
ITapiTrace Verbose: 0 : Creating ITTAPI instance<br />
ITapiTrace Verbose: 0 : Hooking up connection sink to ITTAPI interface<br />
ITapiTrace Information: 0 : ITTapi::put_EventFilter(0x8001F) hr=0x0<br />
ITapiTrace Error: 0 : COM Hresult 0x80040004 "The MEDIATYPE passed in to this method
was invalid." generated <br />
   at JulMar.Tapi3.TapiException.ThrowExceptionForHR(Int32 hr)<br />
   at JulMar.Tapi3.TTapi.RegisterCallNotifications(ITAddress* pitf, Int16
vbMonitor, Int16 vbOwner, Int32 supportedMediaTypes)<br />
   at JulMar.Tapi3.TAddress.Open(TAPIMEDIATYPES supportedMediaTypes)<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 5, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 4, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 3, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 2, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 1, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 0, Terminal=<br />
ITapiTrace Verbose: 0 : Processing TapiCallNotificationEventArgs: Event=CNE_OWNER,
Call=TCall: 171360625 CS_OFFERING<br />
ITapiTrace Verbose: 0 : Processing TapiCallStateEventArgs: Call=TCall: 171360625 CS_OFFERING,
State=CS_OFFERING, Cause=CEC_NONE<br />
ITapiTrace Error: 0 : COM Hresult 0x80040216 "" generated <br />
   at JulMar.Tapi3.TapiException.ThrowExceptionForHR(Int32 hr)<br />
   at JulMar.Tapi3.TTerminal.set_MediaPlayList(String[] fileList)<br />
   at AnsMachine.AutoAttendantForm.AnswerCall()<br />
   at AnsMachine.AutoAttendantForm.OnCallState(Object sender, TapiCallStateEventArgs
e)<br />
ITapiTrace Verbose: 0 : Processing TapiCallStateEventArgs: Call=TCall: 171360625 CS_DISCONNECTED,
State=CS_DISCONNECTED, Cause=CEC_DISCONNECT_NORMAL<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 5, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 4, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 3, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 2, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 1, Terminal=<br />
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055<br />
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 0, Terminal=<br />
ITapiTrace Error: 0 : ITTapi::Shutdown hr=0x0<br /></p>
            <p>
 
</p>
          </span>
        </font>
        <strong>
          <font color="#000000">
          </font>
        </strong>
      </body>
      <title>Debugging the underlying Telephony calls</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,3a275fbf-e292-4017-a783-5b40dc1f0ec7.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/07/DebuggingTheUnderlyingTelephonyCalls.aspx</link>
      <pubDate>Tue, 07 Mar 2006 23:18:50 GMT</pubDate>
      <description>&lt;p&gt;
So, a question was asked "How do I determine what's happening in the TAPI3 wrapper"?&amp;nbsp;
The answer is you turn on the internal trace source -- ITapi3 was built with a build
in tracing facility to tell you when it had any underlying interface or COM failures
and it's easy to activate.&amp;nbsp; First, add an &lt;strong&gt;Application Configuration File&lt;/strong&gt; to
your project.&amp;nbsp; Open that file and add the following lines:
&lt;/p&gt;
&lt;font size=2&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
&amp;lt;?
&lt;/font&gt;&lt;font color=#800000 size=2&gt;xml&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;version&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;1.0&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;encoding&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;utf-8&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; ?&amp;gt;&lt;br&gt;
&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;configuration&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;system.diagnostics&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;sources&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;source&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;ITapiTrace&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;switchName&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;tapiSwitch&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;switchType&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Diagnostics.SourceSwitch&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;listeners&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;MyTraceLog&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;type&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;System.Diagnostics.TextWriterTraceListener&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;initializeData&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;MyTrace.txt&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;font color=#800000 size=2&gt;listeners&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;font color=#800000 size=2&gt;source&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;font color=#800000 size=2&gt;sources&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;switches&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/font&gt;&lt;font color=#800000 size=2&gt;add&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;name&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;tapiSwitch&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; &lt;/font&gt;&lt;font color=#ff0000 size=2&gt;value&lt;/font&gt;&lt;font color=#0000ff size=2&gt;=&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt;All&lt;/font&gt;&lt;font size=2&gt;"&lt;/font&gt;&lt;font color=#0000ff size=2&gt; /&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;font color=#800000 size=2&gt;switches&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/font&gt;&lt;font color=#800000 size=2&gt;system.diagnostics&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;br&gt;
&amp;lt;/&lt;/font&gt;&lt;font color=#800000 size=2&gt;configuration&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;gt;&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font face=Verdana color=#000000 size=2&gt;This will create a file called "MyTrace.txt"
in your working directory.&amp;nbsp; The important line is the &lt;strong&gt;source&lt;/strong&gt; tag
which identifies the internal &lt;strong&gt;TraceSource&lt;/strong&gt; object used by the ITapi3
library.&amp;nbsp; Inside this file will be the internal TAPI3 calls being made for your
application.&amp;nbsp; As an example, the following trace shows me that several underlying
COM errors occurred in the running of a simple TAPI3 application -- it was unable
to retrieve the ITTerminal interface from the &lt;strong&gt;ITAddressEvent&lt;/strong&gt; interface
(which actually isn't really an error), failed to open the line (because Unimodem
won't allow the media type VOICE to be passed for my modem), and failed to set the
play list for this MSP&amp;nbsp;--&amp;nbsp;[&lt;font face="Courier New"&gt;0x80040216&lt;/font&gt;&lt;font face=Verdana&gt;]
is actually a DirectShow error [VFW_E_NOT_FOUND].&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
ITapiTrace Verbose: 0 : Creating ITTAPI instance&lt;br&gt;
ITapiTrace Verbose: 0 : Hooking up connection sink to ITTAPI interface&lt;br&gt;
ITapiTrace Information: 0 : ITTapi::put_EventFilter(0x8001F) hr=0x0&lt;br&gt;
ITapiTrace Error: 0 : COM Hresult 0x80040004 "The MEDIATYPE passed in to this method
was invalid." generated&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;at JulMar.Tapi3.TapiException.ThrowExceptionForHR(Int32 hr)&lt;br&gt;
&amp;nbsp;&amp;nbsp; at JulMar.Tapi3.TTapi.RegisterCallNotifications(ITAddress* pitf, Int16
vbMonitor, Int16 vbOwner, Int32 supportedMediaTypes)&lt;br&gt;
&amp;nbsp;&amp;nbsp; at JulMar.Tapi3.TAddress.Open(TAPIMEDIATYPES supportedMediaTypes)&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 5, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 4, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 3, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 2, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 1, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 0, Terminal=&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiCallNotificationEventArgs: Event=CNE_OWNER,
Call=TCall: 171360625 CS_OFFERING&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiCallStateEventArgs: Call=TCall: 171360625 CS_OFFERING,
State=CS_OFFERING, Cause=CEC_NONE&lt;br&gt;
ITapiTrace Error: 0 : COM Hresult 0x80040216 "" generated&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;at JulMar.Tapi3.TapiException.ThrowExceptionForHR(Int32 hr)&lt;br&gt;
&amp;nbsp;&amp;nbsp; at JulMar.Tapi3.TTerminal.set_MediaPlayList(String[] fileList)&lt;br&gt;
&amp;nbsp;&amp;nbsp; at AnsMachine.AutoAttendantForm.AnswerCall()&lt;br&gt;
&amp;nbsp;&amp;nbsp; at AnsMachine.AutoAttendantForm.OnCallState(Object sender, TapiCallStateEventArgs
e)&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiCallStateEventArgs: Call=TCall: 171360625 CS_DISCONNECTED,
State=CS_DISCONNECTED, Cause=CEC_DISCONNECT_NORMAL&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 5, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 4, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 3, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 2, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 1, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITAddressEvent::get_Terminal failed hr=0x80040055&lt;br&gt;
ITapiTrace Verbose: 0 : Processing TapiAddressChangedEventArgs: Evt=AE_RINGING, Address=DSSP
Line #1 - Address 0, Terminal=&lt;br&gt;
ITapiTrace Error: 0 : ITTapi::Shutdown hr=0x0&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;/span&gt;&lt;/font&gt;&lt;strong&gt;&lt;font color=#000000&gt;&lt;/font&gt;&lt;/strong&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,3a275fbf-e292-4017-a783-5b40dc1f0ec7.aspx</comments>
      <category>Code</category>
      <category>Tapi</category>
      <category>Debugging</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=b97577a5-a612-4289-b70f-4bd827835c5e</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,b97577a5-a612-4289-b70f-4bd827835c5e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,b97577a5-a612-4289-b70f-4bd827835c5e.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=b97577a5-a612-4289-b70f-4bd827835c5e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I got an email question today asking about how to write a .WAV file out to an active
call using our TAPI3 wrapper.  It's actually pretty easy to do and it follows
along with the normal SDK method used in C++.  Here's the relevant code (for
the full example, download the <a href="http://www.julmar.com/samples/tapi3wrapper.zip">http://www.julmar.com/samples/tapi3wrapper.zip</a> and
look at the AutoAttendant sample).
</p>
        <p>
First, when a new offering call shows up, get hold of the file playback terminal for
it and set it up to play your .WAV files.  We cannot play the files until the
call is answered, but this will essentially "queue" it up.
</p>
        <font size="2">
          <p>
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                <font color="#008000">
                  <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                    <font color="#008000">//
Method called when TE_CALLSTATE == OFFERING raised</font>
                    <br />
                    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">private</span>
                    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> AnswerCall()<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   //
Get the playback terminal from the call</span><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   try</span><br />
   {<br />
      playbackTerminal <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> activeCall.RequestTerminal(TTerminal.FilePlaybackTerminal, <br />
                  TAPIMEDIATYPES.AUDIO,
TERMINAL_DIRECTION.TD_CAPTURE);<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">      if</span> (playbackTerminal
!<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
      {<br />
         playbackTerminal.MediaPlayList <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span>[]
{ <font color="#808080">"Hello.wav"</font> };<br />
         activeCall.SelectTerminalOnCall(playbackTerminal);<br />
         activeCall.Answer();<br />
      }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">      else</span><br />
      {<br />
         MessageBox.Show(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"Failed
to retrieve playback terminal."</span>);<br />
         activeCall.Disconnect(DISCONNECT_CODE.DC_REJECTED);<br />
      }<br />
   }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   catch</span> (TapiException
ex)<br />
   {<br />
   }<br />
}<br /></span>
                </font>
              </span>
            </span>
          </p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#000000" size="2">
                <p>
Next, watch for the call media to change indicating we have an active stream for our
terminal.  When that happens, start the playback stream:
</p>
                <p>
                </p>
              </font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font color="#008000">//
Method called when TE_CALLMEDIA is raised<br /></font>
            </span>
          </span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">private</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> OnCallMedia(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">object</span> sender,
TapiCallMediaEventArgs e)<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   try</span> <br />
   {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">      if</span> (activeCall
!<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span> &amp;&amp;
e.Event == CALL_MEDIA_EVENT.CME_STREAM_ACTIVE &amp;&amp;<br />
            e.Terminal.Direction
== TERMINAL_DIRECTION.TD_CAPTURE &amp;&amp;<br />
            playbackTerminal
!<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
      {<br />
         playbackTerminal.Start();<br />
         SetStatusMessage(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"File
Playback Terminal started "</span>);<br />
      }<br />
   }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   catch</span> (TapiException
ex)<br />
   {<br />
   }<br />
}<br /></span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <p>
              <font face="Verdana" color="#000000" size="2">Finally, when the file terminal is finished,
close and dispose the stream.  This is done just to cleanup the resources properly:</font>
            </p>
            <p>
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                    <font color="#008000">//
Method called when TE_FILETERMINAL is raised<br /></font>
                  </span>
                </span>private</span>
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> OnFileTerminal(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">object</span> sender,
TapiFileTerminalEventArgs e)<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   //
We are interested in TMS_IDLE because we will un-select playback and </span><br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   //
select recording</span><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   if</span> (e.State
== TERMINAL_MEDIA_STATE.TMS_IDLE)<br />
   {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">      if</span> (e.Terminal.Direction
== TERMINAL_DIRECTION.TD_CAPTURE &amp;&amp; playbackTerminal !<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)<br />
      {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">         try</span><br />
         {<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">            //
Remove the playback terminal</span><br />
            activeCall.UnselectTerminalOnCall(playbackTerminal);<br />
            playbackTerminal.Dispose();<br />
            playbackTerminal <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>;<br />
         }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">         catch</span> (TapiException
ex)<br />
         {<br />
         }<br />
      }<br />
   }<br />
}
</p>
            <p>
              <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                  <font color="#000000">
                  </font>
                </span>
              </span>
              <font face="Verdana" size="2">That's
pretty much it -- there's a full sample of this that should work with voice modems
or any streaming-capable TSP.  </font>
            </p>
            <p>
              <font face="Verdana" size="2">
                <strong>Updated: 3/16/05 -- </strong>
              </font>
              <font face="Verdana" size="2">It
doesn't appear to completely work with the H.323 provider; the file terminal gets
connected but apparently never reports an IDLE state and so never gets disconnected
in the above sample.  This appears to be true of the Platform SDK samples as
well.</font>
              <br />
            </p>
          </span>
        </font>
      </body>
      <title>Managing Media Streams with TAPI 3.0</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,b97577a5-a612-4289-b70f-4bd827835c5e.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/06/ManagingMediaStreamsWithTAPI30.aspx</link>
      <pubDate>Mon, 06 Mar 2006 23:02:34 GMT</pubDate>
      <description>&lt;p&gt;
I got an email question today asking about how to write a .WAV file out to an active
call using our TAPI3 wrapper.&amp;nbsp; It's actually pretty easy to do and it follows
along with the normal SDK method used in C++.&amp;nbsp; Here's the relevant code (for
the full example, download the &lt;a href="http://www.julmar.com/samples/tapi3wrapper.zip"&gt;http://www.julmar.com/samples/tapi3wrapper.zip&lt;/a&gt; and
look at the AutoAttendant sample).
&lt;/p&gt;
&lt;p&gt;
First, when a new offering call shows up, get hold of the file playback terminal for
it and set it up to play your .WAV files.&amp;nbsp; We cannot play the files until the
call is answered, but this will essentially "queue" it up.
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#008000&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#008000&gt;//
Method called when TE_CALLSTATE == OFFERING raised&lt;/font&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; AnswerCall()&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;//
Get the playback terminal from the call&lt;/span&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;playbackTerminal &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; activeCall.RequestTerminal(TTerminal.FilePlaybackTerminal,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TAPIMEDIATYPES.AUDIO,
TERMINAL_DIRECTION.TD_CAPTURE);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (playbackTerminal
!&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;playbackTerminal.MediaPlayList &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt;[]
{ &lt;font color=#808080&gt;"Hello.wav"&lt;/font&gt; };&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activeCall.SelectTerminalOnCall(playbackTerminal);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activeCall.Answer();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MessageBox.Show(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"Failed
to retrieve playback terminal."&lt;/span&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activeCall.Disconnect(DISCONNECT_CODE.DC_REJECTED);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch&lt;/span&gt; (TapiException
ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;br&gt;
&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#000000 size=2&gt; 
&lt;p&gt;
Next, watch for the call media to change indicating we have an active stream for our
terminal.&amp;nbsp; When that happens, start the playback stream:
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#008000&gt;//
Method called when TE_CALLMEDIA is raised&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; OnCallMedia(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
TapiCallMediaEventArgs e)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;/span&gt;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (activeCall
!&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt; &amp;amp;&amp;amp;
e.Event == CALL_MEDIA_EVENT.CME_STREAM_ACTIVE &amp;amp;&amp;amp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;e.Terminal.Direction
== TERMINAL_DIRECTION.TD_CAPTURE &amp;amp;&amp;amp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;playbackTerminal
!&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;playbackTerminal.Start();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SetStatusMessage(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"File
Playback Terminal started "&lt;/span&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch&lt;/span&gt; (TapiException
ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;br&gt;
&gt;
&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; 
&lt;p&gt;
&lt;font face=Verdana color=#000000 size=2&gt;Finally, when the file terminal is finished,
close and dispose the stream.&amp;nbsp; This is done just to cleanup the resources properly:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#008000&gt;//
Method called when TE_FILETERMINAL is raised&lt;br&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; OnFileTerminal(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
TapiFileTerminalEventArgs e)&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;//
We are interested in TMS_IDLE because we will un-select playback and&amp;nbsp;&lt;/span&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;//
select recording&lt;/span&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (e.State
== TERMINAL_MEDIA_STATE.TMS_IDLE)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (e.Terminal.Direction
== TERMINAL_DIRECTION.TD_CAPTURE &amp;amp;&amp;amp; playbackTerminal !&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//
Remove the playback terminal&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activeCall.UnselectTerminalOnCall(playbackTerminal);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;playbackTerminal.Dispose();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;playbackTerminal &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch&lt;/span&gt; (TapiException
ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#000000&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font face=Verdana size=2&gt;That's
pretty much it -- there's a full sample of this that should work with voice modems
or any streaming-capable TSP.&amp;nbsp; &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face=Verdana size=2&gt;&lt;strong&gt;Updated: 3/16/05 -- &lt;/strong&gt;&lt;/font&gt;&lt;font face=Verdana size=2&gt;It
doesn't appear to completely work with the H.323 provider; the file terminal gets
connected but apparently never reports an IDLE state and so never gets disconnected
in the above sample.&amp;nbsp; This appears to be true of the Platform SDK samples as
well.&lt;/font&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;/span&gt;&lt;/font&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,b97577a5-a612-4289-b70f-4bd827835c5e.aspx</comments>
      <category>Code</category>
      <category>Tapi</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=d503a167-04e4-4e88-9218-6deeae20d9ea</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,d503a167-04e4-4e88-9218-6deeae20d9ea.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,d503a167-04e4-4e88-9218-6deeae20d9ea.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=d503a167-04e4-4e88-9218-6deeae20d9ea</wfw:commentRss>
      <title>Wrapping the TAPI 3.0 API with C++/CLI</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,d503a167-04e4-4e88-9218-6deeae20d9ea.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/03/03/WrappingTheTAPI30APIWithCCLI.aspx</link>
      <pubDate>Fri, 03 Mar 2006 18:05:50 GMT</pubDate>
      <description>&lt;p&gt;
New announcement - TAPI3 wrapper for .NET available on our samples page -- &lt;a href="http://www.julmar.com/samples/tapi3wrapper.zip"&gt;http://www.julmar.com/samples/tapi3wrapper.zip&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Recently, I released the ATAPI.NET project into the wild for people to be able to
easily code up .NET applications that utilize TAPI.&amp;nbsp; That assembly is based on
the C API exported from TAPI 2.1 and so uses the older form of TAPI programming.&amp;nbsp;
With Windows 2000, Microsoft released a COM version of TAPI - dubbed TAPI 3.0 that
was designed to allow VB developers to access the telephony API.&amp;nbsp; However, as
I noted in my previous post, Microsoft claims that the object model is too complex
and that there are significant issues with accessing it from managed code.
&lt;/p&gt;
&lt;p&gt;
.NET has a built-in facility to access COM objects, it creates .NET wrappers (called
RCW's) around the COM interfaces and then allows you to call the COM object as if
it were a .NET object.&amp;nbsp; That's great&amp;nbsp;until you need to mesh the COM style
of cleanup (AddRef/Release) with the .NET style (GC).&amp;nbsp; Essentially, the COM object
doesn't get released until the managed wrapper gets collected.&amp;nbsp; In addition,
if you have multiple wrappers for a single interface (TAPI returns the same interface
through different methods), the interface won't be released until &lt;strong&gt;all&lt;/strong&gt; the
wrappers are collected.
&lt;/p&gt;
&lt;p&gt;
Sometimes, this isn't really a problem - so we keep a COM interface alive a little
longer than normal.&amp;nbsp; In TAPI's case however it can be a huge problem because
some TAPI service providers will not let you create new calls unless the&amp;nbsp;existing
call&amp;nbsp;interface has been released - even if it isn't connected to anything.
&lt;/p&gt;
&lt;p&gt;
So, two options exist today:
&lt;/p&gt;
&lt;p&gt;
1) Don't use TAPI 3.x - use TAPI 2.x where you have more control over the underlying
TAPI call handle and can call lineDeallocate yourself.&amp;nbsp; In .NET this means using
some wrapper like ATAPI.NET.&amp;nbsp; If you don't need terminal and stream support,
this is fine.&amp;nbsp; This is what the newsgroups typically will recommend to people.
&lt;/p&gt;
&lt;p&gt;
2) Call Marshal.ReleaseCOMObject on every outstanding interface.&amp;nbsp; Just plain
ugly and extremely error-prone.
&lt;/p&gt;
&lt;p&gt;
Now, a new option exists.&amp;nbsp; I've been in conversations with Matthias Moetje -
one of the TAPI MVPs and went back to my original TAPI3 wrapper which was written
in MC++ (yuck) and ported it to C++/CLI (which, BTW, is very cool).&amp;nbsp; It has almost
everything supported except agents and call center support.&amp;nbsp; It solves the above
problem in a couple of steps:
&lt;/p&gt;
&lt;p&gt;
1) It guarantees that the same interface will match 1:1 with a managed object as long
as the object hasn't been collected yet.&amp;nbsp; This means the object will only have
one holding managed object.&lt;br&gt;
2) It implements IDisposable on most of the&amp;nbsp;wrappers allowing the client to get
rid of interfaces immediately.&lt;br&gt;
3) It "auto-disposes" calls when they hit the disconnected state.&amp;nbsp; This can be
turned on or off depending on need through the &lt;font face="Courier New"&gt;TTapi.AutoDestroyCalls&lt;/font&gt; flag
&lt;/p&gt;
&lt;font size=2&gt; 
&lt;p&gt;
Instead of a Register function, each address has an &lt;font face="Courier New" color=#0000ff&gt;Open&lt;/font&gt; and &lt;font face="Courier New" color=#0000ff&gt;Monitor&lt;/font&gt; method
and a &lt;font face="Courier New" color=#0000ff&gt;Close&lt;/font&gt; method. Since you have to
pass the address in anyway, I moved the function to that level and made it distinct
rather than having you pass in two booleans to indicate intent.
&lt;/p&gt;
&lt;p&gt;
There are some shorthand functions: for example, the &lt;font face="Courier New" color=#0000ff&gt;TCall&lt;/font&gt; object
(which represents ITBasicCallControl, ITCallInfo, et.al.) has a &lt;font face="Courier New" color=#0000ff&gt;SelectDefaultTerminals&lt;/font&gt; method
which enumerates the streams and hooks up the default static/video terminals for each
stream - basically the code that was in every TAPI sample provided by MS. There's
also a &lt;font face="Courier New" color=#0000ff&gt;FindTerminal&lt;/font&gt; method on the TStream
class which will locate a terminal of the proper media type/direction if it exists.
&lt;/p&gt;
&lt;/font&gt; 
&lt;p&gt;
The library itself follows the TAPI3 interfaces pretty closely - except it combines
the various control interfaces together.&amp;nbsp; So for example:
&lt;/p&gt;
&lt;p&gt;
&lt;table class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing=0 cellpadding=0 border=1&gt;
&lt;tbody&gt;
&lt;tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes"&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: black; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 1.2in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt" valign=top width=115&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="COLOR: white"&gt;&lt;font face="Times New Roman"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;Class&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: black; PADDING-BOTTOM: 0in; BORDER-LEFT: #ffffff; WIDTH: 4.95in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign=top width=475&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="COLOR: white"&gt;&lt;font face="Times New Roman"&gt;Interfaces&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow: 1"&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ffffff; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 1.2in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign=top width=115&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;font color=#000000&gt;&lt;font face="Times New Roman"&gt;TTapi&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ffffff; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ffffff; WIDTH: 4.95in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign=top width=475&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;span style="FONT-FAMILY: 'Courier New'"&gt;&lt;font color=#000000&gt;ITTapi, ITTapi2&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow: 2"&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ffffff; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 1.2in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign=top width=115&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;font color=#000000&gt;&lt;font face="Times New Roman"&gt;TAddress&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ffffff; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ffffff; WIDTH: 4.95in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign=top width=475&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;font color=#000000&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;ITAddress, ITAddress2, &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: 'Courier New'; mso-highlight: white; mso-no-proof: yes"&gt;ITAddressCapabilities&lt;/span&gt;&lt;/font&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;,
ITAddressTranslation, ITLegacyAddressMediaControl, ITLegacyAddressMediaControl2, ITMediaSupport,
ITTerminalSupport&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes"&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ffffff; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt solid; WIDTH: 1.2in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign=top width=115&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;font color=#000000&gt;&lt;font face="Times New Roman"&gt;TCall&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ffffff; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ffffff; WIDTH: 4.95in; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign=top width=475&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;span style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: 'Courier New'; mso-highlight: white; mso-no-proof: yes"&gt;ITCallInfo&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;, &lt;span style="BACKGROUND: white; mso-highlight: white"&gt;ITBasicCallControl&lt;/span&gt;, &lt;span style="BACKGROUND: white; mso-highlight: white"&gt;ITBasicCallControl&lt;/span&gt;2, &lt;span style="BACKGROUND: white; mso-highlight: white"&gt;ITStreamControl&lt;/span&gt;, &lt;span style="BACKGROUND: white; mso-highlight: white"&gt;ITLegacyCallMediaControl&lt;/span&gt;, &lt;span style="BACKGROUND: white; mso-highlight: white"&gt;ITLegacyCallMediaControl&lt;/span&gt;2&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'"&gt;
&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;
In each case, the same properties and methods are exposed by the reference class and
it will do the underlying cast necessary to get to the functionality.&amp;nbsp; The downside
of this, is that if the interface isn't supported, the library must throw an exception
- in this case a &lt;font face="Courier New" color=#0000ff&gt;TapiException&lt;/font&gt; which
holds a string message indicating the failure and an error code (the HRESULT).&amp;nbsp;
The &lt;font face="Courier New" color=#0000ff&gt;TTapi&lt;/font&gt; class exposes the &lt;font face="Courier New"&gt;TE_xxx&lt;/font&gt; events
you generally registered a sink for.
&lt;/p&gt;
&lt;p&gt;
I didn't bother to encapsulate the DirectShow library - instead each of the TAPI wrappers
provides a &lt;font face="Courier New" color=#0000ff&gt;QueryInterface&lt;/font&gt; method which
you can use to get to an interface if necessary.&amp;nbsp; So, for example, if you want
to get to the venerable IVideoWindow interface from DirectShow, you can include an
interop reference to Quartz.DLL and then do the following on the TTerminal object:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;IVideoWindow&lt;/font&gt; videoWindow = thisTerminal.QueryInterface(&lt;font color=#0000ff&gt;typeof&lt;/font&gt;(&lt;font color=#0000ff&gt;IVideoWindow&lt;/font&gt;)) &lt;font color=#0000ff&gt;as&lt;/font&gt; &lt;font color=#0000ff&gt;IVideoWindow&lt;/font&gt;;&lt;br&gt;
&lt;font color=#0000ff&gt;if&lt;/font&gt; (videoWindow != null) { ... }&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
So, here's an example of using it - I think it's much cleaner that the comparable
RCW code, and it's thread-aware and works around the general problem of TAPI3 under
.NET through a&amp;nbsp;&lt;font face="Courier New"&gt;Dispose&lt;/font&gt; mechanism and the &lt;font face="Courier New"&gt;TTapi.AutoDestroyCalls&lt;/font&gt; flag.
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font color=#0000ff&gt;&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
using
&lt;/font&gt;&lt;font size=2&gt; System;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;using&lt;/font&gt;&lt;font size=2&gt; System.Collections.Generic;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;using&lt;/font&gt;&lt;font size=2&gt; System.Text;&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;using&lt;/font&gt;&lt;font size=2&gt; JulMar.Tapi3;&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt; 
&lt;p&gt;
namespace
&lt;/font&gt;&lt;font size=2&gt; TestTapi&lt;br&gt;
{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;class&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;Program&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;static&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#0000ff size=2&gt;void&lt;/font&gt;&lt;font size=2&gt; Main(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;string&lt;/font&gt;&lt;font size=2&gt;[]
args)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&lt;/font&gt;&lt;font color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TTapi&lt;/font&gt;&lt;font size=2&gt; tapi
= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;new&lt;/font&gt;&lt;font size=2&gt; &lt;/font&gt;&lt;font color=#008080 size=2&gt;TTapi&lt;/font&gt;&lt;font size=2&gt;();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;TCall&lt;/font&gt;&lt;font size=2&gt; call
= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt;; &lt;/font&gt;&lt;font color=#008080 size=2&gt;TAddress&lt;/font&gt;&lt;font size=2&gt; modemAddr
= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt;;&lt;br&gt;
&lt;/font&gt;&gt;
&lt;p&gt;
&lt;font size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tapi.Initialize();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tapi.TE_CALLNOTIFICATION += &lt;/font&gt;&lt;font color=#0000ff size=2&gt;delegate&lt;/font&gt;&lt;font size=2&gt;(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; sender, &lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiCallNotificationEventArgs&lt;/font&gt;&lt;font size=2&gt; e)&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;/font&gt;&lt;font size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"New
call {0} detected from {1}"&lt;/font&gt;&lt;font size=2&gt;, e.Call.ToString(), e.Event);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=2&gt;tapi.TE_CALLSTATE
+= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;delegate&lt;/font&gt;&lt;font size=2&gt;(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;object&lt;/font&gt;&lt;font size=2&gt; sender, &lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiCallStateEventArgs&lt;/font&gt;&lt;font size=2&gt; e)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"{0}:{4}
has changed state to {1} due to {2} - current={3}:{5}"&lt;/font&gt;&lt;font size=2&gt;,&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=2&gt;e.Call,
e.State, e.Cause, e.Call == call, e.Call.GetHashCode(), (call != &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt;)
? call.GetHashCode() : 0);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (e.State
== &lt;/font&gt;&lt;font color=#008080 size=2&gt;CALL_STATE&lt;/font&gt;&lt;font size=2&gt;.CS_INPROGRESS
&amp;amp;&amp;amp; e.Call == call)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Dropping
call"&lt;/font&gt;&lt;font size=2&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;e.Call.Disconnect(&lt;/font&gt;&lt;font color=#008080 size=2&gt;DISCONNECT_CODE&lt;/font&gt;&lt;font size=2&gt;.DC_NORMAL);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
&lt;/p&gt;
&gt;&lt;font size=2&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TAddress&lt;/font&gt;&lt;font size=2&gt; addr &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;font size=2&gt; tapi.Addresses)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;String&lt;/font&gt;&lt;font size=2&gt;.Compare(addr.ServiceProviderName, &lt;/font&gt;&lt;font color=#800000 size=2&gt;"unimdm.tsp"&lt;/font&gt;&lt;font size=2&gt;, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;true&lt;/font&gt;&lt;font size=2&gt;)
== 0 &amp;amp;&amp;amp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=2&gt;addr.QueryMediaType(&lt;/font&gt;&lt;font color=#008080 size=2&gt;TAPIMEDIATYPES&lt;/font&gt;&lt;font size=2&gt;.AUDIO))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modemAddr
= addr;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/font&gt;&lt;font size=2&gt; (modemAddr
!= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"{0}
= {1} ({3}) [{2}]"&lt;/font&gt;&lt;font size=2&gt;, modemAddr.AddressName, modemAddr.State, modemAddr.ServiceProviderName,
modemAddr.DialableAddress);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modemAddr.Monitor(&lt;/font&gt;&lt;font color=#008080 size=2&gt;TAPIMEDIATYPES&lt;/font&gt;&lt;font size=2&gt;.AUDIO);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;ConsoleKey&lt;/font&gt;&lt;font size=2&gt; ki
= &lt;/font&gt;&lt;font color=#008080 size=2&gt;ConsoleKey&lt;/font&gt;&lt;font size=2&gt;.A;&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&lt;/font&gt;&lt;font size=2&gt; (ki
!= &lt;/font&gt;&lt;font color=#008080 size=2&gt;ConsoleKey&lt;/font&gt;&lt;font size=2&gt;.Q)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008000 size=2&gt;//
Flip the auto-destroy flag&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (ki
== &lt;/font&gt;&lt;font color=#008080 size=2&gt;ConsoleKey&lt;/font&gt;&lt;font size=2&gt;.D)&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tapi.AutoDestroyCalls
= !tapi.AutoDestroyCalls;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Set
AutoDestroy to {0}"&lt;/font&gt;&lt;font size=2&gt;, tapi.AutoDestroyCalls);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008000 size=2&gt;//
List existing calls&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#0000ff&gt;else &lt;/font&gt;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (ki
== &lt;/font&gt;&lt;font color=#008080 size=2&gt;ConsoleKey&lt;/font&gt;&lt;font size=2&gt;.L)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;foreach&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TCall&lt;/font&gt;&lt;font size=2&gt; _call &lt;/font&gt;&lt;font color=#0000ff size=2&gt;in&lt;/font&gt;&lt;font size=2&gt; modemAddr.EnumerateCalls())&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Existing
call found: {0}:{1}"&lt;/font&gt;&lt;font size=2&gt;, _call, _call.GetHashCode());&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_call.Dispose(); &lt;/font&gt;&lt;font color=#008000 size=2&gt;//
Go ahead and dump it&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=2&gt;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008000 size=2&gt;//
Create a new call&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;else&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=2&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;call
= modemAddr.CreateCall(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"5551213"&lt;/font&gt;&lt;font size=2&gt;, &lt;/font&gt;&lt;font color=#008080 size=2&gt;LINEADDRESSTYPES&lt;/font&gt;&lt;font size=2&gt;.PhoneNumber, &lt;/font&gt;&lt;font color=#008080 size=2&gt;TAPIMEDIATYPES&lt;/font&gt;&lt;font size=2&gt;.DATAMODEM);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Created
new call {0}:{1}"&lt;/font&gt;&lt;font size=2&gt;, call, call.GetHashCode());&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;try&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=2&gt;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008000 size=2&gt;//
This will fail if existing call interface is still around (i.e. not disposed)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font size=2&gt;call.Connect(&lt;/font&gt;&lt;font color=#0000ff size=2&gt;false&lt;/font&gt;&lt;font size=2&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;catch&lt;/font&gt;&lt;font size=2&gt; (&lt;/font&gt;&lt;font color=#008080 size=2&gt;TapiException&lt;/font&gt;&lt;font size=2&gt; ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(ex.Message);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"Press
a key to try another call.. Q to quit"&lt;/font&gt;&lt;font size=2&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ki
= &lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.ReadKey().Key;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&gt;
&lt;p&gt;
&lt;font color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;This
will destroy any&amp;nbsp;outstanding interfaces&lt;br&gt;
&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tapi.Shutdown();
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//
Call should be disposed here.. state will be CS_UNKNOWN&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (call
!= &lt;/font&gt;&lt;font color=#0000ff size=2&gt;null&lt;/font&gt;&lt;font size=2&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=#008080 size=2&gt;Console&lt;/font&gt;&lt;font size=2&gt;.WriteLine(&lt;/font&gt;&lt;font color=#800000 size=2&gt;"{0}
{1}"&lt;/font&gt;&lt;font size=2&gt;, call, call.CallState);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/font&gt;
&lt;br&gt;
&lt;/span&gt;&amp;nbsp;&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,d503a167-04e4-4e88-9218-6deeae20d9ea.aspx</comments>
      <category>Code</category>
      <category>Tapi</category>
    </item>
    <item>
      <trackback:ping>http://www.julmar.com/blog/mark/Trackback.aspx?guid=712cc7bb-42fe-4ecf-909e-1c5ea3c725c9</trackback:ping>
      <pingback:server>http://www.julmar.com/blog/mark/pingback.aspx</pingback:server>
      <pingback:target>http://www.julmar.com/blog/mark/PermaLink,guid,712cc7bb-42fe-4ecf-909e-1c5ea3c725c9.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.julmar.com/blog/mark/CommentView,guid,712cc7bb-42fe-4ecf-909e-1c5ea3c725c9.aspx</wfw:comment>
      <wfw:commentRss>http://www.julmar.com/blog/mark/SyndicationService.asmx/GetEntryCommentsRss?guid=712cc7bb-42fe-4ecf-909e-1c5ea3c725c9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Ok, ok so it's been a while.  I've been very busy with two tasks -- first, I
spent the last few weeks doing a Guerrilla .NET for <a href="http://www.develop.com">DevelopMentor</a> with <a href="http://www.dotnetconsult.co.uk/weblog/">Rich
Blewitt</a>.  We had a blast together and it was great to hang out with him. 
I also spent a day sitting in on DM's new C++/CLI class being taught by the very capable
Marcus Heege - incredible stuff which every C++ guy on the Microsoft platform should
get into..
</p>
        <p>
The other thing I've been working with is resurrecting an old project of mine - ATAPI
which was originally setup to wrap the TAPI 2.x API in an "easy to use" set of C++
classes.  I'd ported it to .NET a few years ago but was not really happy with
the results.  I had the chance to revisit it because of a client's requirement
to integrate TAPI into their .NET platform code.  So, I spent a couple of weeks
working on the codebase again under .NET 2.0 and this time around I'm pretty pleased
with the architecture.  I wanted something very easy to use, and I think
I've achieved that even though it isn't a complete wrapper.  
</p>
        <p>
For example, to walk through all the lines and dump out the device classes available -
you can simply do this:
</p>
        <p>
          <font face="Courier New">
            <font color="#0000ff">using</font> System;<br /><font color="#0000ff">using</font> System.Collections.Generic;<br /><font color="#0000ff">using</font> System.Text;<br /><font color="#0000ff">using</font> JulMar.Atapi;</font>
        </p>
        <p>
          <font face="Courier New">
            <font color="#0000ff">namespace</font> EnumDevices<br />
{<br />
    <font color="#0000ff">class</font> Program<br />
    {<br />
        <font color="#0000ff">static void</font> Main(<font color="#0000ff">string</font>[]
args)<br />
        {<br />
            TapiManager mgr
= <font color="#0000ff">new</font> TapiManager(<font color="#800080">"EnumDevices"</font>);<br />
            mgr.Initialize(); <font color="#008000">//
Start up Tapi</font></font>
        </p>
        <p>
          <font face="Courier New">            <font color="#0000ff">foreach</font> (TapiLine
line <font color="#0000ff">in</font> mgr.Lines)<br />
            {<br />
                <font color="#0000ff">foreach</font> (string
s in line.Capabilities.AvailableDeviceClasses)<br />
                   
Console.WriteLine<font color="#800080">("{0} - {1}"</font>, line.Name, s);<br />
            }            
<br />
            mgr.Shutdown();<br />
        }<br />
    }<br />
}</font>
        </p>
        <p>
Cool huh?
</p>
        <p>
So.. why not use the TAPI3 COM API you ask?  Well, as it turns out, it doesn't
work that well with the RCW infrastructure in .NET -- check out <a href="http://support.microsoft.com/kb/841712/en-us">http://support.microsoft.com/kb/841712/en-us</a> where
Microsoft basically says "TAPI3 is too complicated".. like I needed someone to tell
me that..
</p>
        <p>
The ATAPI.NET stuff is available from JulMar's download area - you can get it
along with a sample program from <a href="http://www.julmar.com/samples/atapinet.zip">http://www.julmar.com/samples/atapinet.zip</a>.
</p>
        <p>
enjoy.
</p>
      </body>
      <title>ATAPI for .NET 2.0</title>
      <guid isPermaLink="false">http://www.julmar.com/blog/mark/PermaLink,guid,712cc7bb-42fe-4ecf-909e-1c5ea3c725c9.aspx</guid>
      <link>http://www.julmar.com/blog/mark/2006/02/15/ATAPIForNET20.aspx</link>
      <pubDate>Wed, 15 Feb 2006 19:20:58 GMT</pubDate>
      <description>&lt;p&gt;
Ok, ok so it's been a while.&amp;nbsp; I've been very busy with two tasks -- first, I
spent the last few weeks doing a Guerrilla .NET for &lt;a href="http://www.develop.com"&gt;DevelopMentor&lt;/a&gt;&amp;nbsp;with &lt;a href="http://www.dotnetconsult.co.uk/weblog/"&gt;Rich
Blewitt&lt;/a&gt;.&amp;nbsp; We had a blast together and it was great to hang out with him.&amp;nbsp;
I also spent a day sitting in on DM's new C++/CLI class being taught by the very capable
Marcus Heege - incredible stuff which every C++ guy on the Microsoft platform should
get into..
&lt;/p&gt;
&lt;p&gt;
The other thing I've been working with is resurrecting an old project of mine - ATAPI
which was originally setup to wrap the TAPI 2.x API in an "easy to use" set of C++
classes.&amp;nbsp; I'd ported it to .NET a few years ago but was not really happy with
the results.&amp;nbsp; I had the chance to revisit it because of a client's requirement
to integrate TAPI into their .NET platform code.&amp;nbsp; So, I spent a couple of weeks
working on the codebase again under .NET 2.0 and this time around I'm pretty pleased
with the architecture.&amp;nbsp; I wanted&amp;nbsp;something very easy to use, and I think
I've achieved that even though it isn't&amp;nbsp;a complete wrapper.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
For example, to walk through all the lines and dump out the device classes available&amp;nbsp;-
you can simply do this:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;using&lt;/font&gt; System;&lt;br&gt;
&lt;font color=#0000ff&gt;using&lt;/font&gt; System.Collections.Generic;&lt;br&gt;
&lt;font color=#0000ff&gt;using&lt;/font&gt; System.Text;&lt;br&gt;
&lt;font color=#0000ff&gt;using&lt;/font&gt; JulMar.Atapi;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;namespace&lt;/font&gt; EnumDevices&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;class&lt;/font&gt; Program&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;static void&lt;/font&gt; Main(&lt;font color=#0000ff&gt;string&lt;/font&gt;[]
args)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TapiManager mgr
= &lt;font color=#0000ff&gt;new&lt;/font&gt; TapiManager(&lt;font color=#800080&gt;"EnumDevices"&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mgr.Initialize(); &lt;font color=#008000&gt;//
Start up Tapi&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;foreach&lt;/font&gt; (TapiLine
line &lt;font color=#0000ff&gt;in&lt;/font&gt; mgr.Lines)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;foreach&lt;/font&gt; (string
s in line.Capabilities.AvailableDeviceClasses)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Console.WriteLine&lt;font color=#800080&gt;("{0} - {1}"&lt;/font&gt;, line.Name, s);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mgr.Shutdown();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Cool huh?
&lt;/p&gt;
&lt;p&gt;
So.. why not use the TAPI3 COM API you ask?&amp;nbsp; Well, as it turns out, it doesn't
work that well with the RCW infrastructure in .NET -- check out &lt;a href="http://support.microsoft.com/kb/841712/en-us"&gt;http://support.microsoft.com/kb/841712/en-us&lt;/a&gt;&amp;nbsp;where
Microsoft basically says "TAPI3 is too complicated".. like I needed someone to tell
me that..
&lt;/p&gt;
&lt;p&gt;
The ATAPI.NET stuff is available from JulMar's download area - you can&amp;nbsp;get it
along with a sample program from &lt;a href="http://www.julmar.com/samples/atapinet.zip"&gt;http://www.julmar.com/samples/atapinet.zip&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
enjoy.
&lt;/p&gt;</description>
      <comments>http://www.julmar.com/blog/mark/CommentView,guid,712cc7bb-42fe-4ecf-909e-1c5ea3c725c9.aspx</comments>
      <category>Code</category>
      <category>Tapi</category>
    </item>
  </channel>
</rss>