<?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>Building a Better User Experience - Tips and Tricks</title>
    <link>http://www.mindfusioncorp.com/weblog/</link>
    <description>A weblog authored by Keith Rome, with a focus on the User Experience.</description>
    <language>en-us</language>
    <copyright>Keith Rome</copyright>
    <lastBuildDate>Mon, 09 Jun 2008 21:59:22 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>krome@wintellect.com</managingEditor>
    <webMaster>krome@wintellect.com</webMaster>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=ce802397-894c-4772-994b-5d5ba4df3fda</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,ce802397-894c-4772-994b-5d5ba4df3fda.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,ce802397-894c-4772-994b-5d5ba4df3fda.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=ce802397-894c-4772-994b-5d5ba4df3fda</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Audio support is all too often one of the last things a developer thinks of when it
comes to building a user interface. Fortunately, Silverlight offers some basic building
blocks that make it fairly trivial to add event-driven sounds to our applications.
I have taken the built-in functionality one step further, and created a simple run-time
audio engine that makes it even easier.
</p>
        <p>
First, I will discuss the requirements that I had in mind when I created this engine.
Second, I will discuss the ideal API for a complete solution. Third, I submit the
simple effects engine that I developed in order to meet those requirements and API.
</p>
        <p>
          <strong>Sound Effects Engine Requirements</strong>
        </p>
        <ul>
          <li>
Must be able to play looping “background music” tracks. 
</li>
          <li>
Must be able to play smaller sound effects on demand. 
</li>
          <li>
Must support concurrent (and overlapping) sounds effects without interfering with
already-playing audio. 
</li>
          <li>
Must adequately handle the possibility of download delays when pulling down external
audio files. 
</li>
          <li>
Should cache audio files between playbacks. 
</li>
          <li>
Should allow serving of audio from high-bandwidth CDN such as Silverlight Streaming. 
</li>
        </ul>
        <p>
          <strong>An Ideal Sound Effects API</strong>
        </p>
        <ul>
          <li>
Should be very approachable. If possible, only a single line of code to play any audio
(similar to PlaySound() API). 
</li>
          <li>
Should support any formats supported by Silverlight. 
</li>
          <li>
Should be efficient. 
</li>
          <li>
Should offer download and playback completion callbacks (for chaining and synchronization). 
</li>
          <li>
Should support aggressive background pre-caching of audio files. 
</li>
        </ul>
        <p>
          <strong>The SilverlightToolbox Solution</strong>
        </p>
        <p>
To address the simplicity requirements, this sound effects engine is implemented as
a single static C# class that can be easily included into any Silverlight project.
It can exist in a referenced class library, or can be linked directly into the main
project.
</p>
        <p>
To address looping background music, a single method SetBackgroundLoop() is supplied.
This will begin playback of a single audio clip, and will automatically repeat it.
Only one track can be played as the background loop – calling this method again will
terminate the running track and start the new one. You can also pass String.Empty
to stop all background music.
</p>
        <p>
To address typical sound effect clips. two overloads of the PlaySoundEffect() method
are supplied. The simpler of the two methods will simply play a clip once it has been
downloaded. The extended version allows you to specify a callback for when the clip
has been downloaded and started playing, and a second callback that can be used for
notification that the clip has ended.
</p>
        <p>
To address the scenario where multiple sound effects might be played at the same time,
the engine internally maintains a queue of MediaElements. When a new sound needs to
played, it pulls an unused element and puts it into service. Once the sound is finished,
the element is returned to the queue. This allows Silverlight itself to handle media
mixing, and by caching those MediaElements, it does so without placing undue stress
on the environment.
</p>
        <p>
To address the issue of download delays, the startedCallback and completedCallback
parameters of PlaySoundEffect() were introduced.
</p>
        <p>
To address caching of audio files, a WebClient is used (which in turn leverages the
browser’s cache). Furthermore, the engine will reuse any downloaded file streams (and
is smart enough to not re-queue the same file if it already queued for download).
</p>
        <p>
By using a MediaElement for playback, audio tracks are automatically supported from
streaming sources and Content Delivery Networks, and can be of any type supported
by Silverlight.
</p>
        <p>
To support chaining of audio effects, and to support synchronization of UI with audio,
the PlaySoundEffect() method accepts callback events that are fired when the clip
has been downloaded, and again when it has completed playback. To further help with
UI synchronization, a second utility class is provided (DelayedAction) which provides
a simple wrapper for BackgroundWorker that can be used to easily delay execution of
a block of code after a specified amount of time.
</p>
        <p>
To support pre-caching of audio files, the PreloadMedia() method can be used.
</p>
        <p>
          <strong>Typical usage:</strong>
        </p>
        <p>
In order for the sound effects engine to function properly, it must be provided with
a top-level XAML container (MediaElement currently will not perform playback without
a parent object). This is done by calling the Initialize() method, typically from
your program’s startup code:
</p>
        <div>
          <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">SoundEffects.Initialize(<span style="color: #0000ff">this</span>.LayoutRoot);</pre>
        </div>
        <p>
 
</p>
        <p>
After this has been done, background music can be played, and we can also queue up
some sound effect clips for later:
</p>
        <div>
          <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">SoundEffects.SetBackgroundLoop(<span style="color: #006080">"cautious-path.wma"</span>);
SoundEffects.PreloadMedia(<span style="color: #006080">"pop1.wma"</span>);</pre>
        </div>
        <p>
 
</p>
        <p>
Then, at various points throughout the application, we can play the sound effect (for
example, in response to a control event):
</p>
        <div>
          <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">SoundEffects.PlaySoundEffect(<span style="color: #006080">"pop1.wma"</span>);</pre>
        </div>
        <p>
 
</p>
        <p>
If at any point we need to delay the sound effect slightly, we can control this be
introducing a short delay:
</p>
        <div>
          <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">DelayedAction.Execute(2.0, () =&gt; SoundEffects.PlaySoundEffect(<span style="color: #006080">"pop1.wma"</span>));</pre>
        </div>
        <p>
 
</p>
        <p>
Complete Source Code for DelayedAction.cs:
</p>
        <div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
          <div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 1:</span>
              <span style="color: #0000ff">using</span> System;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 2:</span>
              <span style="color: #0000ff">using</span> System.ComponentModel;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 3:</span>
              <span style="color: #0000ff">using</span> System.Threading;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 4:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 5:</span>
              <span style="color: #0000ff">namespace</span> Wintellect.SilverlightToolbox</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 6:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 7:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> DelayedAction</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 8:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 9:</span>
              <span style="color: #0000ff">class</span> DelayedCallback</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 10:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 11:</span>
              <span style="color: #0000ff">public</span> TimeSpan
Delay { get; set; }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 12:</span>
              <span style="color: #0000ff">public</span> Action
Callback { get; set; }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 13:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 14:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 15:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> Execute(<span style="color: #0000ff">double</span> seconds,
Action callback)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 16:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 17:</span> BackgroundWorker
Delay = <span style="color: #0000ff">new</span> BackgroundWorker();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 18:</span> Delay.DoWork
+= (s, e) =&gt;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 19:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 20:</span> DelayedCallback
DelayCallback = (DelayedCallback)e.Argument;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 21:</span> Thread.Sleep(DelayCallback.Delay);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 22:</span> e.Result
= DelayCallback.Callback;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 23:</span> };</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 24:</span> Delay.RunWorkerCompleted
+= (s, e) =&gt;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 25:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 26:</span> Action
Callback = e.Result <span style="color: #0000ff">as</span> Action;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 27:</span> Callback();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 28:</span> };</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 29:</span> Delay.RunWorkerAsync(<span style="color: #0000ff">new</span> DelayedCallback</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 30:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 31:</span> Delay
= TimeSpan.FromSeconds(seconds),</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 32:</span> Callback
= callback</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 33:</span> });</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 34:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 35:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 36:</span> }</pre>
          </div>
        </div>
        <p>
 
</p>
        <p>
Complete Source Code for SoundEffects.cs:
</p>
        <div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
          <div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 1:</span>
              <span style="color: #0000ff">using</span> System;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 2:</span>
              <span style="color: #0000ff">using</span> System.Collections.Generic;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 3:</span>
              <span style="color: #0000ff">using</span> System.IO;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 4:</span>
              <span style="color: #0000ff">using</span> System.Net;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 5:</span>
              <span style="color: #0000ff">using</span> System.Windows;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 6:</span>
              <span style="color: #0000ff">using</span> System.Windows.Controls;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 7:</span>
              <span style="color: #0000ff">using</span> System.Windows.Media;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 8:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 9:</span>
              <span style="color: #0000ff">namespace</span> Wintellect.SilverlightToolbox</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 10:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 11:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">class</span> SoundEffects</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 12:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 13:</span>
              <span style="color: #0000ff">static</span> Panel
Root;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 14:</span>
              <span style="color: #0000ff">static</span> MediaElement
BackgroundLoop = <span style="color: #0000ff">new</span> MediaElement();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 15:</span>
              <span style="color: #0000ff">static</span> WebClient
EffectDownloader = <span style="color: #0000ff">new</span> WebClient();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 16:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 17:</span>
              <span style="color: #0000ff">static</span> Queue&lt;MediaElement&gt;
AvailableSoundEffectGenerators = <span style="color: #0000ff">new</span> Queue&lt;MediaElement&gt;();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 18:</span>
              <span style="color: #0000ff">static</span> Dictionary&lt;<span style="color: #0000ff">string</span>,
Stream&gt; DownloadedEffects = <span style="color: #0000ff">new</span> Dictionary&lt;<span style="color: #0000ff">string</span>,
Stream&gt;();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 19:</span>
              <span style="color: #0000ff">static</span> Queue&lt;<span style="color: #0000ff">string</span>&gt;
PendingDownloads = <span style="color: #0000ff">new</span> Queue&lt;<span style="color: #0000ff">string</span>&gt;();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 20:</span>
              <span style="color: #0000ff">static</span> Queue&lt;QueuedEffect&gt;
PendingEffects = <span style="color: #0000ff">new</span> Queue&lt;QueuedEffect&gt;();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 21:</span>
              <span style="color: #0000ff">static</span> Dictionary&lt;MediaElement,
Action&gt; PendingStartupCallbacks = <span style="color: #0000ff">new</span> Dictionary&lt;MediaElement,
Action&gt;();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 22:</span>
              <span style="color: #0000ff">static</span> Dictionary&lt;MediaElement,
Action&gt; PendingCompletionCallbacks = <span style="color: #0000ff">new</span> Dictionary&lt;MediaElement,
Action&gt;();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 23:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 24:</span>
              <span style="color: #0000ff">enum</span> TargetType</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 25:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 26:</span> BackgroundMusic,</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 27:</span> SoundEffect,</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 28:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 29:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 30:</span>
              <span style="color: #0000ff">class</span> QueuedEffect</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 31:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 32:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">string</span> MediaName
{ get; set; }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 33:</span>
              <span style="color: #0000ff">public</span> TargetType
Target { get; set; }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 34:</span>
              <span style="color: #0000ff">public</span> Action
StartedCallback { get; set; }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 35:</span>
              <span style="color: #0000ff">public</span> Action
CompletedCallback { get; set; }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 36:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 37:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 38:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> Initialize(Panel
root)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 39:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 40:</span> Root
= root;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 41:</span> InitializeTarget(root,
BackgroundLoop);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 42:</span> EffectDownloader.OpenReadCompleted
+= (s, e) =&gt;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 43:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 44:</span> DownloadedEffects[(<span style="color: #0000ff">string</span>)e.UserState]
= e.Result;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 45:</span> DownloadEffects();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 46:</span> PlayEffect();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 47:</span> };</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 48:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 49:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 50:</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> DownloadEffects()</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 51:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 52:</span>
              <span style="color: #0000ff">if</span> (PendingDownloads.Count
== 0)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 53:</span>
              <span style="color: #0000ff">return</span>;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 54:</span>
              <span style="color: #0000ff">string</span> MediaName
= PendingDownloads.Dequeue();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 55:</span> EffectDownloader.OpenReadAsync(<span style="color: #0000ff">new</span> Uri(MediaName,
UriKind.Relative), MediaName);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 56:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 57:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 58:</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> InitializeTarget(Panel
root, MediaElement target)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 59:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 60:</span> target.Width
= 0;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 61:</span> target.Height
= 0;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 62:</span> target.Visibility
= Visibility.Collapsed;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 63:</span> root.Children.Add(target);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 64:</span> target.AutoPlay
= <span style="color: #0000ff">false</span>;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 65:</span> target.MediaOpened
+= (s, e) =&gt;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 66:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 67:</span> MediaElement
Target = s <span style="color: #0000ff">as</span> MediaElement;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 68:</span> Target.Volume
= 0.35;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 69:</span> Target.Play();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 70:</span>
              <span style="color: #0000ff">if</span> (PendingStartupCallbacks.ContainsKey(Target))</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 71:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 72:</span> Target.Dispatcher.BeginInvoke(PendingStartupCallbacks[Target]);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 73:</span> PendingStartupCallbacks.Remove(Target);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 74:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 75:</span> };</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 76:</span> target.MediaEnded
+= (s, e) =&gt;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 77:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 78:</span> MediaElement
Target = s <span style="color: #0000ff">as</span> MediaElement;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 79:</span> Target.Stop();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 80:</span>
              <span style="color: #0000ff">if</span> (s
== BackgroundLoop)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 81:</span> Target.Play();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 82:</span>
              <span style="color: #0000ff">else</span>
            </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 83:</span> AvailableSoundEffectGenerators.Enqueue(Target);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 84:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 85:</span>
              <span style="color: #0000ff">if</span> (PendingCompletionCallbacks.ContainsKey(Target))</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 86:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 87:</span> Target.Dispatcher.BeginInvoke(PendingCompletionCallbacks[Target]);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 88:</span> PendingCompletionCallbacks.Remove(Target);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 89:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 90:</span> };</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 91:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 92:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 93:</span>
              <span style="color: #0000ff">static</span> MediaElement
GetUnusedEffectGenerator()</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 94:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 95:</span>
              <span style="color: #0000ff">if</span> (AvailableSoundEffectGenerators.Count
&gt; 0)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 96:</span>
              <span style="color: #0000ff">return</span> AvailableSoundEffectGenerators.Dequeue();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 97:</span>
              <span style="color: #0000ff">else</span>
            </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 98:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 99:</span> MediaElement
Result = <span style="color: #0000ff">new</span> MediaElement();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 100:</span> InitializeTarget(Root,
Result);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 101:</span>
              <span style="color: #0000ff">return</span> Result;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 102:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 103:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 104:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 105:</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> PlayEffect()</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 106:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 107:</span>
              <span style="color: #0000ff">lock</span> (PendingEffects)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 108:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 109:</span>
              <span style="color: #0000ff">if</span> (PendingEffects.Count
== 0)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 110:</span>
              <span style="color: #0000ff">return</span>;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 111:</span> QueuedEffect
Effect = PendingEffects.Dequeue();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 112:</span>
              <span style="color: #0000ff">if</span> (DownloadedEffects.ContainsKey(Effect.MediaName))</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 113:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 114:</span> MediaElement
TargetElement = <span style="color: #0000ff">null</span>;</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 115:</span>
              <span style="color: #0000ff">switch</span> (Effect.Target)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 116:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 117:</span>
              <span style="color: #0000ff">case</span> TargetType.BackgroundMusic:</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 118:</span> {
TargetElement = BackgroundLoop; <span style="color: #0000ff">break</span>; }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 119:</span>
              <span style="color: #0000ff">case</span> TargetType.SoundEffect:</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 120:</span> {
TargetElement = GetUnusedEffectGenerator(); <span style="color: #0000ff">break</span>;
}</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 121:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 122:</span>
              <span style="color: #0000ff">if</span> (Effect.StartedCallback
!= <span style="color: #0000ff">null</span>)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 123:</span> PendingStartupCallbacks.Add(TargetElement,
Effect.StartedCallback);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 124:</span>
              <span style="color: #0000ff">if</span> (Effect.CompletedCallback
!= <span style="color: #0000ff">null</span>)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 125:</span> PendingCompletionCallbacks.Add(TargetElement,
Effect.CompletedCallback);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 126:</span> TargetElement.SetSource(DownloadedEffects[Effect.MediaName]);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 127:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 128:</span>
              <span style="color: #0000ff">else</span>
            </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 129:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 130:</span> PendingEffects.Enqueue(Effect);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 131:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 132:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 133:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 134:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 135:</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> PlaySound(TargetType
target, <span style="color: #0000ff">string</span> mediaName, Action startedCallback,
Action completedCallback)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 136:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 137:</span>
              <span style="color: #0000ff">if</span> (target
== TargetType.BackgroundMusic)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 138:</span>
              <span style="color: #0000ff">if</span> (BackgroundLoop.CurrentState
!= MediaElementState.Stopped)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 139:</span> BackgroundLoop.Stop();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 140:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 141:</span>
              <span style="color: #0000ff">if</span> (mediaName
!= String.Empty)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 142:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 143:</span>
              <span style="color: #0000ff">lock</span> (PendingEffects)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 144:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 145:</span>
              <span style="color: #0000ff">if</span> (!DownloadedEffects.ContainsKey(mediaName))</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 146:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 147:</span> PendingDownloads.Enqueue(mediaName);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 148:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 149:</span> PendingEffects.Enqueue(<span style="color: #0000ff">new</span> QueuedEffect</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 150:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 151:</span> MediaName
= mediaName,</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 152:</span> Target
= target,</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 153:</span> StartedCallback
= startedCallback,</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 154:</span> CompletedCallback
= completedCallback</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 155:</span> });</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 156:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 157:</span> DownloadEffects();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 158:</span> PlayEffect();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 159:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 160:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 161:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 162:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> SetBackgroundLoop(<span style="color: #0000ff">string</span> mediaName)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 163:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 164:</span> PlaySound(TargetType.BackgroundMusic,
mediaName, <span style="color: #0000ff">null</span>, <span style="color: #0000ff">null</span>);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 165:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 166:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 167:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> PlaySoundEffect(<span style="color: #0000ff">string</span> effectName)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 168:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 169:</span> PlaySound(TargetType.SoundEffect,
effectName, <span style="color: #0000ff">null</span>, <span style="color: #0000ff">null</span>);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 170:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 171:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 172:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> PlaySoundEffect(<span style="color: #0000ff">string</span> effectName,
Action startedCallback, Action completedCallback)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 173:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 174:</span> PlaySound(TargetType.SoundEffect,
effectName, startedCallback, completedCallback);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 175:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 176:</span>  </pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 177:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> PreloadMedia(<span style="color: #0000ff">string</span> mediaName)</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 178:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 179:</span>
              <span style="color: #0000ff">if</span> (!DownloadedEffects.ContainsKey(mediaName))</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 180:</span> {</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 181:</span> PendingDownloads.Enqueue(mediaName);</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 182:</span> DownloadEffects();</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 183:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 184:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 185:</span> }</pre>
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span style="color: #606060"> 186:</span> }</pre>
          </div>
        </div>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=ce802397-894c-4772-994b-5d5ba4df3fda" />
      </body>
      <title>A Simple Sound Effects Engine for Silverlight 2</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,ce802397-894c-4772-994b-5d5ba4df3fda.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2008/06/09/ASimpleSoundEffectsEngineForSilverlight2.aspx</link>
      <pubDate>Mon, 09 Jun 2008 21:59:22 GMT</pubDate>
      <description>&lt;p&gt;
Audio support is all too often one of the last things a developer thinks of when it
comes to building a user interface. Fortunately, Silverlight offers some basic building
blocks that make it fairly trivial to add event-driven sounds to our applications.
I have taken the built-in functionality one step further, and created a simple run-time
audio engine that makes it even easier.
&lt;/p&gt;
&lt;p&gt;
First, I will discuss the requirements that I had in mind when I created this engine.
Second, I will discuss the ideal API for a complete solution. Third, I submit the
simple effects engine that I developed in order to meet those requirements and API.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Sound Effects Engine Requirements&lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Must be able to play looping “background music” tracks. 
&lt;/li&gt;
&lt;li&gt;
Must be able to play smaller sound effects on demand. 
&lt;/li&gt;
&lt;li&gt;
Must support concurrent (and overlapping) sounds effects without interfering with
already-playing audio. 
&lt;/li&gt;
&lt;li&gt;
Must adequately handle the possibility of download delays when pulling down external
audio files. 
&lt;/li&gt;
&lt;li&gt;
Should cache audio files between playbacks. 
&lt;/li&gt;
&lt;li&gt;
Should allow serving of audio from high-bandwidth CDN such as Silverlight Streaming. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;strong&gt;An Ideal Sound Effects API&lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Should be very approachable. If possible, only a single line of code to play any audio
(similar to PlaySound() API). 
&lt;/li&gt;
&lt;li&gt;
Should support any formats supported by Silverlight. 
&lt;/li&gt;
&lt;li&gt;
Should be efficient. 
&lt;/li&gt;
&lt;li&gt;
Should offer download and playback completion callbacks (for chaining and synchronization). 
&lt;/li&gt;
&lt;li&gt;
Should support aggressive background pre-caching of audio files. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;strong&gt;The SilverlightToolbox Solution&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
To address the simplicity requirements, this sound effects engine is implemented as
a single static C# class that can be easily included into any Silverlight project.
It can exist in a referenced class library, or can be linked directly into the main
project.
&lt;/p&gt;
&lt;p&gt;
To address looping background music, a single method SetBackgroundLoop() is supplied.
This will begin playback of a single audio clip, and will automatically repeat it.
Only one track can be played as the background loop – calling this method again will
terminate the running track and start the new one. You can also pass String.Empty
to stop all background music.
&lt;/p&gt;
&lt;p&gt;
To address typical sound effect clips. two overloads of the PlaySoundEffect() method
are supplied. The simpler of the two methods will simply play a clip once it has been
downloaded. The extended version allows you to specify a callback for when the clip
has been downloaded and started playing, and a second callback that can be used for
notification that the clip has ended.
&lt;/p&gt;
&lt;p&gt;
To address the scenario where multiple sound effects might be played at the same time,
the engine internally maintains a queue of MediaElements. When a new sound needs to
played, it pulls an unused element and puts it into service. Once the sound is finished,
the element is returned to the queue. This allows Silverlight itself to handle media
mixing, and by caching those MediaElements, it does so without placing undue stress
on the environment.
&lt;/p&gt;
&lt;p&gt;
To address the issue of download delays, the startedCallback and completedCallback
parameters of PlaySoundEffect() were introduced.
&lt;/p&gt;
&lt;p&gt;
To address caching of audio files, a WebClient is used (which in turn leverages the
browser’s cache). Furthermore, the engine will reuse any downloaded file streams (and
is smart enough to not re-queue the same file if it already queued for download).
&lt;/p&gt;
&lt;p&gt;
By using a MediaElement for playback, audio tracks are automatically supported from
streaming sources and Content Delivery Networks, and can be of any type supported
by Silverlight.
&lt;/p&gt;
&lt;p&gt;
To support chaining of audio effects, and to support synchronization of UI with audio,
the PlaySoundEffect() method accepts callback events that are fired when the clip
has been downloaded, and again when it has completed playback. To further help with
UI synchronization, a second utility class is provided (DelayedAction) which provides
a simple wrapper for BackgroundWorker that can be used to easily delay execution of
a block of code after a specified amount of time.
&lt;/p&gt;
&lt;p&gt;
To support pre-caching of audio files, the PreloadMedia() method can be used.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Typical usage:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
In order for the sound effects engine to function properly, it must be provided with
a top-level XAML container (MediaElement currently will not perform playback without
a parent object). This is done by calling the Initialize() method, typically from
your program’s startup code:
&lt;/p&gt;
&lt;div&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;SoundEffects.Initialize(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.LayoutRoot);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
After this has been done, background music can be played, and we can also queue up
some sound effect clips for later:
&lt;/p&gt;
&lt;div&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;SoundEffects.SetBackgroundLoop(&lt;span style="color: #006080"&gt;&amp;quot;cautious-path.wma&amp;quot;&lt;/span&gt;);
SoundEffects.PreloadMedia(&lt;span style="color: #006080"&gt;&amp;quot;pop1.wma&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
Then, at various points throughout the application, we can play the sound effect (for
example, in response to a control event):
&lt;/p&gt;
&lt;div&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;SoundEffects.PlaySoundEffect(&lt;span style="color: #006080"&gt;&amp;quot;pop1.wma&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
If at any point we need to delay the sound effect slightly, we can control this be
introducing a short delay:
&lt;/p&gt;
&lt;div&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;DelayedAction.Execute(2.0, () =&amp;gt; SoundEffects.PlaySoundEffect(&lt;span style="color: #006080"&gt;&amp;quot;pop1.wma&amp;quot;&lt;/span&gt;));&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
Complete Source Code for DelayedAction.cs:
&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.ComponentModel;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Threading;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 4:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Wintellect.SilverlightToolbox&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 6:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DelayedAction&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 8:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DelayedCallback&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 10:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; TimeSpan
Delay { get; set; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Action
Callback { get; set; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 13:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 14:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 15:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Execute(&lt;span style="color: #0000ff"&gt;double&lt;/span&gt; seconds,
Action callback)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 16:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 17:&lt;/span&gt; BackgroundWorker
Delay = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; BackgroundWorker();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 18:&lt;/span&gt; Delay.DoWork
+= (s, e) =&amp;gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 19:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 20:&lt;/span&gt; DelayedCallback
DelayCallback = (DelayedCallback)e.Argument;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 21:&lt;/span&gt; Thread.Sleep(DelayCallback.Delay);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 22:&lt;/span&gt; e.Result
= DelayCallback.Callback;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 23:&lt;/span&gt; };&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 24:&lt;/span&gt; Delay.RunWorkerCompleted
+= (s, e) =&amp;gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 25:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 26:&lt;/span&gt; Action
Callback = e.Result &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; Action;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 27:&lt;/span&gt; Callback();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 28:&lt;/span&gt; };&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 29:&lt;/span&gt; Delay.RunWorkerAsync(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DelayedCallback&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 30:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 31:&lt;/span&gt; Delay
= TimeSpan.FromSeconds(seconds),&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 32:&lt;/span&gt; Callback
= callback&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 33:&lt;/span&gt; });&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 34:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 35:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 36:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
Complete Source Code for SoundEffects.cs:
&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.IO;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Net;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Windows;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Windows.Controls;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Windows.Media;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 8:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; Wintellect.SilverlightToolbox&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 10:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SoundEffects&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 12:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 13:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Panel
Root;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 14:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; MediaElement
BackgroundLoop = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MediaElement();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 15:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; WebClient
EffectDownloader = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WebClient();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 16:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 17:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Queue&amp;lt;MediaElement&amp;gt;
AvailableSoundEffectGenerators = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Queue&amp;lt;MediaElement&amp;gt;();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 18:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;,
Stream&amp;gt; DownloadedEffects = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;,
Stream&amp;gt;();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 19:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Queue&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;
PendingDownloads = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Queue&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 20:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Queue&amp;lt;QueuedEffect&amp;gt;
PendingEffects = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Queue&amp;lt;QueuedEffect&amp;gt;();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 21:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Dictionary&amp;lt;MediaElement,
Action&amp;gt; PendingStartupCallbacks = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Dictionary&amp;lt;MediaElement,
Action&amp;gt;();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 22:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Dictionary&amp;lt;MediaElement,
Action&amp;gt; PendingCompletionCallbacks = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Dictionary&amp;lt;MediaElement,
Action&amp;gt;();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 23:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 24:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;enum&lt;/span&gt; TargetType&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 25:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 26:&lt;/span&gt; BackgroundMusic,&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 27:&lt;/span&gt; SoundEffect,&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 28:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 29:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 30:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; QueuedEffect&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 31:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 32:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; MediaName
{ get; set; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 33:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; TargetType
Target { get; set; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 34:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Action
StartedCallback { get; set; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 35:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Action
CompletedCallback { get; set; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 36:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 37:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 38:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Initialize(Panel
root)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 39:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 40:&lt;/span&gt; Root
= root;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 41:&lt;/span&gt; InitializeTarget(root,
BackgroundLoop);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 42:&lt;/span&gt; EffectDownloader.OpenReadCompleted
+= (s, e) =&amp;gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 43:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 44:&lt;/span&gt; DownloadedEffects[(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;)e.UserState]
= e.Result;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 45:&lt;/span&gt; DownloadEffects();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 46:&lt;/span&gt; PlayEffect();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 47:&lt;/span&gt; };&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 48:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 49:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 50:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DownloadEffects()&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 51:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 52:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (PendingDownloads.Count
== 0)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 53:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 54:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; MediaName
= PendingDownloads.Dequeue();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 55:&lt;/span&gt; EffectDownloader.OpenReadAsync(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri(MediaName,
UriKind.Relative), MediaName);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 56:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 57:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 58:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; InitializeTarget(Panel
root, MediaElement target)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 59:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 60:&lt;/span&gt; target.Width
= 0;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 61:&lt;/span&gt; target.Height
= 0;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 62:&lt;/span&gt; target.Visibility
= Visibility.Collapsed;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 63:&lt;/span&gt; root.Children.Add(target);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 64:&lt;/span&gt; target.AutoPlay
= &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 65:&lt;/span&gt; target.MediaOpened
+= (s, e) =&amp;gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 66:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 67:&lt;/span&gt; MediaElement
Target = s &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; MediaElement;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 68:&lt;/span&gt; Target.Volume
= 0.35;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 69:&lt;/span&gt; Target.Play();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 70:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (PendingStartupCallbacks.ContainsKey(Target))&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 71:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 72:&lt;/span&gt; Target.Dispatcher.BeginInvoke(PendingStartupCallbacks[Target]);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 73:&lt;/span&gt; PendingStartupCallbacks.Remove(Target);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 74:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 75:&lt;/span&gt; };&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 76:&lt;/span&gt; target.MediaEnded
+= (s, e) =&amp;gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 77:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 78:&lt;/span&gt; MediaElement
Target = s &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; MediaElement;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 79:&lt;/span&gt; Target.Stop();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 80:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (s
== BackgroundLoop)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 81:&lt;/span&gt; Target.Play();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 82:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 83:&lt;/span&gt; AvailableSoundEffectGenerators.Enqueue(Target);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 84:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 85:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (PendingCompletionCallbacks.ContainsKey(Target))&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 86:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 87:&lt;/span&gt; Target.Dispatcher.BeginInvoke(PendingCompletionCallbacks[Target]);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 88:&lt;/span&gt; PendingCompletionCallbacks.Remove(Target);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 89:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 90:&lt;/span&gt; };&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 91:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 92:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 93:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; MediaElement
GetUnusedEffectGenerator()&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 94:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 95:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (AvailableSoundEffectGenerators.Count
&amp;gt; 0)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 96:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; AvailableSoundEffectGenerators.Dequeue();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 97:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 98:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 99:&lt;/span&gt; MediaElement
Result = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MediaElement();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 100:&lt;/span&gt; InitializeTarget(Root,
Result);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 101:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Result;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 102:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 103:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 104:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 105:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PlayEffect()&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 106:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 107:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;lock&lt;/span&gt; (PendingEffects)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 108:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 109:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (PendingEffects.Count
== 0)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 110:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 111:&lt;/span&gt; QueuedEffect
Effect = PendingEffects.Dequeue();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 112:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (DownloadedEffects.ContainsKey(Effect.MediaName))&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 113:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 114:&lt;/span&gt; MediaElement
TargetElement = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 115:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;switch&lt;/span&gt; (Effect.Target)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 116:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 117:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; TargetType.BackgroundMusic:&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 118:&lt;/span&gt; {
TargetElement = BackgroundLoop; &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 119:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; TargetType.SoundEffect:&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 120:&lt;/span&gt; {
TargetElement = GetUnusedEffectGenerator(); &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;
}&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 121:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 122:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Effect.StartedCallback
!= &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 123:&lt;/span&gt; PendingStartupCallbacks.Add(TargetElement,
Effect.StartedCallback);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 124:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Effect.CompletedCallback
!= &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 125:&lt;/span&gt; PendingCompletionCallbacks.Add(TargetElement,
Effect.CompletedCallback);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 126:&lt;/span&gt; TargetElement.SetSource(DownloadedEffects[Effect.MediaName]);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 127:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 128:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 129:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 130:&lt;/span&gt; PendingEffects.Enqueue(Effect);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 131:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 132:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 133:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 134:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 135:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PlaySound(TargetType
target, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; mediaName, Action startedCallback,
Action completedCallback)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 136:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 137:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (target
== TargetType.BackgroundMusic)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 138:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (BackgroundLoop.CurrentState
!= MediaElementState.Stopped)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 139:&lt;/span&gt; BackgroundLoop.Stop();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 140:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 141:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mediaName
!= String.Empty)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 142:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 143:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;lock&lt;/span&gt; (PendingEffects)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 144:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 145:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!DownloadedEffects.ContainsKey(mediaName))&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 146:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 147:&lt;/span&gt; PendingDownloads.Enqueue(mediaName);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 148:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 149:&lt;/span&gt; PendingEffects.Enqueue(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; QueuedEffect&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 150:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 151:&lt;/span&gt; MediaName
= mediaName,&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 152:&lt;/span&gt; Target
= target,&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 153:&lt;/span&gt; StartedCallback
= startedCallback,&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 154:&lt;/span&gt; CompletedCallback
= completedCallback&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 155:&lt;/span&gt; });&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 156:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 157:&lt;/span&gt; DownloadEffects();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 158:&lt;/span&gt; PlayEffect();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 159:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 160:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 161:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 162:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SetBackgroundLoop(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; mediaName)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 163:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 164:&lt;/span&gt; PlaySound(TargetType.BackgroundMusic,
mediaName, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 165:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 166:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 167:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PlaySoundEffect(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; effectName)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 168:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 169:&lt;/span&gt; PlaySound(TargetType.SoundEffect,
effectName, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 170:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 171:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 172:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PlaySoundEffect(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; effectName,
Action startedCallback, Action completedCallback)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 173:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 174:&lt;/span&gt; PlaySound(TargetType.SoundEffect,
effectName, startedCallback, completedCallback);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 175:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 176:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 177:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PreloadMedia(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; mediaName)&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 178:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 179:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!DownloadedEffects.ContainsKey(mediaName))&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 180:&lt;/span&gt; {&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 181:&lt;/span&gt; PendingDownloads.Enqueue(mediaName);&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 182:&lt;/span&gt; DownloadEffects();&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 183:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 184:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 185:&lt;/span&gt; }&lt;/pre&gt;
&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt; 186:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=ce802397-894c-4772-994b-5d5ba4df3fda" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,ce802397-894c-4772-994b-5d5ba4df3fda.aspx</comments>
      <category>.NET</category>
      <category>Games</category>
      <category>General</category>
      <category>Media</category>
      <category>Silverlight</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=e62d8fa0-1b92-4906-aff2-8fbd0b25a501</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,e62d8fa0-1b92-4906-aff2-8fbd0b25a501.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,e62d8fa0-1b92-4906-aff2-8fbd0b25a501.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=e62d8fa0-1b92-4906-aff2-8fbd0b25a501</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I have been running a Media Center PC as the hub of my home media network for a few
years now - first MCE 2005 and then VMC (Vista Media Center) once it became available.
In fact, I am about to install my 3rd XBOX 360 in my house (I use those as media extenders
wherever I have a TV). I love my media setup - and more importantly - so does my wife.
</p>
        <p>
I pretty much just let things run and don't think too often about it... but this week
I ran across this completely awesome application which makes my setup even better... <a href="http://www.lifextender.com/">Lifextender</a>.
</p>
        <p>
Lifextender has a very simple premise, which is stated on the home page of it's website:
"Lifextender is a dead-simple commercial-removal application". The program basically
runs in the background where it monitors your system for new recordings. It then analyzes
those recordings and removes any commercial pods that it finds. It is pretty good
- I would say the success rate is about 95%. When it makes it mistake, it seems to
always err on the side of caution and has never removed something I didn't want it
to. The modified recordings are about 75% of the size of of the originals - which
means it is literally giving me back 15 minutes of my life for every "hour" of commercial-infested
programming that I watch.
</p>
        <p>
And oh did I mention - It's also FREE (free as in beer)!
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=e62d8fa0-1b92-4906-aff2-8fbd0b25a501" />
      </body>
      <title>Awesome tool for Media Center - Lifextender</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,e62d8fa0-1b92-4906-aff2-8fbd0b25a501.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2008/04/03/AwesomeToolForMediaCenterLifextender.aspx</link>
      <pubDate>Thu, 03 Apr 2008 22:46:12 GMT</pubDate>
      <description>&lt;p&gt;
I have been running a Media Center PC as the hub of my home media network for a few
years now - first MCE 2005 and then VMC (Vista Media Center) once it became available.
In fact, I am about to install my 3rd XBOX 360 in my house (I use those as media extenders
wherever I have a TV). I love my media setup - and more importantly - so does my wife.
&lt;/p&gt;
&lt;p&gt;
I pretty much just let things run and don't think too often about it... but this week
I ran across this completely awesome application which makes my setup even better... &lt;a href="http://www.lifextender.com/"&gt;Lifextender&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Lifextender has a very simple premise, which is stated on the home page of it's website:
"Lifextender is a dead-simple commercial-removal application". The program basically
runs in the background where it monitors your system for new recordings. It then analyzes
those recordings and removes any commercial pods that it finds. It is pretty good
- I would say the success rate is about 95%. When it makes it mistake, it seems to
always err on the side of caution and has never removed something I didn't want it
to. The modified recordings are about 75% of the size of of the originals - which
means it is literally giving me back 15 minutes of my life for every "hour" of commercial-infested
programming that I watch.
&lt;/p&gt;
&lt;p&gt;
And oh did I mention - It's also FREE (free as in beer)!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=e62d8fa0-1b92-4906-aff2-8fbd0b25a501" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,e62d8fa0-1b92-4906-aff2-8fbd0b25a501.aspx</comments>
      <category>General</category>
      <category>Media</category>
      <category>Tips and Tricks</category>
      <category>Vista</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=0b7336ef-f3af-4366-b376-4b99a3dbfc56</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,0b7336ef-f3af-4366-b376-4b99a3dbfc56.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,0b7336ef-f3af-4366-b376-4b99a3dbfc56.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=0b7336ef-f3af-4366-b376-4b99a3dbfc56</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I ran into a small, but dastardly quirk in Silverlight today. I haven't seen it mentioned
out there so figured I would post this in case someone else might suffer from the
same problem someday...
</p>
        <p>
If you have a MediaElement being used to display video, chances are pretty good that
you also have what is known as a "scrub bar". or at least some buttons used to jump
forward or backward in the video timeline. The documentation says that you can accomplish
this by interacting with the Position property of the MediaElement. The Position property
is of type TimeSpan, which is documented as being immutable except for the Seconds
property, which is read/write. In other words, the only way to change the current
playback position of a playing media element is to set Position.Seconds to the location
you wish to jump to.
</p>
        <p>
The only thing is - this actually doesn't work if you take the documentation at face
value. This bit of code doesn't work as you might think it would:
</p>
        <blockquote>
          <p>
            <font face="Courier New" size="3">MyVideo.Position.Seconds = MyVideo.Position.Seconds
+ 10.0;</font>
          </p>
        </blockquote>
        <p>
In fact, that code has no effect at all. No error message, but also no change to the
position.
</p>
        <p>
The secret here is that while the TimeSpan is indeed modifiable through the Seconds
property, the MediaElement doesn't really care about it unless you reassign the Position
property itself. To compound this, there is no way to create your own TimeSpan from
code in Silverlight 1.0, so the only option we have is to take an existing one. Here
is the code to change the current position (which actually works):
</p>
        <blockquote>
          <p>
            <font face="Courier New" size="3">var pos = MyVideo.Position;</font>
          </p>
          <p>
            <font face="Courier New" size="3">pos.Seconds = pos.Seconds + 10.0;</font>
          </p>
          <p>
            <font face="Courier New" size="3">MyVideo.Position = pos;</font>
          </p>
        </blockquote>
        <p>
HTH
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=0b7336ef-f3af-4366-b376-4b99a3dbfc56" />
      </body>
      <title>Performing Seek operations in Silverlight on a MediaElement</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,0b7336ef-f3af-4366-b376-4b99a3dbfc56.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2008/01/07/PerformingSeekOperationsInSilverlightOnAMediaElement.aspx</link>
      <pubDate>Mon, 07 Jan 2008 20:09:59 GMT</pubDate>
      <description>&lt;p&gt;
I ran into a small, but dastardly quirk in Silverlight today. I haven't seen it mentioned
out there so figured I would post this in case someone else might suffer from the
same problem someday...
&lt;/p&gt;
&lt;p&gt;
If you have a MediaElement being used to display video, chances are pretty good that
you also have what is known as a "scrub bar". or at least some buttons used to jump
forward or backward in the video timeline. The documentation says that you can accomplish
this by interacting with the Position property of the MediaElement. The Position property
is of type TimeSpan, which is documented as being immutable except for the Seconds
property, which is read/write. In other words, the only way to change the current
playback position of a playing media element is to set Position.Seconds to the location
you wish to jump to.
&lt;/p&gt;
&lt;p&gt;
The only thing is - this actually doesn't work if you take the documentation at face
value. This bit of code doesn't work as you might think it would:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New" size=3&gt;MyVideo.Position.Seconds = MyVideo.Position.Seconds
+ 10.0;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
In fact, that code has no effect at all. No error message, but also no change to the
position.
&lt;/p&gt;
&lt;p&gt;
The secret here is that while the TimeSpan is indeed modifiable through the Seconds
property, the MediaElement doesn't really care about it unless you reassign the Position
property itself. To compound this, there is no way to create your own TimeSpan from
code in Silverlight 1.0, so the only option we have is to take an existing one. Here
is the code to change the current position (which actually works):
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New" size=3&gt;var pos = MyVideo.Position;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size=3&gt;pos.Seconds = pos.Seconds + 10.0;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size=3&gt;MyVideo.Position = pos;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
HTH
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=0b7336ef-f3af-4366-b376-4b99a3dbfc56" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,0b7336ef-f3af-4366-b376-4b99a3dbfc56.aspx</comments>
      <category>General</category>
      <category>Silverlight</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=4f8bb2fc-43be-4898-ba71-b2402162a612</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,4f8bb2fc-43be-4898-ba71-b2402162a612.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,4f8bb2fc-43be-4898-ba71-b2402162a612.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=4f8bb2fc-43be-4898-ba71-b2402162a612</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I ran into this nasty little bug today... it is not easy to reproduce, but when it
happens it is very annoying to debug.
</p>
        <p>
First, this bug only occurs when you are using a ZIP file to package your external
resources and using a Silverlight Downloader object to bring the package to the browser,
and subsequently using Image.SetSource() to provide the image files to the visual
elements.
</p>
        <p>
Second, it's not really a <em>bug in functionality</em> exactly, but more of a nuisance
to the viewer. You see, the images get displayed correctly, but Silverlight throws
extra error messages.
</p>
        <p>
The problem occurs when you reuse a single image resource from a downloaded zip archive
for multiple Image elements. And it only happens when the two images are assigned
to the same resource consecutively. Example:
</p>
        <p>
          <code>
            <b>function</b>
            <b> downloadComplete(sender, eventArgs)</b>
            <br />
            <b>{</b>
            <br />
            <b>  // this one is OK</b>
            <br />
            <b>  sender.GetHost().FindName(“Image1”).SetSource(sender, “picture.png”);</b>
            <br />
            <b>  // this one fails</b>
            <br />
            <b>  sender.GetHost().FindName(“Image2”).SetSource(sender, “picture.png”);</b>
            <br />
            <b>}</b>
          </code>
        </p>
        <p>
This is using Silverlight 1.0, but I assume the same issue also happens in 1.1.
</p>
        <p>
The problem appears to be related to referencing the same resource twice consecutively.
If you reference another resource from the Downloader between the two calls to SetSource(),
then the problem goes away. Also, if you simply don't reuse the same resource like
this, then it can be avoided.
</p>
        <p>
          <em>
            <font color="#ff0000">UPDATE January 2008: My previous "fix" of referencing another
resource in between uses of the same resource does not seem to always work. In addition,
some Silverlight installations (not all!) are also raising spurious ImageError 4001
messages. The only complete fix I have found is to implement a custom error handler,
and ignore those ImageErrors:</font>
          </em>
        </p>
        <p>
          <code>
            <strong>function </strong>handleError(sender, errorArgs) 
<br /><b>{</b><br /><strong>  </strong>if (errorArgs.errorType == "ImageError" &amp;&amp; errorArgs.errorCode
== 3002)<br />
    {<br />
      // This error is raised sporadically by SetSource<br />
      return;<br />
    }<br />
    if (errorArgs.errorType == "ImageError" &amp;&amp; errorArgs.errorCode
== 4001)<br />
    {<br />
      // This error is raised sporadically by SetSource<br />
      return;<br />
    }<br />
  Silverlight.default_error_handler(sender, errorArgs); 
<br /><b>}</b></code>
        </p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=4f8bb2fc-43be-4898-ba71-b2402162a612" />
      </body>
      <title>Silverlight Bug: Using a packaged image source for multiple Image elements</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,4f8bb2fc-43be-4898-ba71-b2402162a612.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2007/12/01/SilverlightBugUsingAPackagedImageSourceForMultipleImageElements.aspx</link>
      <pubDate>Sat, 01 Dec 2007 05:15:55 GMT</pubDate>
      <description>&lt;p&gt;
I ran into this nasty little bug today... it is not easy to reproduce, but when it
happens it is very annoying to debug.
&lt;/p&gt;
&lt;p&gt;
First, this bug only occurs when you are using a ZIP file to package your external
resources and using a Silverlight Downloader object to bring the package to the browser,
and subsequently using Image.SetSource() to provide the image files to the visual
elements.
&lt;/p&gt;
&lt;p&gt;
Second, it's not really a &lt;em&gt;bug in functionality&lt;/em&gt; exactly, but more of a nuisance
to the viewer. You see, the images get displayed correctly, but Silverlight throws
extra error messages.
&lt;/p&gt;
&lt;p&gt;
The problem occurs when you reuse a single image resource from a downloaded zip archive
for multiple Image elements. And it only happens when the two images are assigned
to the same resource consecutively. Example:
&lt;/p&gt;
&lt;p&gt;
&lt;code&gt;&lt;b&gt;function&lt;/b&gt;&lt;b&gt; downloadComplete(sender, eventArgs)&lt;/b&gt; 
&lt;br&gt;
&lt;b&gt;{&lt;/b&gt; 
&lt;br&gt;
&lt;b&gt;&amp;nbsp; // this one is OK&lt;/b&gt; 
&lt;br&gt;
&lt;b&gt;&amp;nbsp; sender.GetHost().FindName(“Image1”).SetSource(sender, “picture.png”);&lt;/b&gt; 
&lt;br&gt;
&lt;b&gt;&amp;nbsp; // this one fails&lt;/b&gt; 
&lt;br&gt;
&lt;b&gt;&amp;nbsp; sender.GetHost().FindName(“Image2”).SetSource(sender, “picture.png”);&lt;/b&gt; 
&lt;br&gt;
&lt;b&gt;}&lt;/b&gt;&lt;/code&gt; 
&lt;p&gt;
This is using Silverlight 1.0, but I assume the same issue also happens in 1.1.
&lt;/p&gt;
&lt;p&gt;
The problem appears to be related to referencing the same resource twice consecutively.
If you reference another resource from the Downloader between the two calls to SetSource(),
then the problem goes away. Also, if you simply don't reuse the same resource like
this, then it can be avoided.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;font color=#ff0000&gt;UPDATE January 2008: My previous "fix" of referencing another
resource in between uses of the same resource does not seem to always work. In addition,
some Silverlight installations (not all!) are also raising spurious ImageError 4001
messages. The only complete fix I have found is to implement a custom error handler,
and ignore those ImageErrors:&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;code&gt;&lt;strong&gt;function &lt;/strong&gt;handleError(sender, errorArgs) 
&lt;br&gt;
&lt;b&gt;{&lt;/b&gt; 
&lt;br&gt;
&lt;strong&gt;&amp;nbsp; &lt;/strong&gt;if (errorArgs.errorType == "ImageError" &amp;amp;&amp;amp; errorArgs.errorCode
== 3002)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This error is raised sporadically by SetSource&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (errorArgs.errorType == "ImageError" &amp;amp;&amp;amp; errorArgs.errorCode
== 4001)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This error is raised sporadically by SetSource&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;Silverlight.default_error_handler(sender, errorArgs); 
&lt;br&gt;
&lt;b&gt;}&lt;/b&gt;&lt;/code&gt; 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=4f8bb2fc-43be-4898-ba71-b2402162a612" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,4f8bb2fc-43be-4898-ba71-b2402162a612.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Silverlight</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=6eba2c97-8453-4849-86d4-d83c800317c9</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,6eba2c97-8453-4849-86d4-d83c800317c9.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,6eba2c97-8453-4849-86d4-d83c800317c9.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=6eba2c97-8453-4849-86d4-d83c800317c9</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.mindfusioncorp.com/weblog/2007/10/23/How+To+Botch+An+Interview+And+Ensure+That+You+Will+Never+Get+An+Offer.aspx">My
last post</a> was somewhat negative. I acknowledge that. I was annoyed. Let me make
amends by posting some useful, positive information for those who find themselves
on the other end of the interview table (or phone).
</p>
        <ol>
          <li>
            <strong>
              <strike>Google</strike> Live Search your interviewer.</strong> Most recruiters
will tell you who will be performing your interview. If they don't venture the information,
then ask for it - chances are if they know then they will tell you. Take that name
and do some research. Get to know what your interviewer is most likely to be questioning
you about. If they have written a book on security best practices, then there is a
pretty good chance they will ask you questions about security. Do drop subtle hints
that you read their weblog - most tech people like to hear that - just be sparing
in it. You don't want to come off as a stalker. 
</li>
          <li>
            <strong>Be honest about your skill level.</strong> Many interviewers will ask you
how you rate yourself, so that they can judge just how delusional you are. Be honest
here. If you claim to be a 10 out of 10 in a subject area, then you had better be
an absolute expert. A 10 out of 10 is expected to know that subject inside and out,
perhaps even teach the interviewer a thing or two. Don't be too humble though. Rating
yourself as a 2 out of 10 is highly unlikely to get you into the interview room in
the first place. 
</li>
          <li>
            <strong>Don't interrupt.</strong> When the interviewer is speaking, never (and I mean
NEVER) forcibly interrupt them. I have had many interviews where the candidate would
inject words, statements, or questions while I was trying to guide the interview
towards the next topic. Doing that does not impress the interviewer with your profound
wisdom. What it does is send a clear message that you feel your thoughts are more
important than the interviewer's... which is nothing but a fast track to bottom of
the resume stack. 
</li>
          <li>
            <strong>Speak clearly.</strong> No need to shout, but you should be certain that you
speak confidently and with ample volume to be heard clearly. Avoid slang terms - especially
cursing! Try to provide concise and accurate answers, with as few "umms" as possible.
And for heavens sake, if you don't know the answer to a question, just say it rather
than trying to BS your way through it. 
</li>
          <li>
            <strong>Be prepared to ask questions about the employer's business and work environment.</strong> Even
if you already know the answers (you did research the company's website beforehand,
didn't you?). This shows an interest in the company and team. 
</li>
          <li>
            <strong>Be prepared to answer strange, sometimes seemingly irrelevant questions during
the interview.</strong> Good interviewers are not looking for right or wrong answers
to every question - they are looking for clues about how you work your way through
problems and how you are able to handle stressful situations. This is especially true
in the Consulting industry, where your reaction to a crisis is often more visible
and more important than the act of correcting the underlying problem itself. 
</li>
          <li>
            <strong>Follow-up.</strong> If you already did a technical screening and are now in
for the "big face to face" interview, chances are good that you missed at least one
of the questions during the screening. You should note those questions during the
initial interview, and research them before going to the main interview - especially
if the interviewer is the same person. Let them know that you felt compelled to research
the topic on your own time, and that you now have an answer for that missed question
if they would like to hear it. Chances are they won't want to hear the answer, but
they will take notice that you followed up and did your homework in between the interviews. 
</li>
          <li>
            <strong>Be calm.</strong> It is normal to be nervous. Some folks even have obvious
nervous twitches that come out in full color during something as stressful as an interview
(sweating, fast talking, jittering). Take a few steps to defeat those demons beforehand
- exercise rigorously the morning before your interview, this will clear your mind
and stabilize your metabolism, which helps control sweating problems. Learn some deep
breathing exercises if you need help calming down beforehand. Never, under any circumstances,
drink a "Double Vente Latte Machiatto" or other "energy drink" less than an hour before
the interview. All that caffeine will lead to a panicky interviewee that talks WAY
too fast and incoherently, and that is trying to hold their bladder for an hour. Nothing
good can come of that. 
</li>
          <li>
            <strong>Sleep well the night before.</strong> Don't study your "interview cheat sheet"
late into the night. Go to bed early, and go to bed with a clear mind. You will not
sleep well if you spend the night ruminating over those questions and answers. In
fact, I understand that taking an over-the-counter aid (if you are healthy enough)
can help. Seasickness medications such as Bonine can clear nausea from "stomach butterflies"
that might precede a stressful interview, and also have the nice side effect of being
a sleeping aid (causes drowsiness). As always, <em><u>check with your doctor</u></em> before
taking something like that. 
</li>
          <li>
            <strong>Smile.</strong> The interviewer is not only looking to see if you know the
technical answers to their questions, they are also evaluating whether they would
want to work with you on a team or not, and if you know how to enjoy working with
others. When interviewing, the measuring stick I often use is to ask myself "Would
I be comfortable having a beer after work with this person?". You might be surprised
how often the answer to that is "no" (especially in the ultra-bizarre circus of tech
workers).</li>
        </ol>
        <p>
And here is a "bonus" tip submitted by David Daughtrey...
</p>
        <p>
11. <strong>Dont eat at the Wing Factory on the night before an interview.</strong> Or
any hot wing establishment for that matter.
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=6eba2c97-8453-4849-86d4-d83c800317c9" />
      </body>
      <title>10 interview tips that will help you land a better job</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,6eba2c97-8453-4849-86d4-d83c800317c9.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2007/10/23/10InterviewTipsThatWillHelpYouLandABetterJob.aspx</link>
      <pubDate>Tue, 23 Oct 2007 18:22:18 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://www.mindfusioncorp.com/weblog/2007/10/23/How+To+Botch+An+Interview+And+Ensure+That+You+Will+Never+Get+An+Offer.aspx"&gt;My
last post&lt;/a&gt; was somewhat negative. I acknowledge that. I was annoyed. Let me make
amends by posting some useful, positive information for those who find themselves
on the other end of the interview table (or phone).
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;strike&gt;Google&lt;/strike&gt; Live Search&amp;nbsp;your interviewer.&lt;/strong&gt; Most recruiters
will tell you who will be performing your interview. If they don't venture the information,
then ask for it - chances are if they know then they will tell you. Take that name
and do some research. Get to know what your interviewer is most likely to be questioning
you about. If they have written a book on security best practices, then there is a
pretty good chance they will ask you questions about security. Do drop subtle hints
that you read their weblog - most tech people like to hear that - just be sparing
in it. You don't want to come off as a stalker. 
&lt;li&gt;
&lt;strong&gt;Be honest about your skill level.&lt;/strong&gt; Many interviewers will ask you
how you rate yourself, so that they can judge just how delusional you are. Be honest
here. If you claim to be a 10 out of 10 in a subject area, then you had better be
an absolute expert. A 10 out of 10 is expected to know that subject inside and out,
perhaps even teach the interviewer a thing or two. Don't be too humble though. Rating
yourself as a 2 out of 10 is highly unlikely to get you into the interview room in
the first place. 
&lt;li&gt;
&lt;strong&gt;Don't interrupt.&lt;/strong&gt; When the interviewer is speaking, never (and I mean
NEVER) forcibly interrupt them. I have had many interviews where the candidate would
inject words, statements,&amp;nbsp;or questions while I was trying to guide the interview
towards the next topic. Doing that does not impress the interviewer with your profound
wisdom. What it does is send a clear message that you feel your thoughts are more
important than the interviewer's... which is nothing but a fast track to bottom of
the resume stack. 
&lt;li&gt;
&lt;strong&gt;Speak clearly.&lt;/strong&gt; No need to shout, but you should be certain that you
speak confidently and with ample volume to be heard clearly. Avoid slang terms - especially
cursing! Try to provide concise and accurate answers, with as few "umms" as possible.
And for heavens sake, if you don't know the answer to a question, just say it rather
than trying to BS your way through it. 
&lt;li&gt;
&lt;strong&gt;Be prepared to ask questions about the employer's business and work environment.&lt;/strong&gt; Even
if you already know the answers (you did research the company's website beforehand,
didn't you?). This shows an interest in the company and team. 
&lt;li&gt;
&lt;strong&gt;Be prepared to answer strange, sometimes seemingly irrelevant questions during
the interview.&lt;/strong&gt; Good interviewers are not looking for right or wrong answers
to every question - they are looking for clues about how you work your way through
problems and how you are able to handle stressful situations. This is especially true
in the Consulting industry, where your reaction to a crisis is often more visible
and more&amp;nbsp;important than the act of correcting the underlying problem itself. 
&lt;li&gt;
&lt;strong&gt;Follow-up.&lt;/strong&gt; If you already did a technical screening and are now in
for the "big face to face" interview, chances are good that you missed at least one
of the questions during the screening. You should note those questions during the
initial interview, and research them before going to the main interview - especially
if the interviewer is the same person. Let them know that you felt compelled to research
the topic on your own time, and that you now have an answer for that missed question
if they would like to hear it. Chances are they won't want to hear the answer, but
they will take notice that you followed up and did your homework in between the interviews. 
&lt;li&gt;
&lt;strong&gt;Be calm.&lt;/strong&gt; It is normal to be nervous. Some folks even have obvious
nervous twitches that come out in full color during something as stressful as an interview
(sweating, fast talking, jittering). Take a few steps to defeat those demons beforehand
- exercise rigorously the morning before your interview, this will clear your mind
and stabilize your metabolism, which helps control sweating problems. Learn some deep
breathing exercises if you need help calming down beforehand. Never, under any circumstances,
drink a "Double Vente Latte Machiatto" or other "energy drink" less than an hour before
the interview. All that caffeine will lead to a panicky interviewee that talks WAY
too fast and incoherently, and that is trying to hold their bladder for an hour. Nothing
good can come of that. 
&lt;li&gt;
&lt;strong&gt;Sleep well the night before.&lt;/strong&gt; Don't study your "interview cheat sheet"
late into the night. Go to bed early, and go to bed with a clear mind. You will not
sleep well if you spend the night ruminating over those questions and answers. In
fact, I understand that taking an over-the-counter aid (if you are healthy enough)
can help. Seasickness medications such as Bonine can clear nausea from "stomach butterflies"
that might precede a stressful interview, and also have the nice side effect of being
a sleeping aid (causes drowsiness). As always, &lt;em&gt;&lt;u&gt;check with your doctor&lt;/u&gt;&lt;/em&gt; before
taking something like that. 
&lt;li&gt;
&lt;strong&gt;Smile.&lt;/strong&gt; The interviewer is not only looking to see if you know the
technical answers to their questions, they are also evaluating whether they would
want to work with you on a team or not, and if you know how to enjoy working with
others. When interviewing, the measuring stick I often use is to ask myself "Would
I be comfortable having a beer after work with this person?". You might be surprised
how often the answer to that is "no" (especially in the ultra-bizarre circus of tech
workers).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
And here is a "bonus" tip submitted by David Daughtrey...
&lt;/p&gt;
&lt;p&gt;
11. &lt;strong&gt;Dont eat at the Wing Factory on the night before an interview.&lt;/strong&gt; Or
any hot wing establishment for that matter.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=6eba2c97-8453-4849-86d4-d83c800317c9" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,6eba2c97-8453-4849-86d4-d83c800317c9.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=15d7ab03-1ca0-4728-bdba-3640657e6d19</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,15d7ab03-1ca0-4728-bdba-3640657e6d19.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,15d7ab03-1ca0-4728-bdba-3640657e6d19.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=15d7ab03-1ca0-4728-bdba-3640657e6d19</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>
            <strong>UPDATE 10/25/2007:</strong> Updated this sample to function correctly
with the Silverlight 1.0 release. The main changes necessary were the typical 0.9
to 1.0 changes (remove "Sys.", isWindowless now takes a string and not a boolean,
event handlers no longer string based), and I also had to explicitly set the z-index
of the INPUT element. Thank you Erik for bringing it to my attention.</em>
        </p>
        <p>
 
</p>
        <p>
I have seen a lot of questions and confusion regarding capturing input when using
Silverlight. There are no Button, TextBox, or other similar controls to work with.
I see many folks asking for help with building their own directly within Silverlight
- and bless their hearts, that is a daunting task indeed! The UI model currently does
not offer basic input capture features such as "focus" or "tabbing", or even control-level
keystroke capture. So folks tend to start building those basic services first, before
they ever even get to writing code and xaml to support that simple textbox they need.
</p>
        <p>
If you read that first paragraph and thought "thats crazy, it shouldn't be that hard!",
then I would agree with you. Fortunately, there is a FAR easier and more robust way
to achieve the same thing. In fact, its something that is not new to Silverlight at
all, it's been with us for years. I am of course talking about the tried-and-true
html &lt;input&gt; tag.
</p>
        <p>
One of the most overlooked aspects of Silverlight is that it is a component, not a
platform. Your browser is the platform. It can do a lot of stuff, if you just ask
it to. Nobody wants an entire site as a single Silverlight canvas, just like nobody
wants an entire site as a Flash canvas (unless possibly it is a mini-game or rich
media application)... Flash designers realized this fact years ago. And as a component,
a <em>part</em> of the solution if you will, Silverlight can play nicely with it's
neighbors. With just a little bit of effort and sprinkling a very minimal amount of
javascript pixie dust, we can get a Silverlight applet talking to the rest of
our html DOM. And that's exactly what I am going to show in this topic...
</p>
        <p>
          <em>
            <strong>You can download the code demonstrated in this article here (<a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTip-TextboxesInSilverlight.zip">QuickTip-TextboxesInSilverlight.zip</a>).</strong>
          </em>
        </p>
        <p>
First of all, I am doing this with Silverlight 1.0 beta (the javascript one), as I
think the 1.1 alpha is far too likely to change, and this technique <em>should</em> work
with either. That, and I am lazy and don't want to come back and revisit this post
later to correct the code...
</p>
        <p>
Secondly, I am using the current CTP builds of Visual Studio Orcas and Blend 2 (the
May 2007 bits), both with the Silverlight extensions. If you are using something else,
then your mileage may vary.
</p>
        <p>
          <em>
            <strong>UPDATE 10/25/2007:</strong> Code updated for VS2008 beta2 and the RTM
version of Silverlight 1.0.</em>
        </p>
        <p>
Now on to the code... to be sure we are on the same page, I am creating a new project
from scratch...
</p>
        <p>
First, Create a new project in Blend. Select the Silverlight 1.0 (JavaScript) project
type. It does not matter what you name the project, but for this example I went with
"TextboxesInSilverlight".
</p>
        <p>
          <a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image06.png" atomicselection="true">
            <img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="142" src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image0_thumb4.png" width="419" border="0" />
          </a>
        </p>
        <p>
Switch to XAML view and replace the default canvas with this markup:<font color="#0000ff" size="2"><br /></font></p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font color="#0000ff" size="2">
              <font face="Courier New" color="#ff0000">
                <font color="#0000ff">&lt;</font>
                <font color="#a52a2a">Canvas</font>
                <br />
 xmlns<font color="#0000ff">=</font><font color="#000000">"</font></font>
              <a href="http://schemas.microsoft.com/client/2007">
                <font face="Courier New" color="#0000ff">http://schemas.microsoft.com/client/2007</font>
              </a>
              <font face="Courier New" color="#ff0000">
                <font color="#000000">"</font>
                <br />
 xmlns:x<font color="#0000ff">=</font><font color="#000000">"</font></font>
              <a href="http://schemas.microsoft.com/winfx/2006/xaml">
                <font face="Courier New" color="#0000ff">http://schemas.microsoft.com/winfx/2006/xaml</font>
              </a>
              <font face="Courier New" color="#ff0000">
                <font color="#000000">"</font>
                <br />
 Width<font color="#0000ff">=<font color="#000000">"</font>252</font><font color="#000000">"</font> Height<font color="#0000ff">=<font color="#000000">"</font>272</font><font color="#000000">"</font><br />
 Background<font color="#0000ff">=<font color="#000000">"</font>#FFFF2121</font><font color="#000000">"</font><br />
 <font color="#0000ff">&gt;</font><br />
  <font color="#0000ff">&lt;</font><font color="#a52a2a">TextBlock</font> Width<font color="#0000ff">=<font color="#000000">"</font>64</font><font color="#000000">"</font> Height<font color="#0000ff">=<font color="#000000">"</font>24</font><font color="#000000">"</font> Canvas.Left<font color="#0000ff">=<font color="#000000">"</font>8</font><font color="#000000">"</font> Canvas.Top<font color="#0000ff">=<font color="#000000">"</font>8</font><font color="#000000">"</font><br />
             Text<font color="#0000ff">=<font color="#000000">"</font>Opacity</font><font color="#000000">"</font> TextWrapping<font color="#0000ff">=<font color="#000000">"</font>Wrap<font color="#000000">"</font>/&gt;</font><br />
  <font color="#0000ff">&lt;</font><font color="#a52a2a">Ellipse</font> Opacity<font color="#0000ff">=<font color="#000000">"</font>1</font><font color="#000000">"</font> Fill<font color="#0000ff">=<font color="#000000">"</font>#FF0406FF</font><font color="#000000">"</font> Stroke<font color="#0000ff">=<font color="#000000">"</font>#FF000000</font><font color="#000000">"</font><br />
           x:Name<font color="#0000ff">=<font color="#000000">"</font>TheCircle</font><font color="#000000">"</font> Width<font color="#0000ff">=<font color="#000000">"</font>180</font><font color="#000000">"</font> Height<font color="#0000ff">=<font color="#000000">"</font>180</font><font color="#000000">"</font> <br />
           Canvas.Left<font color="#0000ff">=<font color="#000000">"</font>36</font><font color="#000000">"</font> Canvas.Top<font color="#0000ff">=<font color="#000000">"</font>64<font color="#000000">"</font>/&gt;</font><br /><font color="#0000ff">&lt;/</font><font color="#a52a2a">Canvas</font><font color="#0000ff">&gt;</font></font>
            </font>
          </p>
        </blockquote>
        <p>
This will create a simple red canvas, with a blue circle.
</p>
        <p>
At this point, I generally switch over to Visual Studio Orcas since Blend does not
have Intellisense nor does it really know how to deal with JavaScript. You can do
this easily by right-clicking a project item (such as the xaml file) and selecting
"Edit in Visual Studio".
</p>
        <p>
          <a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image011.png" atomicselection="true">
            <img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="214" src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image0_thumb7.png" width="217" border="0" />
          </a>
        </p>
        <p>
Next, we need to do one small housekeeping chore to make sure that our Silverlight
canvas plays nicely - specifically, we need to ask it to operate "windowless", which
will allow other dhtml elements to overlay it, Open the Default.html.js file, and
modify the call to Silverlight.createObjectEx(). We want to add the parameter for
isWindowless...
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New"> Silverlight.createObjectEx({<br />
  source: <font color="#a52a2a">"Scene.xaml"</font>,<br />
  parentElement: document.getElementById(<font color="#a52a2a">"</font><font color="#a52a2a">SilverlightControlHost</font><font color="#a52a2a">"</font>),<br />
  id: <font color="#a52a2a">"SilverlightControl"</font>,<br />
  properties: {<br />
   width: <font color="#a52a2a">"100%"</font>,<br />
   height: <font color="#a52a2a">"100%"</font>,<br />
   version: <font color="#a52a2a">"0.9"</font>,<br />
   isWindowless: <font color="#a52a2a">"true"</font><br />
  },<br />
  events: {<br />
   onLoad: sceneLoaded<br />
  }<br />
 });</font>
            <br />
          </p>
        </blockquote>
        <p>
To make things a bit more "clean", we will create the input element directly from
code, however it's always good to control visual styling with CSS. Therefore, open
up the Default.html, and alter the &lt;style&gt; tag to match the following: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New"> <font color="#0000ff">&lt;</font><font color="#a52a2a">style</font><font color="#ff0000">type</font><font color="#0000ff">="text/css"&gt;</font><br />
  <font color="#a52a2a">div</font>, <font color="#a52a2a">body</font>, <font color="#a52a2a">input</font><br />
  {<br />
   <font color="#ff0000">margin</font>: <font color="#0000ff">0</font>;<br />
   <font color="#ff0000">padding</font>: <font color="#0000ff">0</font>;<br />
  }<br />
  <font color="#a52a2a">#opacity</font><br />
  {<br />
   <font color="#ff0000">margin</font>: -<font color="#0000ff">272px
0 0 75px</font>;<br />
   <font color="#ff0000">z-index<font color="#000000">:</font></font><font color="#000000"><font color="#0000ff">100</font>;</font><br />
  }<br />
  <font color="#a52a2a">.silverlightHost</font><br />
  {<br />
   <font color="#ff0000">margin</font>: <font color="#0000ff">40px
auto auto auto</font>;<br />
   <font color="#ff0000">height</font>: <font color="#0000ff">272px</font>;<br />
   <font color="#ff0000">width</font>: <font color="#0000ff">252px</font>;<br />
  }<br />
 &lt;/<font color="#a52a2a">style</font>&gt;</font>
          </p>
        </blockquote>
        <p>
This will handle the placement and sizing of the silverlight container &lt;div&gt;
as well as the input control itself. The negative margin is not a typo - this is used
to pull the input control "on top" of the silverlight canvas. We could have also used
absolute positioning, but that is much more brittle, relative positioning FTW. Also,
notice the use of "auto" margins for the main Silverlight Host &lt;div&gt;. This is
how you can center content without resorting to using &lt;center&gt; or &lt;table&gt;...
if you take nothing away from this post, at least remember that one trick. 
</p>
        <p>
The last thing we must do is wire the whole thing up. This can be done in many places,
in many ways. I consider this particular TextBox to be an extension of the Xaml "scene",
so I will add my code to the TextboxesInSilverlight.Scene class which was created
for us by the Blend project template. This is not the only place you could do this
kind of code, but I found that in this particular example it made the most sense.
Had I been building a dialog for a game engine, I might have this code in a seperate
script file that manages my game mechanics (but thats another article...). 
</p>
        <p>
First, we need to capture a global reference to the Scene object that is created (this
object is instantiated by the createSilverlight() function of the Default.html.js
script file we edited in a previous step). The purpose of capturing this reference
is that we will need it later in an event handler. This will allow our html &lt;input&gt;
control to communicate back with the silverlight content. This is easier done than
said. Open the Scene.xaml.js file. Just before the definition of the TextboxesInSilverlight.Scene.prototype
(look up javascript prototype for what this is if you are interested, but that discussion
is out of scope for this article), add a line of code to declare the global reference: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#0000ff">var</font> globalScene = <font color="#0000ff">null</font>; </font>
          </p>
        </blockquote>
        <p>
Now we will create a callback function that will be used to create our JavaScript
object and initialize it: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <font color="#0000ff">function</font> sceneLoaded(control,
userContext, rootElement)<br />
{<br />
    globalScene = <font color="#0000ff">new</font> TextboxesInSilverlight.Scene();<br />
    globalScene.handleLoad(control, userContext, rootElement);<br />
}; </pre>
        </blockquote>
        <p>
Now, the idea for this example is that the value of the text box will determine the
"Opacity" Xaml property of the Ellipse shape in our markup. In order for the event
handler we are about to add to be able to do this, we will capture a reference to
the circle object (technically we can wait and use findName() later during the event
handler, but I prefer to capture it only once - its just my style of coding). Add
this line to the handleLoad function: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#0000ff">this</font>.circle = control.content.findName(<font color="#a52a2a">"TheCircle"</font>);</font>
          </p>
        </blockquote>
        <p>
Next, we will create the input control and add it to the DHTML document. We will add
it directly to the same &lt;div&gt; that Silverlight has injected itself into, and
therefore any layout or positioning that affects the Silverlight canvas will also
affect our &lt;input&gt; box. Add this code to the end of the handleLoad function: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#0000ff">var</font> opacityEdit = window.document.createElement(<font color="#a52a2a">"input"</font>);<br />
opacityEdit.type = <font color="#a52a2a">"text"</font>;<br />
opacityEdit.id = <font color="#a52a2a">"opacity"</font>;<br />
opacityEdit.name = <font color="#a52a2a">"opacity"</font>;<br />
opacityEdit.value = <font color="#a52a2a">"1.0"</font></font>;
</p>
        </blockquote>
        <p>
We are almost done - only two more steps and then we can fire this thing up! First,
we need to add an event handler to react to changes in the value property of the input
control. Add this code to the very end of the handleLoad function: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">opacityEdit.onpropertychange = <font color="#0000ff">function</font>()<br />
    {<br />
        <font color="#0000ff">if</font> (<font color="#0000ff">event</font>.propertyName
== <font color="#a52a2a">"value"</font>)<br />
        {<br />
            globalScene.circle.Opacity
= <font color="#0000ff">event</font>.srcElement.value;<br />
        }<br />
    }</font>
          </p>
        </blockquote>
        <p>
This effectively creates an anonymous function to handle property change events on
the &lt;input&gt; control, which in turn updates the Opacity property of the circle
shape. Cool, huh? 
</p>
        <p>
The last thing to do is finally add the new &lt;input&gt; element to the page, otherwise
all the work until this point will have had no discernable impact at all... add this
one last line to the handleLoad function: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#0000ff">this</font>.control.parentElement.appendChild(opacityEdit);</font>
          </p>
        </blockquote>
        <p>
At this point, your Scene.xaml.js file should look like this: 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">
              <font color="#0000ff">if</font> (!window.TextboxesInSilverlight)<br />
 window.TextboxesInSilverlight = {};</font>
          </p>
          <p>
            <font face="Courier New">TextboxesInSilverlight.Scene = <font color="#0000ff">function</font>() 
<br />
{<br />
}</font>
          </p>
          <p>
            <font face="Courier New">
              <font color="#0000ff">var</font> globalScene = <font color="#0000ff">null</font>;</font>
          </p>
          <p>
            <font face="Courier New">
              <font color="#0000ff">function</font> sceneLoaded(control,
userContext, rootElement)<br />
{<br />
    globalScene = <font color="#0000ff">new</font> TextboxesInSilverlight.Scene();<br />
    globalScene.handleLoad(control, userContext, rootElement);<br />
}</font>
          </p>
          <p>
            <font face="Courier New">TextboxesInSilverlight.Scene.prototype =<br />
{<br />
 handleLoad: <font color="#0000ff">function</font>(control, userContext, rootElement) 
<br />
 {<br />
  <font color="#0000ff">this</font>.control = control;<br />
  <br />
  <font color="#0000ff">this</font>.circle = control.content.findName<font color="#a52a2a">("TheCircle"</font>);<br />
  <br />
  <font color="#0000ff">var</font> opacityEdit = window.document.createElement(<font color="#a52a2a">"input"</font>);<br />
  opacityEdit.type = <font color="#a52a2a">"text"</font>;<br />
  opacityEdit.id = <font color="#a52a2a">"opacity"</font>;<br />
  opacityEdit.name = <font color="#a52a2a">"opacity"</font>;<br />
  opacityEdit.value = <font color="#a52a2a">"1.0"</font>;<br />
  opacityEdit.onpropertychange = <font color="#0000ff">function</font>()<br />
    {<br />
      <font color="#0000ff">if</font> (<font color="#0000ff">event</font>.propertyName
== <font color="#a52a2a">"value"</font>)<br />
      {<br />
        globalScene.circle.Opacity = <font color="#0000ff">event</font>.srcElement.value;<br />
      }<br />
    }<br />
  </font>
            <font face="Courier New">
              <font color="#0000ff">this</font>.control.parentElement.appendChild(opacityEdit);<br />
 } <br />
}</font>
          </p>
        </blockquote>
        <p>
        </p>
        <p>
If the typo gods favor you, then you should be able to use F5 to run the page and
see it all working together: 
</p>
        <p>
          <a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image015.png" atomicselection="true">
            <img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="240" src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image0_thumb9.png" width="228" border="0" />
          </a>
          <a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image017.png" atomicselection="true">
            <img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="240" src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image016.png" width="226" border="0" />
          </a>
        </p>
        <p>
Notice the positioning of the input textboxes, and the interaction of them with the
underlying Silverlight canvas. This is just a simple example, but can be a very powerful
way to "plug in" Silverlight into the surrounding DHTML. 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=15d7ab03-1ca0-4728-bdba-3640657e6d19" />
      </body>
      <title>Quick Tip - Input Controls in Silverlight</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,15d7ab03-1ca0-4728-bdba-3640657e6d19.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2007/06/14/QuickTipInputControlsInSilverlight.aspx</link>
      <pubDate>Thu, 14 Jun 2007 20:25:05 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;&lt;strong&gt;UPDATE 10/25/2007:&lt;/strong&gt; Updated this sample to function correctly
with the Silverlight 1.0 release. The main changes necessary were the typical 0.9
to 1.0 changes (remove "Sys.", isWindowless now takes a string and not a boolean,
event handlers no longer string based), and I also had to explicitly set the z-index
of the INPUT element. Thank you Erik for bringing it to my attention.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
I have seen a lot of questions and confusion regarding capturing input when using
Silverlight. There are no Button, TextBox, or other similar controls to work with.
I see many folks asking for help with building their own directly within Silverlight
- and bless their hearts, that is a daunting task indeed! The UI model currently does
not offer basic input capture features such as "focus" or "tabbing", or even control-level
keystroke capture. So folks tend to start building those basic services first, before
they ever even get to writing code and xaml to support that simple textbox they need.
&lt;/p&gt;
&lt;p&gt;
If you read that first paragraph and thought "thats crazy, it shouldn't be that hard!",
then I would agree with you. Fortunately, there is a FAR easier and more robust way
to achieve the same thing. In fact, its something that is not new to Silverlight at
all, it's been with us for years. I am of course talking about the tried-and-true
html &amp;lt;input&amp;gt; tag.
&lt;/p&gt;
&lt;p&gt;
One of the most overlooked aspects of Silverlight is that it is a component, not a
platform. Your browser is the platform. It can do a lot of stuff, if you just ask
it to. Nobody wants an entire site as a single Silverlight canvas, just like nobody
wants an entire site as a Flash canvas (unless possibly it is a mini-game or rich
media application)... Flash designers realized this fact years ago. And as a component,
a &lt;em&gt;part&lt;/em&gt; of the solution if you will, Silverlight can play nicely with it's
neighbors. With just a little bit of effort and sprinkling a very minimal amount of
javascript pixie dust, we can&amp;nbsp;get a Silverlight applet talking to the rest of
our html DOM. And that's exactly what I am going to show in this topic...
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;strong&gt;You can download the code demonstrated in this article here (&lt;a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTip-TextboxesInSilverlight.zip"&gt;QuickTip-TextboxesInSilverlight.zip&lt;/a&gt;).&lt;/strong&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
First of all, I am doing this with Silverlight 1.0 beta (the javascript one), as I
think the 1.1 alpha is far too likely to change, and this technique &lt;em&gt;should&lt;/em&gt; work
with either. That, and I am lazy and don't want to come back and revisit this post
later to correct the code...
&lt;/p&gt;
&lt;p&gt;
Secondly, I am using the current CTP builds of Visual Studio Orcas and Blend 2 (the
May 2007 bits), both with the Silverlight extensions. If you are using something else,
then your mileage may vary.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;strong&gt;UPDATE 10/25/2007:&lt;/strong&gt; Code updated for VS2008 beta2 and the RTM
version of Silverlight 1.0.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Now on to the code... to be sure we are on the same page, I am creating a new project
from scratch...
&lt;/p&gt;
&lt;p&gt;
First, Create a new project in Blend. Select the Silverlight 1.0 (JavaScript) project
type. It does not matter what you name the project, but for this example I went with
"TextboxesInSilverlight".
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image06.png" atomicselection="true"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=142 src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image0_thumb4.png" width=419 border=0&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Switch to XAML view and replace the default canvas with this markup:&lt;font color=#0000ff size=2&gt;
&lt;br&gt;
&lt;/font&gt;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font color=#0000ff size=2&gt;&lt;font face="Courier New" color=#ff0000&gt;&lt;font color=#0000ff&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a52a2a&gt;Canvas&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;xmlns&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/client/2007"&gt;&lt;font face="Courier New" color=#0000ff&gt;http://schemas.microsoft.com/client/2007&lt;/font&gt;&lt;/a&gt;&lt;font face="Courier New" color=#ff0000&gt;&lt;font color=#000000&gt;"&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;xmlns:x&lt;font color=#0000ff&gt;=&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&lt;/font&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml"&gt;&lt;font face="Courier New" color=#0000ff&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/font&gt;&lt;/a&gt;&lt;font face="Courier New" color=#ff0000&gt;&lt;font color=#000000&gt;"&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;Width&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;252&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Height&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;272&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;Background&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;#FFFF2121&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&lt;font color=#0000ff&gt;&amp;gt;&lt;/font&gt;
&lt;br&gt;
&amp;nbsp; &lt;font color=#0000ff&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a52a2a&gt;TextBlock&lt;/font&gt; Width&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;64&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Height&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;24&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Canvas.Left&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;8&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Canvas.Top&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;8&lt;/font&gt;&lt;font color=#000000&gt;"&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;&amp;nbsp; Text&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;Opacity&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; TextWrapping&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;Wrap&lt;font color=#000000&gt;"&lt;/font&gt;/&amp;gt;&lt;/font&gt;
&lt;br&gt;
&amp;nbsp; &lt;font color=#0000ff&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a52a2a&gt;Ellipse&lt;/font&gt; Opacity&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;1&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Fill&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;#FF0406FF&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Stroke&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;#FF000000&lt;/font&gt;&lt;font color=#000000&gt;"&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;x:Name&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;TheCircle&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt;&amp;nbsp;Width&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;180&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Height&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;180&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&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; Canvas.Left&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;36&lt;/font&gt;&lt;font color=#000000&gt;"&lt;/font&gt; Canvas.Top&lt;font color=#0000ff&gt;=&lt;font color=#000000&gt;"&lt;/font&gt;64&lt;font color=#000000&gt;"&lt;/font&gt;/&amp;gt;&lt;/font&gt;
&lt;br&gt;
&lt;font color=#0000ff&gt;&amp;lt;/&lt;/font&gt;&lt;font color=#a52a2a&gt;Canvas&lt;/font&gt;&lt;font color=#0000ff&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt;&gt; 
&lt;p&gt;
This will create a simple red canvas, with a blue circle.
&lt;/p&gt;
&lt;p&gt;
At this point, I generally switch over to Visual Studio Orcas since Blend does not
have Intellisense nor does it really know how to deal with JavaScript. You can do
this easily by right-clicking a project item (such as the xaml file) and selecting
"Edit in Visual Studio".
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image011.png" atomicselection="true"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=214 src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image0_thumb7.png" width=217 border=0&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Next, we need to do one small housekeeping chore to make sure that our Silverlight
canvas plays nicely - specifically, we need to ask it to operate "windowless", which
will allow other dhtml elements to overlay it, Open the Default.html.js file, and
modify the call to Silverlight.createObjectEx(). We want to add the parameter for
isWindowless...
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;Silverlight.createObjectEx({&lt;br&gt;
&amp;nbsp;&amp;nbsp;source: &lt;font color=#a52a2a&gt;"Scene.xaml"&lt;/font&gt;,&lt;br&gt;
&amp;nbsp;&amp;nbsp;parentElement: document.getElementById(&lt;font color=#a52a2a&gt;"&lt;/font&gt;&lt;font color=#a52a2a&gt;SilverlightControlHost&lt;/font&gt;&lt;font color=#a52a2a&gt;"&lt;/font&gt;),&lt;br&gt;
&amp;nbsp;&amp;nbsp;id: &lt;font color=#a52a2a&gt;"SilverlightControl"&lt;/font&gt;,&lt;br&gt;
&amp;nbsp;&amp;nbsp;properties: {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;width: &lt;font color=#a52a2a&gt;"100%"&lt;/font&gt;,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;height: &lt;font color=#a52a2a&gt;"100%"&lt;/font&gt;,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;version: &lt;font color=#a52a2a&gt;"0.9"&lt;/font&gt;,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;isWindowless: &lt;font color=#a52a2a&gt;"true"&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;},&lt;br&gt;
&amp;nbsp;&amp;nbsp;events: {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;onLoad: sceneLoaded&lt;br&gt;
&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;});&lt;/font&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
To make things a bit more "clean", we will create the input element directly from
code, however it's always good to control visual styling with CSS. Therefore, open
up the Default.html, and alter the &amp;lt;style&amp;gt; tag to match the following: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&lt;font color=#0000ff&gt;&amp;lt;&lt;/font&gt;&lt;font color=#a52a2a&gt;style&lt;/font&gt; &lt;font color=#ff0000&gt;type&lt;/font&gt;&lt;font color=#0000ff&gt;="text/css"&amp;gt;&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=#a52a2a&gt;div&lt;/font&gt;, &lt;font color=#a52a2a&gt;body&lt;/font&gt;, &lt;font color=#a52a2a&gt;input&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#ff0000&gt;margin&lt;/font&gt;: &lt;font color=#0000ff&gt;0&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#ff0000&gt;padding&lt;/font&gt;: &lt;font color=#0000ff&gt;0&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=#a52a2a&gt;#opacity&lt;/font&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#ff0000&gt;margin&lt;/font&gt;: -&lt;font color=#0000ff&gt;272px 0
0 75px&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#ff0000&gt;z-index&lt;font color=#000000&gt;:&lt;/font&gt;&lt;/font&gt;&lt;font color=#000000&gt; &lt;font color=#0000ff&gt;100&lt;/font&gt;;&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=#a52a2a&gt;.silverlightHost&lt;/font&gt; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#ff0000&gt;margin&lt;/font&gt;: &lt;font color=#0000ff&gt;40px auto
auto auto&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#ff0000&gt;height&lt;/font&gt;: &lt;font color=#0000ff&gt;272px&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#ff0000&gt;width&lt;/font&gt;: &lt;font color=#0000ff&gt;252px&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;lt;/&lt;font color=#a52a2a&gt;style&lt;/font&gt;&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This will handle the placement and sizing of the silverlight container &amp;lt;div&amp;gt;
as well as the input control itself. The negative margin is not a typo - this is used
to pull the input control "on top" of the silverlight canvas. We could have also used
absolute positioning, but that is much more brittle, relative positioning FTW. Also,
notice the use of "auto" margins for the main Silverlight Host &amp;lt;div&amp;gt;. This is
how you can center content without resorting to using &amp;lt;center&amp;gt; or &amp;lt;table&amp;gt;...
if you take nothing away from this post, at least remember that one trick. 
&lt;p&gt;
The last thing we must do is wire the whole thing up. This can be done in many places,
in many ways. I consider this particular TextBox to be an extension of the Xaml "scene",
so I will add my code to the TextboxesInSilverlight.Scene class which was created
for us by the Blend project template. This is not the only place you could do this
kind of code, but I found that in this particular example it made the most sense.
Had I been building a dialog for a game engine, I might have this code in a seperate
script file that manages my game mechanics (but thats another article...). 
&lt;p&gt;
First, we need to capture a global reference to the Scene object that is created (this
object is instantiated by the createSilverlight() function of the Default.html.js
script file we edited in a previous step). The purpose of capturing this reference
is that we will need it later in an event handler. This will allow our html &amp;lt;input&amp;gt;
control to communicate back with the silverlight content. This is easier done than
said. Open the Scene.xaml.js file. Just before the definition of the TextboxesInSilverlight.Scene.prototype
(look up javascript prototype for what this is if you are interested, but that discussion
is out of scope for this article), add a line of code to declare the global reference: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;var&lt;/font&gt; globalScene = &lt;font color=#0000ff&gt;null&lt;/font&gt;; &lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Now we will create a callback function that will be used to create our JavaScript
object and initialize it: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font color=#0000ff&gt;function&lt;/font&gt; sceneLoaded(control,
userContext, rootElement)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; globalScene = &lt;font color=#0000ff&gt;new&lt;/font&gt; TextboxesInSilverlight.Scene();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; globalScene.handleLoad(control, userContext, rootElement);&lt;br&gt;
}; &lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Now, the idea for this example is that the value of the text box will determine the
"Opacity" Xaml property of the Ellipse shape in our markup. In order for the event
handler we are about to add to be able to do this, we will capture a reference to
the circle object (technically we can wait and use findName() later during the event
handler, but I prefer to capture it only once - its just my style of coding). Add
this line to the handleLoad function: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;this&lt;/font&gt;.circle = control.content.findName(&lt;font color=#a52a2a&gt;"TheCircle"&lt;/font&gt;);&lt;/font&gt; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Next, we will create the input control and add it to the DHTML document. We will add
it directly to the same &amp;lt;div&amp;gt; that Silverlight has injected itself into, and
therefore any layout or positioning that affects the Silverlight canvas will also
affect our &amp;lt;input&amp;gt; box. Add this code to the end of the handleLoad function: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;var&lt;/font&gt; opacityEdit = window.document.createElement(&lt;font color=#a52a2a&gt;"input"&lt;/font&gt;);&lt;br&gt;
opacityEdit.type = &lt;font color=#a52a2a&gt;"text"&lt;/font&gt;;&lt;br&gt;
opacityEdit.id = &lt;font color=#a52a2a&gt;"opacity"&lt;/font&gt;;&lt;br&gt;
opacityEdit.name = &lt;font color=#a52a2a&gt;"opacity"&lt;/font&gt;;&lt;br&gt;
opacityEdit.value = &lt;font color=#a52a2a&gt;"1.0"&lt;/font&gt;&lt;/font&gt;;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
We are almost done - only two more steps and then we can fire this thing up! First,
we need to add an event handler to react to changes in the value property of the input
control. Add this code to the very end of the handleLoad function: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;opacityEdit.onpropertychange = &lt;font color=#0000ff&gt;function&lt;/font&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;&amp;nbsp; &lt;font color=#0000ff&gt;if&lt;/font&gt; (&lt;font color=#0000ff&gt;event&lt;/font&gt;.propertyName
== &lt;font color=#a52a2a&gt;"value"&lt;/font&gt;)&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; globalScene.circle.Opacity
= &lt;font color=#0000ff&gt;event&lt;/font&gt;.srcElement.value;&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;/font&gt; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This effectively creates an anonymous function to handle property change events on
the &amp;lt;input&amp;gt; control, which in turn updates the Opacity property of the circle
shape. Cool, huh? 
&lt;p&gt;
The last thing to do is finally add the new &amp;lt;input&amp;gt; element to the page, otherwise
all the work until this point will have had no discernable impact at all... add this
one last line to the handleLoad function: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;this&lt;/font&gt;.control.parentElement.appendChild(opacityEdit);&lt;/font&gt; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
At this point, your Scene.xaml.js file should look like this: &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;if&lt;/font&gt; (!window.TextboxesInSilverlight)&lt;br&gt;
&amp;nbsp;window.TextboxesInSilverlight = {};&lt;/font&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;TextboxesInSilverlight.Scene = &lt;font color=#0000ff&gt;function&lt;/font&gt;() 
&lt;br&gt;
{&lt;br&gt;
}&lt;/font&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;var&lt;/font&gt; globalScene = &lt;font color=#0000ff&gt;null&lt;/font&gt;;&lt;/font&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;function&lt;/font&gt; sceneLoaded(control,
userContext, rootElement)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; globalScene = &lt;font color=#0000ff&gt;new&lt;/font&gt; TextboxesInSilverlight.Scene();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; globalScene.handleLoad(control, userContext, rootElement);&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;TextboxesInSilverlight.Scene.prototype =&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;handleLoad: &lt;font color=#0000ff&gt;function&lt;/font&gt;(control, userContext, rootElement) 
&lt;br&gt;
&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=#0000ff&gt;this&lt;/font&gt;.control = control;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=#0000ff&gt;this&lt;/font&gt;.circle = control.content.findName&lt;font color=#a52a2a&gt;("TheCircle"&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=#0000ff&gt;var&lt;/font&gt; opacityEdit = window.document.createElement(&lt;font color=#a52a2a&gt;"input"&lt;/font&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;opacityEdit.type = &lt;font color=#a52a2a&gt;"text"&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;opacityEdit.id = &lt;font color=#a52a2a&gt;"opacity"&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;opacityEdit.name = &lt;font color=#a52a2a&gt;"opacity"&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;opacityEdit.value = &lt;font color=#a52a2a&gt;"1.0"&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;opacityEdit.onpropertychange = &lt;font color=#0000ff&gt;function&lt;/font&gt;()&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 color=#0000ff&gt;if&lt;/font&gt; (&lt;font color=#0000ff&gt;event&lt;/font&gt;.propertyName
== &lt;font color=#a52a2a&gt;"value"&lt;/font&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;globalScene.circle.Opacity = &lt;font color=#0000ff&gt;event&lt;/font&gt;.srcElement.value;&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;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font color=#0000ff&gt;this&lt;/font&gt;.control.parentElement.appendChild(opacityEdit);&lt;br&gt;
&amp;nbsp;}&amp;nbsp;&lt;br&gt;
}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;p&gt;
If the typo gods favor you, then you should be able to use F5 to run the page and
see it all working together: 
&lt;p&gt;
&lt;a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image015.png" atomicselection="true"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=240 src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image0_thumb9.png" width=228 border=0&gt;&lt;/a&gt; &lt;a href="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image017.png" atomicselection="true"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=240 src="http://www.mindfusioncorp.com/weblog/content/binary/QuickTipInputControlsinSilverlight_E5E5/image016.png" width=226 border=0&gt;&lt;/a&gt; 
&lt;p&gt;
Notice the positioning of the input textboxes, and the interaction of them with the
underlying Silverlight canvas. This is just a simple example, but can be a very powerful
way to "plug in"&amp;nbsp;Silverlight&amp;nbsp;into the surrounding&amp;nbsp;DHTML. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=15d7ab03-1ca0-4728-bdba-3640657e6d19" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,15d7ab03-1ca0-4728-bdba-3640657e6d19.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Silverlight</category>
      <category>Tips and Tricks</category>
      <category>Web 2.0</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=a7054160-92e3-46da-9fda-eb2cc9cd9294</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,a7054160-92e3-46da-9fda-eb2cc9cd9294.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,a7054160-92e3-46da-9fda-eb2cc9cd9294.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=a7054160-92e3-46da-9fda-eb2cc9cd9294</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I catch a lot of crap from my peers about the length of my posts and their apparent
lack of reasonable brevity. Well complain no more, because my pal <a href="http://devcow.com/blogs/jdattis/default.aspx" target="_blank">Dan</a> has
totally jumped the shark with his pair of matching Longest Posts Evar:
</p>
        <p>
 
</p>
        <p>
          <a href="http://devcow.com/blogs/jdattis/archive/2007/02/23/Office_SharePoint_Server_2007_Forms_Based_Authentication_FBA_Walkthrough_Part_1.aspx?CommentPosted=true" target="_blank">Office
SharePoint Server 2007 - Forms Based Authentication (FBA) Walk-through - Part 1</a>
        </p>
        <p>
and the sequel to the bestselling novel: 
</p>
        <p>
          <a href="http://devcow.com/blogs/jdattis/archive/2007/03/01/Office_SharePoint_Server_2007_Forms_Based_Authentication_FBA_w_MySites_Walkthrough_Part_2.aspx" target="_blank">Office
SharePoint Server 2007 - Forms Based Authentication (FBA) w/MySites Walk-through -
Part 2</a>
        </p>
        <p>
  
</p>
        <p>
Heck, even the titles are huge. <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a7054160-92e3-46da-9fda-eb2cc9cd9294" /></p>
      </body>
      <title>Longest Posts EVAR</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,a7054160-92e3-46da-9fda-eb2cc9cd9294.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2007/03/05/LongestPostsEVAR.aspx</link>
      <pubDate>Mon, 05 Mar 2007 19:12:22 GMT</pubDate>
      <description>&lt;p&gt;
I catch a lot of crap from my peers about the length of my posts and their apparent
lack of reasonable brevity. Well complain no more, because my pal &lt;a href="http://devcow.com/blogs/jdattis/default.aspx" target="_blank"&gt;Dan&lt;/a&gt; has
totally jumped the shark with his pair of matching Longest Posts Evar:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://devcow.com/blogs/jdattis/archive/2007/02/23/Office_SharePoint_Server_2007_Forms_Based_Authentication_FBA_Walkthrough_Part_1.aspx?CommentPosted=true" target="_blank"&gt;Office
SharePoint Server 2007 - Forms Based Authentication (FBA) Walk-through - Part 1&lt;/a&gt; 
&lt;p&gt;
and the sequel to the bestselling novel: 
&lt;p&gt;
&lt;a href="http://devcow.com/blogs/jdattis/archive/2007/03/01/Office_SharePoint_Server_2007_Forms_Based_Authentication_FBA_w_MySites_Walkthrough_Part_2.aspx" target="_blank"&gt;Office
SharePoint Server 2007 - Forms Based Authentication (FBA) w/MySites Walk-through -
Part 2&lt;/a&gt; 
&lt;p&gt;
&amp;nbsp; 
&lt;p&gt;
Heck, even the titles are huge. &lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a7054160-92e3-46da-9fda-eb2cc9cd9294" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,a7054160-92e3-46da-9fda-eb2cc9cd9294.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=606cf429-221c-4b83-8167-305181917e7c</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,606cf429-221c-4b83-8167-305181917e7c.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,606cf429-221c-4b83-8167-305181917e7c.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=606cf429-221c-4b83-8167-305181917e7c</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Databinding in .NET is immensely powerful. You can bind nearly any property of any
object to any property of any control. The source object can be any .NET object -
a business component, a DataSet, a built-in .NET class, or even another Control! Of
course like any powerful feature, the <em>Devil is in the Details</em>.
</p>
        <h3>Simple versus Complex Binding
</h3>
        <p>
To understand the databinding system first requires acknowledgement that there is
in fact two "flavors" of databinding. You can bind to two very different categories
of objects, and this is what differentiates the flavors of binding. The two flavors
are called <strong>Simple</strong> and <strong>Complex</strong> binding. This is somewhat
of a misnomer in my opinion as there is nothing inherently more complicated about
Complex binding - it's just <em>different</em>. I would prefer to call these two forms
of binding <strong>Item</strong> and <strong>List</strong> binding, as that more accurately
describes their use. In fact, I will try to refer to them as such throughout these
posts.
</p>
        <h4>Item Binding
</h4>
        <p>
Item Binding refers to the connection of a source object property value to a target
control's bindable property. These connections are typically two-way, in other words
you can change either side of the connection and the databinding system will push
the change to the other side. Another cool aspect is that you can bind many controls
to the same source property - however you cannot bind a control's property to more
than one source. An example of this would be binding the <strong><em>Text</em></strong> property
of a <strong><em>Label</em></strong> control to the <strong><em>FirstName</em></strong> string
property of a Customer object.
</p>
        <h4>List Binding
</h4>
        <p>
List Binding refers to the connection of a source list of objects to a target control
that is capable of display and/or navigating between multiple items in the list. The
source list can be any .NET object that implements IList, ICollection, IEnumerable or
IBindingList, including arrays, collections, generic lists, and DataTables. In more
advanced scenarios, an object that implements IListSource can also be used - IListSource
simply defines a list of lists. Controls that are able to participate in List Binding
include the ubiquitous DataGrid/DataGridView, and many other controls that consume
lists of items for various reasons - DropDowns, ListBoxes, and TreeViews to name a
few.
</p>
        <h4>Mixing and Matching
</h4>
        <p>
Unfortunately, you usually cannot mix (or should not mix) both Item and List Binding
in the same source objects. Due to the way the databinding system discovers and uses
databinding interfaces (will be discussed in a followup topic), it is not possible
to have both Item and List bindings on the same object. An example of this would be
binding to Customer entries in a list as well as the Count property of the list itself.
</p>
        <h4>Examples
</h4>
        <h5>Item Binding Examples
</h5>
        <p>
When creating Item Binding connections, you always begin with the target control,
and add to its DataBindings collection a list of property names and their sources.
DataBindings.Add() is an overloaded method with two main usage scenarios. Most of
the time you will use the form of Add(PropertyName, DataSource, SourcePropertyName).
In more rare situations you might want to create a Binding object directly and and
use the form Add(Binding)... this can be useful when you want to override default
formatting and parsing of values.
</p>
        <ul>
          <li>
Binding to a property of a business object 
</li>
        </ul>
        <blockquote>
          <p>
            <font face="Courier New" size="2">Customer C = <font color="#0080ff">new</font> Customer("John"); </font>
          </p>
          <p>
            <font face="Courier New" size="2">TextBox TextBox1 = <font color="#0080ff">new</font> TextBox(); </font>
          </p>
          <p>
            <font face="Courier New" size="2">TextBox1.DataBindings.Add("Text", C, "FirstName"); </font>
          </p>
          <p>
            <font face="Courier New" size="2">
              <em>-or-</em>
            </font>
          </p>
          <p>
            <font face="Courier New" size="2">Binding B = <font color="#0080ff">new</font> Binding("Text",
C, "FirstName"); </font>
          </p>
          <p>
            <font face="Courier New" size="2">TextBox1.DataBindings.Add(B);</font>
          </p>
        </blockquote>
        <ul>
          <li>
Binding to a public field of a business object 
</li>
        </ul>
        <blockquote>
          <p>
You can't do it in this version of the framework! 
</p>
        </blockquote>
        <ul>
          <li>
Binding to a field in a DataTable 
</li>
        </ul>
        <blockquote>
          <p>
            <font face="Courier New">DataTable CustomerDT = <font color="#0080ff">new</font> DataTable("Customers"); </font>
          </p>
          <p>
            <font face="Courier New">CustomerDT.Columns.Add("FirstName", typeof(string)); </font>
          </p>
          <p>
            <font face="Courier New">CustomerDT.Rows.Add(<font color="#0080ff">new object</font>[1]
{"John"}); </font>
          </p>
          <p>
            <font face="Courier New">TextBox TextBox1 = <font color="#0080ff">new</font> TextBox(); </font>
          </p>
          <p>
            <font face="Courier New">TextBox1.DataBindings.Add("Text", CustomerDT, "FirstName");</font>
          </p>
        </blockquote>
        <ul>
          <li>
Binding multiple controls to the same source data 
</li>
        </ul>
        <blockquote>
          <p>
            <font face="Courier New">CheckBox CheckBox1 = <font color="#0080ff">new</font> CheckBox(); </font>
          </p>
          <p>
            <font face="Courier New">TextBox TextBox1 = <font color="#0080ff">new</font> TextBox(); </font>
          </p>
          <p>
            <font face="Courier New">TextBox1.DataBindings.Add("Enabled", CheckBox1, "Checked");</font>
          </p>
        </blockquote>
        <h5>List Binding Examples
</h5>
        <ul>
          <li>
Binding a grid to a DataTable</li>
        </ul>
        <blockquote>
          <p>
            <font face="Courier New">DataSet CustomerDS = <font color="#0080ff">new</font> DataSet();</font>
          </p>
          <p>
            <font face="Courier New">DataTable CustomerDT = CustomerDS.Tables.Add("Customers");</font>
          </p>
          <p>
            <font face="Courier New">CustomerDT.Columns.Add("FirstName", typeof(string));</font>
          </p>
          <p>
            <font face="Courier New">DataGrid CustomerGrid = <font color="#0080ff">new</font> DataGrid();</font>
          </p>
          <p>
            <font face="Courier New">CustomerGrid.DataSource = CustomerDT;</font>
          </p>
          <p>
            <em>Note that the following can also replace the above DataSource assignment:</em>
          </p>
          <p>
            <font face="Courier New">CustomerGrid.DataMember = "Customers";</font>
          </p>
          <p>
            <font face="Courier New">CustomerGrid.DataSource = CustomerDS;</font>
          </p>
          <p>
            <em>However, it is very important to realize that while on the surface they may appear
to give identical results, these datasource assignments are <strong>not the same</strong>!
I will explain this further in part 6 of this series.</em>
          </p>
        </blockquote>
        <ul>
          <li>
Binding a ComboBox to an array</li>
        </ul>
        <blockquote>
          <p>
            <font face="Courier New">string[] StatusList = <font color="#0080ff">new</font> string[2]
{"Active", "Canceled", "Completed"};</font>
          </p>
          <p>
            <font face="Courier New">ComboBox CurrentStatus = <font color="#0080ff">new</font> ComboBox();</font>
          </p>
          <p>
            <font face="Courier New">CurrentStatus.DataSource = StatusList;</font>
          </p>
          <p>
            <em>Note that with a ComboBox, the List Binding is what is used to supply the list
of possible values displayed when activating the control.</em>
          </p>
        </blockquote>
        <ul>
          <li>
Binding a ListBox to a Business Object Collection</li>
        </ul>
        <blockquote>
          <p>
            <font face="Courier New">List&lt;Customer&gt; CustomerList = <font color="#0080ff">new</font> List&lt;Customer&gt;;</font>
          </p>
          <p>
            <font face="Courier New">CustomerList.Add(new Customer("John"));</font>
          </p>
          <p>
            <font face="Courier New">CustomerList.Add(new Customer("Mary"));</font>
          </p>
          <p>
            <font face="Courier New">ComboBox CustomerSelection = <font color="#0080ff">new</font> ComboBox();</font>
          </p>
          <p>
            <font face="Courier New">CustomerSelection.DisplayMember = "FirstName";</font>
          </p>
          <p>
            <font face="Courier New">CustomerSelection.ValueMember = "CustomerID";</font>
          </p>
          <p>
            <font face="Courier New">CustomerSelection.DataSource = CustomerList;</font>
          </p>
          <p>
            <em>Note that ListBox controls, like ComboBox controls, use a List Binding to supply
values for the range pf possible values. They both can also use an Item Binding to
connect the actual currently selected value to a data source object.</em>
          </p>
        </blockquote>
        <p>
          <strong>
            <em>
              <font face="Verdana">To Be Continued...</font>
            </em>
          </strong>
        </p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=606cf429-221c-4b83-8167-305181917e7c" />
      </body>
      <title>Adventures in Databinding ~ Part 2 ~ Simple versus Complex Binding</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,606cf429-221c-4b83-8167-305181917e7c.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2007/01/09/AdventuresInDatabindingPart2SimpleVersusComplexBinding.aspx</link>
      <pubDate>Tue, 09 Jan 2007 05:21:26 GMT</pubDate>
      <description>&lt;p&gt;
Databinding in .NET is immensely powerful. You can bind nearly any property of any
object to any property of any control. The source object can be any .NET object -
a business component, a DataSet, a built-in .NET class, or even another Control! Of
course like any powerful feature, the &lt;em&gt;Devil is in the Details&lt;/em&gt;.
&lt;/p&gt;
&lt;h3&gt;Simple versus Complex Binding
&lt;/h3&gt;
&lt;p&gt;
To understand the databinding system first requires acknowledgement that there is
in fact two "flavors" of databinding. You can bind to two very different categories
of objects, and this is what differentiates the flavors of binding. The two flavors
are called &lt;strong&gt;Simple&lt;/strong&gt; and &lt;strong&gt;Complex&lt;/strong&gt; binding. This is somewhat
of a misnomer in my opinion as there is nothing inherently more complicated about
Complex binding - it's just &lt;em&gt;different&lt;/em&gt;. I would prefer to call these two forms
of binding &lt;strong&gt;Item&lt;/strong&gt; and &lt;strong&gt;List&lt;/strong&gt; binding, as that more accurately
describes their use. In fact, I will try to refer to them as such throughout these
posts.
&lt;/p&gt;
&lt;h4&gt;Item Binding
&lt;/h4&gt;
&lt;p&gt;
Item Binding refers to the connection of a source object property value to a target
control's bindable property. These connections are typically two-way, in other words
you can change either side of the connection and the databinding system will push
the change to the other side. Another cool aspect is that you can bind many controls
to the same source property - however you cannot bind a control's property to more
than one source. An example of this would be binding the &lt;strong&gt;&lt;em&gt;Text&lt;/em&gt;&lt;/strong&gt; property
of a &lt;strong&gt;&lt;em&gt;Label&lt;/em&gt;&lt;/strong&gt; control to the &lt;strong&gt;&lt;em&gt;FirstName&lt;/em&gt;&lt;/strong&gt; string
property of a Customer object.
&lt;/p&gt;
&lt;h4&gt;List Binding
&lt;/h4&gt;
&lt;p&gt;
List Binding refers to the connection of a source list of objects to a target control
that is capable of display and/or navigating between multiple items in the list. The
source list can be any .NET object that implements IList, ICollection, IEnumerable&amp;nbsp;or
IBindingList, including arrays, collections, generic lists, and DataTables. In more
advanced scenarios, an object that implements IListSource can also be used - IListSource
simply defines a list of lists. Controls that are able to participate in List Binding
include the ubiquitous DataGrid/DataGridView, and many other controls that consume
lists of items for various reasons - DropDowns, ListBoxes, and TreeViews to name a
few.
&lt;/p&gt;
&lt;h4&gt;Mixing and Matching
&lt;/h4&gt;
&lt;p&gt;
Unfortunately, you usually cannot mix (or should not mix) both Item and List Binding
in the same source objects. Due to the way the databinding system discovers and uses
databinding interfaces (will be discussed in a followup topic), it is not possible
to have both Item and List bindings on the same object. An example of this would be
binding to Customer entries in a list as well as the Count property of the list itself.
&lt;/p&gt;
&lt;h4&gt;Examples
&lt;/h4&gt;
&lt;h5&gt;Item Binding Examples
&lt;/h5&gt;
&lt;p&gt;
When creating Item Binding connections, you always begin with the target control,
and add to its DataBindings collection a list of property names and their sources.
DataBindings.Add() is an overloaded method with two main usage scenarios. Most of
the time you will use the form of Add(PropertyName, DataSource, SourcePropertyName).
In more rare situations you might want to create a Binding object directly and and
use the form Add(Binding)... this can be useful when you want to override default
formatting and parsing of values.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Binding to a property of a business object 
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New" size=2&gt;Customer C = &lt;font color=#0080ff&gt;new&lt;/font&gt; Customer("John"); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size=2&gt;TextBox TextBox1 = &lt;font color=#0080ff&gt;new&lt;/font&gt; TextBox(); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size=2&gt;TextBox1.DataBindings.Add("Text", C, "FirstName"); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size=2&gt;&lt;em&gt;-or-&lt;/em&gt; &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size=2&gt;Binding B = &lt;font color=#0080ff&gt;new&lt;/font&gt; Binding("Text",
C, "FirstName"); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size=2&gt;TextBox1.DataBindings.Add(B);&lt;/font&gt; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
Binding to a public field of a business object 
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
You can't do it in this version of the framework! 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
Binding to a field in a DataTable 
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;DataTable CustomerDT = &lt;font color=#0080ff&gt;new&lt;/font&gt; DataTable("Customers"); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerDT.Columns.Add("FirstName", typeof(string)); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerDT.Rows.Add(&lt;font color=#0080ff&gt;new object&lt;/font&gt;[1]
{"John"}); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;TextBox TextBox1 = &lt;font color=#0080ff&gt;new&lt;/font&gt; TextBox(); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;TextBox1.DataBindings.Add("Text", CustomerDT, "FirstName");&lt;/font&gt; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
Binding multiple controls to the same source data 
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;CheckBox CheckBox1 = &lt;font color=#0080ff&gt;new&lt;/font&gt; CheckBox(); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;TextBox TextBox1 = &lt;font color=#0080ff&gt;new&lt;/font&gt; TextBox(); &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;TextBox1.DataBindings.Add("Enabled", CheckBox1, "Checked");&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;h5&gt;List Binding Examples
&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
Binding a grid to a DataTable&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;DataSet CustomerDS = &lt;font color=#0080ff&gt;new&lt;/font&gt; DataSet();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;DataTable CustomerDT = CustomerDS.Tables.Add("Customers");&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerDT.Columns.Add("FirstName", typeof(string));&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;DataGrid CustomerGrid = &lt;font color=#0080ff&gt;new&lt;/font&gt; DataGrid();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerGrid.DataSource = CustomerDT;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Note that the following can also replace the above DataSource assignment:&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerGrid.DataMember = "Customers";&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerGrid.DataSource = CustomerDS;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;However, it is very important to realize that while on the surface they may appear
to give identical results, these datasource assignments are &lt;strong&gt;not the same&lt;/strong&gt;!
I will explain this further in part 6 of this series.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
Binding a ComboBox to an array&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;string[] StatusList = &lt;font color=#0080ff&gt;new&lt;/font&gt; string[2]
{"Active", "Canceled", "Completed"};&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;ComboBox&amp;nbsp;CurrentStatus = &lt;font color=#0080ff&gt;new&lt;/font&gt; ComboBox();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CurrentStatus.DataSource = StatusList;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Note that with a ComboBox, the List Binding is what is used to supply the list
of possible values displayed when activating the control.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
Binding a ListBox to a Business Object Collection&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;List&amp;lt;Customer&amp;gt; CustomerList = &lt;font color=#0080ff&gt;new&lt;/font&gt; List&amp;lt;Customer&amp;gt;;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerList.Add(new Customer("John"));&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerList.Add(new Customer("Mary"));&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;ComboBox CustomerSelection = &lt;font color=#0080ff&gt;new&lt;/font&gt; ComboBox();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerSelection.DisplayMember = "FirstName";&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerSelection.ValueMember = "CustomerID";&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;CustomerSelection.DataSource = CustomerList;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Note that ListBox controls, like ComboBox controls, use a List Binding to supply
values for the range pf possible values. They both can also use an Item Binding to
connect the actual currently selected value to a data source object.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;&lt;em&gt;&lt;font face=Verdana&gt;To Be Continued...&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=606cf429-221c-4b83-8167-305181917e7c" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,606cf429-221c-4b83-8167-305181917e7c.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=4ad99e3f-44f3-4304-ab9f-dd11ae029e44</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,4ad99e3f-44f3-4304-ab9f-dd11ae029e44.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,4ad99e3f-44f3-4304-ab9f-dd11ae029e44.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=4ad99e3f-44f3-4304-ab9f-dd11ae029e44</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Rik explains how to use a Visual Studio macro to <a href="http://www.r2musings.com/GoogleMSDNSearchWithinVisualStudio2005.aspx">search
for highlited text using Google</a> (or alternatively from MSDN2 online) directly
from within the IDE... its a pretty cool trick.
</p>
        <p>
Which reminds me - Rik R has been a friend of mine for a few years now (a former coworker
from 2001/2002), we were building highly interactive websites years ago using javascript,
xml, and XmlHttpRequest. Today, we would call such a system a "Web 2.0 AJAX site".
But back then, it was seen as heretical - since postbacks were the status quo. Anyways...
I finally talked him into blogging... you can catch the feed at <a href="http://www.r2musings.com">www.r2musings.com</a> as
he writes about his journey in the land of .NET
</p>
        <p>
Speaking of new bloggers.... I also convinced Dan Attis to pick up the habit not too
long ago... and as you can tell from the activity on his <a href="http://devcow.com/blogs/jdattis/default.aspx">weblog</a>,
he is quite the prolific writer!
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=4ad99e3f-44f3-4304-ab9f-dd11ae029e44" />
      </body>
      <title>Adding a Google or MSDN2 search to VS2005</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,4ad99e3f-44f3-4304-ab9f-dd11ae029e44.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2006/01/30/AddingAGoogleOrMSDN2SearchToVS2005.aspx</link>
      <pubDate>Mon, 30 Jan 2006 20:52:21 GMT</pubDate>
      <description>&lt;p&gt;
Rik explains how to use a Visual Studio macro to &lt;a href="http://www.r2musings.com/GoogleMSDNSearchWithinVisualStudio2005.aspx"&gt;search
for highlited text using Google&lt;/a&gt; (or alternatively from MSDN2 online) directly
from within the IDE... its a pretty cool trick.
&lt;/p&gt;
&lt;p&gt;
Which reminds me - Rik R has been a friend of mine for a few years now (a former coworker
from 2001/2002), we were building highly interactive websites years ago using javascript,
xml, and XmlHttpRequest. Today, we would call such a system a "Web 2.0 AJAX site".
But back then, it was seen as heretical - since postbacks were the status quo. Anyways...
I finally talked him into blogging... you can catch the feed at &lt;a href="http://www.r2musings.com"&gt;www.r2musings.com&lt;/a&gt; as
he writes about his journey in the land of .NET
&lt;/p&gt;
&lt;p&gt;
Speaking of new bloggers.... I also convinced Dan Attis to pick up the habit not too
long ago... and as you can tell from the activity on&amp;nbsp;his &lt;a href="http://devcow.com/blogs/jdattis/default.aspx"&gt;weblog&lt;/a&gt;,
he is quite the prolific writer!
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=4ad99e3f-44f3-4304-ab9f-dd11ae029e44" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,4ad99e3f-44f3-4304-ab9f-dd11ae029e44.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=a666f1c6-99f5-45c3-b799-ab5e73e5f514</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,a666f1c6-99f5-45c3-b799-ab5e73e5f514.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,a666f1c6-99f5-45c3-b799-ab5e73e5f514.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=a666f1c6-99f5-45c3-b799-ab5e73e5f514</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Last May, I posted about how I was <a href="http://www.mindfusioncorp.com/weblog/2005/05/06/Protecting+Assets.aspx">signing
up for an internet-based file backup service</a>. I saw it as insurance for my personal
data, and an investment in my personal sanity. Today was the day I had to "cash in"
on that investment.
</p>
        <p>
The server that I have been using to store my personal files at home has been on its
last leg for a while now. I went through the trouble of installing a RAID controller
months ago and configuring for mirrored drives (faster recovery with mirrored,
and besides I didnt have enough drive bays to support raid 5).
</p>
        <p>
The strong winds yesterday caused the power in my home to waver on and off, which
was the death blow for my ailing rackmounted UPS. And in it's final moments, as a last
act, the UPS must have sent a spike into the server... because at this point, the
server refuses to boot, or even to POST test. The redundant drives, while protecting
me from a disk failure, are pretty useless without a server to power them up.
</p>
        <p>
Thats when the internet backup came to the rescue. I was able to restore every byte
of lost data (last successful backup was only the day before). Our digital photos,
old emails, online banking files, corporate documents, source code repositories,...
everything was salvaged!
</p>
        <p>
I am very glad that I had the foresight nearly a year ago to plan for a significant
data loss, and by taking the right steps managed to mitigate the risk, saving my personal
digital valuables which would surely be lost today if I had not. I would definately
recommend a data protection/backup service such as <a href="http://www.storageguardian.com/index2.htm">Storage
Guardian</a> to anyone with personal data that they consider important (which is pretty
much everyone that owns a computer, isnt it?).
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a666f1c6-99f5-45c3-b799-ab5e73e5f514" />
      </body>
      <title>Planning pays off</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,a666f1c6-99f5-45c3-b799-ab5e73e5f514.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2006/01/16/PlanningPaysOff.aspx</link>
      <pubDate>Mon, 16 Jan 2006 02:03:39 GMT</pubDate>
      <description>&lt;p&gt;
Last May, I posted about how I was &lt;a href="http://www.mindfusioncorp.com/weblog/2005/05/06/Protecting+Assets.aspx"&gt;signing
up for an internet-based file backup service&lt;/a&gt;. I saw it as insurance for my personal
data, and an investment in my personal sanity. Today was the day I had to "cash in"
on that investment.
&lt;/p&gt;
&lt;p&gt;
The server that I have been using to store my personal files at home has been on its
last leg for a while now. I went through the trouble of installing a RAID controller
months ago&amp;nbsp;and configuring for mirrored drives (faster recovery with mirrored,
and besides I didnt have enough drive bays to support raid 5).
&lt;/p&gt;
&lt;p&gt;
The strong winds yesterday caused the power in my home to waver on and off, which
was the death blow for my ailing rackmounted UPS. And in it's final moments, as a&amp;nbsp;last
act, the UPS must have sent a spike into the server... because at this point, the
server refuses to boot, or even to POST test. The redundant drives, while protecting
me from a disk failure, are pretty useless without a server to power them up.
&lt;/p&gt;
&lt;p&gt;
Thats when the internet backup came to the rescue. I was able to restore every byte
of lost data (last successful backup was only the day before). Our digital photos,
old emails, online banking files, corporate documents, source code repositories,...
everything was salvaged!
&lt;/p&gt;
&lt;p&gt;
I am very glad that I had the foresight nearly a year ago to plan for a significant
data loss, and by taking the right steps managed to mitigate the risk, saving my personal
digital valuables which would surely be lost today if I had not. I would definately
recommend a data protection/backup service such as &lt;a href="http://www.storageguardian.com/index2.htm"&gt;Storage
Guardian&lt;/a&gt; to anyone with personal data that they consider important (which is pretty
much everyone that owns a computer, isnt it?).
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a666f1c6-99f5-45c3-b799-ab5e73e5f514" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,a666f1c6-99f5-45c3-b799-ab5e73e5f514.aspx</comments>
      <category>General</category>
      <category>Media</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=58d68111-b577-4edd-997b-28fc0275a6b1</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,58d68111-b577-4edd-997b-28fc0275a6b1.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,58d68111-b577-4edd-997b-28fc0275a6b1.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=58d68111-b577-4edd-997b-28fc0275a6b1</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I have been following this blog for a while now - it is quite active and has great
timely information on AJAX technologies (not just .NET either - they talk about anything
ajax):
</p>
        <p>
 
</p>
        <p>
          <a href="http://www.ajaxian.com/">http://www.ajaxian.com/</a>
        </p>
        <p>
.
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=58d68111-b577-4edd-997b-28fc0275a6b1" />
      </body>
      <title>Interested in AJAX?</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,58d68111-b577-4edd-997b-28fc0275a6b1.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/12/06/InterestedInAJAX.aspx</link>
      <pubDate>Tue, 06 Dec 2005 17:46:48 GMT</pubDate>
      <description>&lt;p&gt;
I have been following this blog for a while now - it is quite active and has great
timely information on AJAX technologies (not just .NET either - they talk about anything
ajax):
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.ajaxian.com/"&gt;http://www.ajaxian.com/&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=58d68111-b577-4edd-997b-28fc0275a6b1" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,58d68111-b577-4edd-997b-28fc0275a6b1.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=6064777c-9422-4eee-a2da-8ed7a04f37a8</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,6064777c-9422-4eee-a2da-8ed7a04f37a8.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,6064777c-9422-4eee-a2da-8ed7a04f37a8.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=6064777c-9422-4eee-a2da-8ed7a04f37a8</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I recently needed to implement an HttpHandler in a project to handle retrieval of
rendered PDF reports from a database. It shouldn't have been a big deal, very few
lines of code, even less than typical since my Business Logic Layer encapsulates all
of the aspects of the data retrieval itself into a single line of code... my handler
only had to set the ContentType, add a couple of headers (Content-Length and Content-Disposition),
and then BinaryWrite() the data. Easy as pie, or so I thought.
</p>
        <p>
The file streamed fine out of the database - no surprises there. Content-Length had
no issue and once I remembered to install Acrobat Reader into my VPC where I was testing
this, then the ContentType of "application/pdf" worked as well.
</p>
        <p>
But try as I might, I could not seem to get that darn Content-Disposition to be recognized
by Internet Explorer! Every time I tested it, the "Save" dialog would always display
a random file name, instead of the one I supplied in the header.
</p>
        <p>
I double-checked, then triple-checked my code. I had two other web developers look
at the code, and give it a thumbs-up. I even resorted to tracing the HTTP protocol
traffic just to be 100% certain that IE was getting the HTTP header. Sure enough,
the header was being set and IE was seeing it. But it wasnt obeying it.
</p>
        <p>
It turns out there seems to be a maximum length to the filename you can supply using
the attachment notation of the Content-Disposition header. And my filename was in
excess of that limit, causing it to be ignored by IE. While I am not sure what the
exact limit is (or if it is some other kind of esoteric bug in IE), and do not have
time to experiment and discover that limit, simply reducing the length of my attachment
filename has resolved the issue.
</p>
        <p>
By the way, the length of the filename causing a problem was only something
like 40 to 50 characters, which really isn't unrealistic. I was embedding the report
execution date/time (in a string format that is valid in a file name), in order to
prevent saved reports from being overwritten.
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=6064777c-9422-4eee-a2da-8ed7a04f37a8" />
      </body>
      <title>Weird HTTP header issue in Internet Explorer 6</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,6064777c-9422-4eee-a2da-8ed7a04f37a8.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/12/05/WeirdHTTPHeaderIssueInInternetExplorer6.aspx</link>
      <pubDate>Mon, 05 Dec 2005 03:55:51 GMT</pubDate>
      <description>&lt;p&gt;
I recently needed to implement an HttpHandler in a project to handle retrieval of
rendered PDF reports from a database. It shouldn't have been a big deal, very few
lines of code, even less than typical since my Business Logic Layer encapsulates all
of the aspects of the data retrieval itself into a single line of code... my handler
only had to set the ContentType, add a couple of headers (Content-Length and Content-Disposition),
and then BinaryWrite() the data. Easy as pie, or so I thought.
&lt;/p&gt;
&lt;p&gt;
The file streamed fine out of the database - no surprises there. Content-Length had
no issue and once I remembered to install Acrobat Reader into my VPC where I was testing
this, then the ContentType of "application/pdf"&amp;nbsp;worked as well.
&lt;/p&gt;
&lt;p&gt;
But try as I might, I could not seem to get that darn Content-Disposition to be recognized
by Internet Explorer! Every time I tested it, the "Save" dialog would always display
a random file name, instead of the one I supplied in the header.
&lt;/p&gt;
&lt;p&gt;
I double-checked, then triple-checked my code. I had two other web developers look
at the code, and give it a thumbs-up. I even resorted to tracing the HTTP protocol
traffic just to be 100% certain that IE was getting the HTTP header. Sure enough,
the header was being set and IE was seeing it. But it wasnt obeying it.
&lt;/p&gt;
&lt;p&gt;
It turns out there seems to be a maximum length to the filename you can supply using
the attachment notation of the Content-Disposition header. And my filename was in
excess of that limit, causing it to be ignored by IE. While I am not sure what the
exact limit is (or if it is some other kind of esoteric bug in IE), and do not have
time to experiment and discover that limit, simply reducing the length of my attachment
filename has resolved the issue.
&lt;/p&gt;
&lt;p&gt;
By the way, the length&amp;nbsp;of the filename causing a problem&amp;nbsp;was only something
like 40 to 50 characters, which really isn't unrealistic. I was embedding the report
execution date/time (in a string format that is valid in a file name), in order to
prevent saved reports from being overwritten.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=6064777c-9422-4eee-a2da-8ed7a04f37a8" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,6064777c-9422-4eee-a2da-8ed7a04f37a8.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=de3faa12-513f-4d5d-90af-f394f5a778e4</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,de3faa12-513f-4d5d-90af-f394f5a778e4.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,de3faa12-513f-4d5d-90af-f394f5a778e4.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=de3faa12-513f-4d5d-90af-f394f5a778e4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I saw this come across on slashdot this morning...
</p>
        <p>
It seems <a href="http://www.vmware.com/">VMWare</a> has a new free "<a href="http://www.vmware.com/products/player/">player</a>"
product. It appears to be the same as vmware 5 workstation, except that you cannot
create new virtual machines or add hardware to existing ones - you can only use machines
created using one of the full-featured versions (Wkstn/GSX/ESX). Aside from that,
it's supposed to be fully-functional.
</p>
        <p>
And it claims to support Virtual PC / Virtual Server images as well.
</p>
        <p>
And thats pretty cool, since vmware has always been a better virtualization product
than VPC. The only reason most shops use VPC right now is because it comes with MSDN
subscriptions.
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=de3faa12-513f-4d5d-90af-f394f5a778e4" />
      </body>
      <title>VMWare Player</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,de3faa12-513f-4d5d-90af-f394f5a778e4.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/10/21/VMWarePlayer.aspx</link>
      <pubDate>Fri, 21 Oct 2005 18:42:21 GMT</pubDate>
      <description>&lt;p&gt;
I saw this come across on slashdot this morning...
&lt;/p&gt;
&lt;p&gt;
It seems &lt;a href="http://www.vmware.com/"&gt;VMWare&lt;/a&gt; has a new free "&lt;a href="http://www.vmware.com/products/player/"&gt;player&lt;/a&gt;"
product. It appears to be the same as vmware 5 workstation, except that you cannot
create new virtual machines or add hardware to existing ones - you can only use machines
created using one of the full-featured versions (Wkstn/GSX/ESX). Aside from that,
it's supposed to be fully-functional.
&lt;/p&gt;
&lt;p&gt;
And it claims to support Virtual PC / Virtual Server images as well.
&lt;/p&gt;
&lt;p&gt;
And thats pretty cool, since vmware has always been a better virtualization product
than VPC. The only reason most shops use VPC right now is because it comes with MSDN
subscriptions.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=de3faa12-513f-4d5d-90af-f394f5a778e4" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,de3faa12-513f-4d5d-90af-f394f5a778e4.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=06c5880b-f6a4-419a-a7ff-ef26bd242ec5</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,06c5880b-f6a4-419a-a7ff-ef26bd242ec5.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,06c5880b-f6a4-419a-a7ff-ef26bd242ec5.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=06c5880b-f6a4-419a-a7ff-ef26bd242ec5</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This was a presentation I gave earlier this month (October 2005) to the <a href="http://www.atlantacsharp.org/">Atlanta
C# Developer Group</a>.
</p>
        <p>
Code generation is one of those "cool" techniques in software development where you
just don't know what you have been missing until you see it in action... and then
once exposed to it, you find yourself wondering "how did I ever get along without
this?".
</p>
        <p>
In this presentation, I discussed the reasons and benefits of using code generation
tools, and the problems they can solve (or avoid entirely). I focused on the benefits
of consistent code, building upon a solid foundation, and simplification of complex
application features.
</p>
        <p>
We designed and built the code for a basic application foundation, supporting simple
features such as lightweight enforced transactions, entity persistence, and other
baseline features. Then a series of linked templates were created that take advantage
of that code foundation. Finally, we built an example UI that leverages the generated
middleware to dramatically simplify and streamline the actual development process.
It was pretty durn cool IMO.
</p>
        <p>
All templates were built using <a href="http://www.codesmithtools.com/">CodeSmith</a>,
which is a fantastically useful tool. I feel like I might have been giving a sales
pitch for that product by showing off many of the way too cool features of the new
version of CodeSmith, but it's one of those things I strongly feel is worth every
penny.
</p>
        <p>
The powerpoint slide deck and all relevant source code can be downloaded from the
presentation archive of the Atlanta C# Developer's Group website at: <a href="http://www.atlantacsharp.org/PresentationArchive.aspx">http://www.atlantacsharp.org/PresentationArchive.aspx</a></p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=06c5880b-f6a4-419a-a7ff-ef26bd242ec5" />
      </body>
      <title>C# UG Presentation: Engineering an Application Foundation using Code Generation</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,06c5880b-f6a4-419a-a7ff-ef26bd242ec5.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/10/17/CUGPresentationEngineeringAnApplicationFoundationUsingCodeGeneration.aspx</link>
      <pubDate>Mon, 17 Oct 2005 18:55:57 GMT</pubDate>
      <description>&lt;p&gt;
This was a presentation I gave earlier this month (October 2005) to the &lt;a href="http://www.atlantacsharp.org/"&gt;Atlanta
C# Developer Group&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Code generation is one of those "cool" techniques in software development where you
just don't know what you have been missing until you see it in action... and then
once exposed to it, you find yourself wondering "how did I ever get along without
this?".
&lt;/p&gt;
&lt;p&gt;
In this presentation, I discussed the reasons and benefits of using code generation
tools, and the problems they can solve (or avoid entirely). I focused on the benefits
of consistent code, building upon a solid foundation, and simplification of complex
application features.
&lt;/p&gt;
&lt;p&gt;
We designed and built the code for a basic application foundation, supporting simple
features such as lightweight enforced transactions, entity persistence, and other
baseline features. Then a series of linked templates were created that take advantage
of that code foundation. Finally, we built an example UI that leverages the generated
middleware to dramatically simplify and streamline the actual development process.
It was pretty durn cool IMO.
&lt;/p&gt;
&lt;p&gt;
All templates were built using &lt;a href="http://www.codesmithtools.com/"&gt;CodeSmith&lt;/a&gt;,
which is a fantastically useful tool. I feel like I might have been giving a sales
pitch for that product by showing off many of the way too cool features of the new
version of CodeSmith, but it's one of those things I strongly feel is worth every
penny.
&lt;/p&gt;
&lt;p&gt;
The powerpoint slide deck and all relevant source code can be downloaded from the
presentation archive of the&amp;nbsp;Atlanta C# Developer's Group website at: &lt;a href="http://www.atlantacsharp.org/PresentationArchive.aspx"&gt;http://www.atlantacsharp.org/PresentationArchive.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=06c5880b-f6a4-419a-a7ff-ef26bd242ec5" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,06c5880b-f6a4-419a-a7ff-ef26bd242ec5.aspx</comments>
      <category>.NET</category>
      <category>Events</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=a3019722-8f26-4fb1-8178-37080f2f57e8</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,a3019722-8f26-4fb1-8178-37080f2f57e8.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,a3019722-8f26-4fb1-8178-37080f2f57e8.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=a3019722-8f26-4fb1-8178-37080f2f57e8</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I actually gave this short presentation to the <a href="http://www.atlantacsharp.org/">Atlanta
C# Developer Group</a> back in September, but never got around to blogging about it...
</p>
        <p>
The presentation covered why you should be using custom exception classes in your
own code, and how to structure your exception class inheritance to gain the most
benefit. It showed working examples of the concepts. It also touched on a few related
practices such as only catching exceptions that you can deal with, and designing a
meaningful exception taxonomy.
</p>
        <p>
The slides and source code can be downloaded from the Atlanta C# Developer Group's
presentation archive at: <a href="http://www.atlantacsharp.org/PresentationArchive.aspx">http://www.atlantacsharp.org/PresentationArchive.aspx</a></p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a3019722-8f26-4fb1-8178-37080f2f57e8" />
      </body>
      <title>C# UG Presentation: Custom Exceptions</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,a3019722-8f26-4fb1-8178-37080f2f57e8.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/10/17/CUGPresentationCustomExceptions.aspx</link>
      <pubDate>Mon, 17 Oct 2005 18:41:25 GMT</pubDate>
      <description>&lt;p&gt;
I actually gave this short presentation to the &lt;a href="http://www.atlantacsharp.org/"&gt;Atlanta
C# Developer Group&lt;/a&gt; back in September, but never got around to blogging about it...
&lt;/p&gt;
&lt;p&gt;
The presentation covered why you should be using custom exception classes in your
own code, and how to structure your exception&amp;nbsp;class inheritance to gain the most
benefit. It showed working examples of the concepts. It also touched on a few related
practices such as only catching exceptions that you can deal with, and designing a
meaningful exception taxonomy.
&lt;/p&gt;
&lt;p&gt;
The slides and source code can be downloaded from the Atlanta C# Developer Group's
presentation archive at: &lt;a href="http://www.atlantacsharp.org/PresentationArchive.aspx"&gt;http://www.atlantacsharp.org/PresentationArchive.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a3019722-8f26-4fb1-8178-37080f2f57e8" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,a3019722-8f26-4fb1-8178-37080f2f57e8.aspx</comments>
      <category>.NET</category>
      <category>Events</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=a4530fe7-2af8-437c-b86e-700ec5cebdc9</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,a4530fe7-2af8-437c-b86e-700ec5cebdc9.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,a4530fe7-2af8-437c-b86e-700ec5cebdc9.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=a4530fe7-2af8-437c-b86e-700ec5cebdc9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In my previous post, I talked about how to properly design a service. However, I did
not give any real examples of it. All talk and no code. In this post, I hope to show
how to actually do it.
</p>
        <p>
          <hr />
        </p>
        <p>
        </p>
        <h3>Example: Hello, World!
</h3>
        <p>
Because you can never wear out an old example, and everyone already knows the Software
Requirements Specification (SRS) for "Hello, World!".
</p>
        <h5>Contract-First Design
</h5>
        <p>
Starting out, we need to first define the contract of the service that will be known
as HelloWorldService. While I could demonstrate the purist's SOA approach by starting
out with actual XSD schema, I will instead show what 9 out of 10 developers will be
more comfortable with - a .NET interface contract.
</p>
        <p>
HelloWorldService is a simple service, it's functionality is comprised of only one
operation, "HelloWorld". HelloWorld accepts a single string input: "PersonName". It
also returns a single string value: "GreetingText". With these requirements in mind,
I will lay out the following interfaces and supporting class types:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <font color="#0000ff">namespace</font> HelloWorld.Interface<br />
{<br />
    <font color="#0000ff">public class</font> HelloWorldRequest<br />
    {<br />
        <font color="#0000ff">public string</font> PersonName;<br />
    }<br />
    <font color="#0000ff">public class</font> HelloWorldResponse<br />
    {<br />
        <font color="#0000ff">public string</font> GreetingText;<br />
    }<br />
    <font color="#0000ff">public interface</font> IDocHelloWorldService<br />
    {<br />
        <font color="#008000">// This is the document-centric
design method</font><br />
        HelloWorldResponse HelloWorld(HelloWorldRequest
Request);<br />
    }<br />
    <font color="#0000ff">public interface</font> IRpcHelloWorldService<br />
    {<br />
        <font color="#008000">// This is the Rpc-centric
design method</font><br />
        <font color="#0000ff">string </font>HelloWorld(<font color="#0000ff">string </font>PersonName);<br />
    }<br />
}</pre>
        </blockquote>
        <p>
All of these definitions are placed in a single assembly, <strong>HelloWorld.Interface.dll</strong>.
This part is important if you decide to provide a Remoting option, as this will function
as the shared assembly (the equivalent to COM's type library and WebServices' WSDL).
</p>
        <h5>Define Seperate Endpoints and Implementations
</h5>
        <p>
Here is where the rubber hits the road. The guts of the service will live in the Implementation
assembly. Actual endpoints will live in their own assemblies, or web projects. I will
start out by building the Implementation assembly, named <strong>HelloWorld.Implementation.dll</strong>,
which contains the following code:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <font color="#0000ff">namespace </font>HelloWorld.Implementation<br />
{<br />
    <font color="#0000ff">using </font>HelloWorld.Interface;</pre>
          <pre>    <font color="#0000ff">public
class</font> DocHelloWorld: MarshalByRefObject, IDocHelloWorldService<br />
    {<br />
        <font color="#0000ff">public </font>HelloWorldResponse
HelloWorld(HelloWorldRequest Request)<br />
        {<br />
            HelloWorldResponse
Response = <font color="#0000ff">new </font>HelloWorldResponse();<br />
            Response.GreetingText
= <font color="#a52a2a">"Hello, "</font> + Request.PersonName + <font color="#a52a2a">"!"</font>;<br />
            <font color="#0000ff">return </font>Response;<br />
        }<br />
    }<br />
    <font color="#0000ff">public class</font> RpcHelloWorld: MarshalByRefObject,
IRpcHelloWorldService<br />
    {<br />
        <font color="#0000ff">public string</font> HelloWorld(<font color="#0000ff">string </font>PersonName)<br />
        {<br />
            <font color="#0000ff">return </font><font color="#a52a2a">"Hello,
"</font> + PersonName + <font color="#a52a2a">"!"</font>;<br />
        }<br />
    }<br />
}</pre>
        </blockquote>
        <p>
Notice the difference in the amount of code needed to support each design method.
Document-centric can require more code, but the trade-off is for increased control
and flexibility.
</p>
        <p>
Now, we can define endpoints.
</p>
        <p>
The simplest "endpoint" is to merely add a direct reference to HelloWorld.Implementation.dll,
and use the service classes directly. This will result in an in-process working instance,
just like any other .NET object.
</p>
        <p>
The next simplest endpoint is to configure the service as a Remotable object. You
might have noticed that I chose to derive my implementation classes from <em>MarshalByRefObject</em>.
This decision allows the Remoting system to expose my implementation classes as Remoting
objects - objects that run in one process/machine, but are used in another process/machine
transparently [almost] to the calling code.
</p>
        <p>
I will not go into details of how to set up Remoting, Ingo Rammer does a MUCH better
job than I could ever hope to in his book "<em>Advanced .NET Remoting</em>". In essence,
you will need a remoting host (an IIS web application is the easiest), and you will
need to add the web.config entries to expose <font color="#0000ff">IDocHelloWorld</font> and <font color="#0000ff">IRpcHelloWorld</font> as
"well-known services". Note that you are <em>exposing the interfaces</em> here, and <em>NOT
the implementation</em> objects... an important distinction. Then you simply dump
the Interface and Implementation assemblies into the web's bin folder.
</p>
        <p>
On the Remoting client side, you create a similar entry in the application's config
file (alternatively, you can make calls in code to Remoting.Configuration to achieve
the same effect). The client-side configuration causes .NET to channel requests for
the service interface to be forwarded across the network to the target server. In
your client application code, you simply use <strong>Activator.GetObject(<font color="#0000ff">typeof</font>(IDocHelloWorld), <font color="#a52a2a">"remoting
url...."</font>)</strong> to request the remote instance. The framework takes care
of the rest.
</p>
        <p>
Finally, we can define a traditional Web Service endpoint. Since asmx is the simplest
way to do this, we will use that technology in this example, although you could alternatively
use WSE's non-asmx transport ability. We just create a plain-vanilla Web Service asmx
in a web project (named <strong>DocHelloWorldWebService</strong>), and add a reference
to HelloWorld.Interface.dll and HelloWorld.Implementation.dll. We modify the web service
code like so:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <font color="#0000ff">public
class</font> DocHelloWorldWebService : System.Web.Services.WebService, IDocHelloWorld<br />
{<br />
    <font color="#0000ff">using</font> HelloWorld.Interface;<br />
    <font color="#0000ff">using</font> HelloWorld.Implementation;</pre>
          <pre>    <font color="#008000">/*
.... IDE generated stuff .... */</font></pre>
          <pre>    <font color="#808080">[WebMethod]</font><br />
    <font color="#0000ff">public</font> HelloWorldResponse HelloWorld(HelloWorldRequest
request)<br />
    {<br />
        DocHelloWorld = <font color="#0000ff">new</font> DocHelloWorld();<br />
        <font color="#0000ff">return</font> DocHelloWorld(request);<br />
    }<br />
}</pre>
        </blockquote>
        <p>
We can also provide an RPC-centric version by adding a <strong>RpcHelloWorldWebService</strong> like
this:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <font color="#0000ff">public
class</font> RpcHelloWorldWebService : System.Web.Services.WebService, IRpcHelloWorld<br />
{<br />
    <font color="#0000ff">using</font> HelloWorld.Interface;<br />
    <font color="#0000ff">using</font> HelloWorld.Implementation;</pre>
          <pre>    <font color="#008000">/*
.... IDE generated stuff .... */</font></pre>
          <pre>    <font color="#808080">[WebMethod]</font><br />
    <font color="#0000ff">public string</font> HelloWorld(<font color="#0000ff">string</font> personName)<br />
    {<br />
        RpcHelloWorld = <font color="#0000ff">new</font> RpcHelloWorld();<br />
        <font color="#0000ff">return</font> RpcHelloWorld(personName);<br />
    }<br />
}</pre>
        </blockquote>
        <p dir="ltr">
Obviously, you would need to also do a few other things to complete the web service,
such as giving a non-default namespace, etc.
</p>
        <h5>Wrap-up
</h5>
        <p>
So, there you have it. An example of how to properly design a service in .NET. While
not terribly difficult, it certainly is a totally new way of thinking about system
design for many people. Hopefully this is of some benefit to you, who knows it might
save you from a costly code refactoring when you suddenly have to support a new transport
or service endpoint type.
</p>
        <p>
In conclusion, I would also like to point out a few excellent resource books that
are relevant to the subject:
</p>
        <p>
"<em>Advanced .NET Remoting</em>", <strong>Ingo Rammer</strong><br />
"<em>Expert Service-Oriented Architecture in C#</em>", <strong>Jeffrey Hasan</strong><br /></p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a4530fe7-2af8-437c-b86e-700ec5cebdc9" />
      </body>
      <title>Designing a Service, Part 2</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,a4530fe7-2af8-437c-b86e-700ec5cebdc9.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/08/03/DesigningAServicePart2.aspx</link>
      <pubDate>Wed, 03 Aug 2005 22:39:11 GMT</pubDate>
      <description>&lt;p&gt;
In my previous post, I talked about how to properly design a service. However, I did
not give any real examples of it. All talk and no code. In this post, I hope to show
how to actually do it.
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h3&gt;Example: Hello, World!
&lt;/h3&gt;
&lt;p&gt;
Because you can never wear out an old example, and everyone already knows the Software
Requirements Specification (SRS) for "Hello, World!".
&lt;/p&gt;
&lt;h5&gt;Contract-First Design
&lt;/h5&gt;
&lt;p&gt;
Starting out, we need to first define the contract of the service that will be known
as HelloWorldService. While I could demonstrate the purist's SOA approach by starting
out with actual XSD schema, I will instead show what 9 out of 10 developers will be
more comfortable with - a .NET interface contract.
&lt;/p&gt;
&lt;p&gt;
HelloWorldService is a simple service, it's functionality is comprised of only one
operation, "HelloWorld". HelloWorld accepts a single string input: "PersonName". It
also returns a single string value: "GreetingText". With these requirements in mind,
I will lay out the following interfaces and supporting class types:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font color=#0000ff&gt;namespace&lt;/font&gt; HelloWorld.Interface&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public class&lt;/font&gt; HelloWorldRequest&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;public string&lt;/font&gt; PersonName;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public class&lt;/font&gt; HelloWorldResponse&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;public string&lt;/font&gt; GreetingText;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public interface&lt;/font&gt; IDocHelloWorldService&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=#008000&gt;// This is the document-centric
design method&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HelloWorldResponse HelloWorld(HelloWorldRequest
Request);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public interface&lt;/font&gt; IRpcHelloWorldService&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=#008000&gt;// This is the Rpc-centric
design method&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;string &lt;/font&gt;HelloWorld(&lt;font color=#0000ff&gt;string &lt;/font&gt;PersonName);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
All of these definitions are placed in a single assembly, &lt;strong&gt;HelloWorld.Interface.dll&lt;/strong&gt;.
This part is important if you decide to provide a Remoting option, as this will function
as the shared assembly (the equivalent to COM's type library and WebServices' WSDL).
&lt;/p&gt;
&lt;h5&gt;Define Seperate Endpoints and Implementations
&lt;/h5&gt;
&lt;p&gt;
Here is where the rubber hits the road. The guts of the service will live in the Implementation
assembly. Actual endpoints will live in their own assemblies, or web projects. I will
start out by building the Implementation assembly, named &lt;strong&gt;HelloWorld.Implementation.dll&lt;/strong&gt;,
which contains the following code:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font color=#0000ff&gt;namespace &lt;/font&gt;HelloWorld.Implementation&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;using &lt;/font&gt;HelloWorld.Interface;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public
class&lt;/font&gt; DocHelloWorld: MarshalByRefObject, IDocHelloWorldService&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;public &lt;/font&gt;HelloWorldResponse
HelloWorld(HelloWorldRequest Request)&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; HelloWorldResponse
Response = &lt;font color=#0000ff&gt;new &lt;/font&gt;HelloWorldResponse();&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; Response.GreetingText
= &lt;font color=#a52a2a&gt;"Hello, "&lt;/font&gt; + Request.PersonName + &lt;font color=#a52a2a&gt;"!"&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; &lt;font color=#0000ff&gt;return &lt;/font&gt;Response;&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;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public class&lt;/font&gt; RpcHelloWorld: MarshalByRefObject,
IRpcHelloWorldService&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;public string&lt;/font&gt; HelloWorld(&lt;font color=#0000ff&gt;string &lt;/font&gt;PersonName)&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; &lt;font color=#0000ff&gt;return &lt;/font&gt;&lt;font color=#a52a2a&gt;"Hello,
"&lt;/font&gt; + PersonName + &lt;font color=#a52a2a&gt;"!"&lt;/font&gt;;&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;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Notice the difference in the amount of code needed to support each design method.
Document-centric can require more code, but the trade-off is for increased control
and flexibility.
&lt;/p&gt;
&lt;p&gt;
Now, we can define endpoints.
&lt;/p&gt;
&lt;p&gt;
The simplest "endpoint" is to merely add a direct reference to HelloWorld.Implementation.dll,
and use the service classes directly. This will result in an in-process working instance,
just like any other .NET object.
&lt;/p&gt;
&lt;p&gt;
The next simplest endpoint is to configure the service as a Remotable object. You
might have noticed that I chose to derive my implementation classes from &lt;em&gt;MarshalByRefObject&lt;/em&gt;.
This decision allows the Remoting system to expose my implementation classes as Remoting
objects - objects that run in one process/machine, but are used in another process/machine
transparently [almost] to the calling code.
&lt;/p&gt;
&lt;p&gt;
I will not go into details of how to set up Remoting, Ingo Rammer does a MUCH better
job than I could ever hope to in his book "&lt;em&gt;Advanced .NET Remoting&lt;/em&gt;". In essence,
you will need a remoting host (an IIS web application is the easiest), and you will
need to add the web.config entries to expose &lt;font color=#0000ff&gt;IDocHelloWorld&lt;/font&gt; and &lt;font color=#0000ff&gt;IRpcHelloWorld&lt;/font&gt; as
"well-known services". Note that you are &lt;em&gt;exposing the interfaces&lt;/em&gt; here, and &lt;em&gt;NOT
the implementation&lt;/em&gt; objects... an important distinction. Then you simply dump
the Interface and Implementation assemblies into the web's bin folder.
&lt;/p&gt;
&lt;p&gt;
On the Remoting client side, you create a similar entry in the application's config
file (alternatively, you can make calls in code to Remoting.Configuration to achieve
the same effect). The client-side configuration causes .NET to channel requests for
the service interface to be forwarded across the network to the target server. In
your client application code, you simply use &lt;strong&gt;Activator.GetObject(&lt;font color=#0000ff&gt;typeof&lt;/font&gt;(IDocHelloWorld), &lt;font color=#a52a2a&gt;"remoting
url...."&lt;/font&gt;)&lt;/strong&gt; to request the remote instance. The framework takes care
of the rest.
&lt;/p&gt;
&lt;p&gt;
Finally, we can define a traditional Web Service endpoint. Since asmx is the simplest
way to do this, we will use that technology in this example, although you could alternatively
use WSE's non-asmx transport ability. We just create a plain-vanilla Web Service asmx
in a web project (named &lt;strong&gt;DocHelloWorldWebService&lt;/strong&gt;), and add a reference
to HelloWorld.Interface.dll and HelloWorld.Implementation.dll. We modify the web service
code like so:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font color=#0000ff&gt;public class&lt;/font&gt; DocHelloWorldWebService
: System.Web.Services.WebService, IDocHelloWorld&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;using&lt;/font&gt; HelloWorld.Interface;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;using&lt;/font&gt; HelloWorld.Implementation;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;/*
.... IDE generated stuff .... */&lt;/font&gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#808080&gt;[WebMethod]&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public&lt;/font&gt; HelloWorldResponse HelloWorld(HelloWorldRequest
request)&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; DocHelloWorld = &lt;font color=#0000ff&gt;new&lt;/font&gt; DocHelloWorld();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;return&lt;/font&gt; DocHelloWorld(request);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
We can also provide an RPC-centric version by adding a &lt;strong&gt;RpcHelloWorldWebService&lt;/strong&gt; like
this:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font color=#0000ff&gt;public class&lt;/font&gt; RpcHelloWorldWebService
: System.Web.Services.WebService, IRpcHelloWorld&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;using&lt;/font&gt; HelloWorld.Interface;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;using&lt;/font&gt; HelloWorld.Implementation;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;/*
.... IDE generated stuff .... */&lt;/font&gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#808080&gt;[WebMethod]&lt;/font&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;public string&lt;/font&gt; HelloWorld(&lt;font color=#0000ff&gt;string&lt;/font&gt; personName)&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; RpcHelloWorld = &lt;font color=#0000ff&gt;new&lt;/font&gt; RpcHelloWorld();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0000ff&gt;return&lt;/font&gt; RpcHelloWorld(personName);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
Obviously, you would need to also do a few other things to complete the web service,
such as giving a non-default namespace, etc.
&lt;/p&gt;
&lt;h5&gt;Wrap-up
&lt;/h5&gt;
&lt;p&gt;
So, there you have it. An example of how to properly design a service in .NET. While
not terribly difficult, it certainly is a totally new way of thinking about system
design for many people. Hopefully this is of some benefit to you, who knows it might
save you from a costly code refactoring when you suddenly have to support a new transport
or service endpoint type.
&lt;/p&gt;
&lt;p&gt;
In conclusion, I would also like to point out a few excellent resource books that
are relevant to the subject:
&lt;/p&gt;
&lt;p&gt;
"&lt;em&gt;Advanced .NET Remoting&lt;/em&gt;", &lt;strong&gt;Ingo Rammer&lt;/strong&gt;
&lt;br&gt;
"&lt;em&gt;Expert Service-Oriented Architecture in C#&lt;/em&gt;", &lt;strong&gt;Jeffrey Hasan&lt;/strong&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=a4530fe7-2af8-437c-b86e-700ec5cebdc9" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,a4530fe7-2af8-437c-b86e-700ec5cebdc9.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=37cfaa85-f691-461a-8b28-7f0586ca5b0d</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,37cfaa85-f691-461a-8b28-7f0586ca5b0d.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,37cfaa85-f691-461a-8b28-7f0586ca5b0d.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=37cfaa85-f691-461a-8b28-7f0586ca5b0d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <br />
Last week I hooked up with a few other smart guys after the <a href="http://www.atlantadotnet.org/">Atlanta
.NET User Group</a> meeting. We were at the regular post-nerd-meeting hangout - <a href="http://www.buffalowildwings.com">Buffalo
Wild Wings</a> on Mansell Road.
</p>
        <p>
We talked about a number of interesting topics, including AJAX/Atlas, Vista, and Indigo.
At one point, someone questioned the validity of Remoting in light of WebServices,
and wondered why anyone was using it now that is is supposedly on the way out. And
my perspective was "why choose at all?". It is perfectly feasible and dare I say it
"good practice" to design your system to support both. In fact, if you do things right,
you will even be prepared for a smoother migration to Indigo or WSE.
</p>
        <p>
So what is the secret trick to designing a service like this? Simple: it's called
"contract-first design". Back in the days of COM, you might have known it as "interface-first".
</p>
        <p>
          <hr />
        </p>
        <p>
        </p>
        <h3>Contract-First Service Design
</h3>
        <p>
The concept is surprisingly simple. A "service", whether it be a Web Service, system
Service, or logical in-process service, can be defined as a unit of system functionality
that operates independently of other units, and provides a well-known and concise
interface. What this means is that no matter how complex a peice of functionality
may be, it can be described in terms of some abstract interface. In Service nomenclature,
this interface is called the "<em>contract</em>". The "contract" states the individual
methods (operations) that a given service implements.
</p>
        <p>
When we talk about Web Services, the "contract" is expressed as a WSDL document. When
we talk about Remoting, this contract is expressed as compiled IL in a shared assembly.
In COM, the contract was expressed in the Type Library. Indigo's name for this idea
is by far the most explicit and clear, the "ServiceContract".
</p>
        <p>
When you define a contract, you are declaring the exact functionality that a service
MUST provide, and which a client MAY consume. The Service is not allowed (theoretically)
to provide funtionality that exceeds or falls short of that contract, and the Client
is not able to request any functionality that falls outside the scope of the contract.
Furthermore, the contract also defines the specifics of HOW the functionality is to
be addressed... for example, an operation requires a specific set of inputs, and will
not respond (or should not) to inputs which are invalid or incomplete.
</p>
        <p>
Therefore, a Service Contract ensures a consistent and predictable interaction between
client and service.
</p>
        <p>
          <em>So HOW do we go about designing a .NET solution in such a manner?</em>
        </p>
        <h5>Plan ahead.
</h5>
        <p>
It is far easier to produce an adaptable architecture if you plan ahead for the adaptability.
This means thinking about your interface before you think about the implementation.
</p>
        <p>
At a minimum, start with defining your interface(s). You will need to define a seperate
interface for each logical service. If you are a SOA purist, then this is where you
bust out with the XSD editor and define your messages, operations, and portTypes.
If you are not an SOA purist, then this is where you start laying out .NET interface
definitions (yes, the language constructs that are defined with the "interface" keyword).
Even if you are going the pure-SOA route, you will want to run the xsd.exe compiler
against your schema to create some .NET stubs.... then change those from "class" to
"interface" definitions. Either way, on the .NET side you want a set of interface
definitions for the services, and class definitions for the complex structures.
</p>
        <p>
And here you must make a choice. Do you want to (A) design a completely document-centric
service, or (B) an rpc-centric service? If you want document-centric services, then
you will want to create explicit types for every operation/method, one for the input
and one for the output... even if the content is not complex. If you want RPC-centric
services, then you can save a small amount of effort by only defining explicit types
for cases where you wish to return or accept complex structures.
</p>
        <pre>  <strong>Design Method A</strong></pre>
        <pre>    OperationAResponse = {complex type or simple type...}<br />
    OperationARequest = {complex type or simple type...}<br />
    OperationA = function(OperationARequest), returns OperationAResponse</pre>
        <pre>  <strong>Design
Method B</strong></pre>
        <pre>    OperationB = function(complex or simple type(s)), returns simple type or void</pre>
        <p>
One word of warning: stay away from "ref" or "out" parameters if you choose to follow
Design Method A.
</p>
        <p>
One thing you might notice about Design Method A is that all operations will have
a similar pattern, regardless of inputs and outputs. This is not coincidental. The
Request and Response structures are what we call "documents" in a document-centric
SOA (also called "<em>message-centric</em>"). There is great flexibility and power
in a message-centric design.
</p>
        <h5>Define Seperate Endpoints and Implementations
</h5>
        <p>
This is what fouls up most attempts at designing a good service. Having the contract
pre-defined is not enough - you must also differentiate the service from the consumer.
In the real world, your service will almost always be centralized, but the consumer(s)
will be dispersed. This means that one (1) service may have multiple (N) endpoints.
An endpoint is merely an identifiable address where the implemented service functionality
can be found.
</p>
        <p>
          <em>The problem is that most people do not distinguish between the endpoint and the
implementation.</em> They simple fire up a new asmx file and start dumping code into
it. This is a <strong>BAD PRACTICE</strong>. The asmx is simply and endpoint,
and should not be doing any work except passing the calls over to a real implementation.
In other words, the asmx should be nothing more than a <a href="http://en.wikipedia.org/wiki/Facade_pattern">Facade</a>.
</p>
        <p>
A better approach is to implement the service itself in an external class... better
yet, in an external assembly. This implementation class should implement the defined
interface, just as you would implement any other .NET interface in a class. Then,
you also implement that very same .NET interface in your asmx, however in the asmx
you simply forward the calls to an instance of the external implementation class.
Your Web Service methods become extremely simple shells that are marked up with the <font face="Courier New">[WebMethod()]</font> attribute
and delegate the work to the external class. Very clean and tidy.
</p>
        <p>
Once you have implemented your service like this, many more options become available.
You get the flexibility to create new endpoints, possibly with differing authorization
abilities (external facing ones might enforce WSE security, while internal ones might
not). You also get the ability to very easily expose the service via other transports...
such as Remoting. Either create a new endpoint object that derives from MarshalByRefObject,
or make the service implementation itself derive from MBRO. Then you can add a 
<WELLKNOWN>
entry to an application config file, and your service is now exposed via Remoting,
with an identical interface to the web service! And finally, you enable the consumer
of your service to simply reference it directly as an assembly, if that is desired
for performance or security.
</WELLKNOWN></p>
        <h5>Wrap-up
</h5>
        <p>
That wraps it up for this (somewhat basic) discussion of how to design good services.
My next post will follow up with a concrete example of this process.<br /><br />
In conclusion, I would also like to point out a few excellent resource books that
are relevant to the subject:
</p>
        <p>
"<em>Advanced .NET Remoting</em>", <strong>Ingo Rammer</strong><br />
"<em>Expert Service-Oriented Architecture in C#</em>", <strong>Jeffrey Hasan</strong></p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=37cfaa85-f691-461a-8b28-7f0586ca5b0d" />
      </body>
      <title>Designing a Service, Part 1</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,37cfaa85-f691-461a-8b28-7f0586ca5b0d.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/08/03/DesigningAServicePart1.aspx</link>
      <pubDate>Wed, 03 Aug 2005 22:26:59 GMT</pubDate>
      <description>&lt;p&gt;
&lt;br&gt;
Last week I hooked up with a few other smart guys after the &lt;a href="http://www.atlantadotnet.org/"&gt;Atlanta
.NET User Group&lt;/a&gt; meeting. We were at the regular post-nerd-meeting hangout - &lt;a href="http://www.buffalowildwings.com"&gt;Buffalo
Wild Wings&lt;/a&gt; on Mansell Road.
&lt;/p&gt;
&lt;p&gt;
We talked about a number of interesting topics, including AJAX/Atlas, Vista, and Indigo.
At one point, someone questioned the validity of Remoting in light of WebServices,
and wondered why anyone was using it now that is is supposedly on the way out. And
my perspective was "why choose at all?". It is perfectly feasible and dare I say it
"good practice" to design your system to support both. In fact, if you do things right,
you will even be prepared for a smoother migration to Indigo or WSE.
&lt;/p&gt;
&lt;p&gt;
So what is the secret trick to designing a service like this? Simple: it's called
"contract-first design". Back in the days of COM, you might have known it as "interface-first".
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h3&gt;Contract-First Service Design
&lt;/h3&gt;
&lt;p&gt;
The concept is surprisingly simple. A "service", whether it be a Web Service, system
Service, or logical in-process service, can be defined as a unit of system functionality
that operates independently of other units, and provides a well-known and concise
interface. What this means is that no matter how complex a peice of functionality
may be, it can be described in terms of some abstract interface. In Service nomenclature,
this interface is called the "&lt;em&gt;contract&lt;/em&gt;". The "contract" states the individual
methods (operations) that a given service implements.
&lt;/p&gt;
&lt;p&gt;
When we talk about Web Services, the "contract" is expressed as a WSDL document. When
we talk about Remoting, this contract is expressed as compiled IL in a shared assembly.
In COM, the contract was expressed in the Type Library. Indigo's name for this idea
is by far the most explicit and clear, the "ServiceContract".
&lt;/p&gt;
&lt;p&gt;
When you define a contract, you are declaring the exact functionality that a service
MUST provide, and which a client MAY consume. The Service is not allowed (theoretically)
to provide funtionality that exceeds or falls short of that contract, and the Client
is not able to request any functionality that falls outside the scope of the contract.
Furthermore, the contract also defines the specifics of HOW the functionality is to
be addressed... for example, an operation requires a specific set of inputs, and will
not respond (or should not) to inputs which are invalid or incomplete.
&lt;/p&gt;
&lt;p&gt;
Therefore, a Service Contract ensures a consistent and predictable interaction between
client and service.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;So HOW do we go about designing a .NET solution in such a manner?&lt;/em&gt;
&lt;/p&gt;
&lt;h5&gt;Plan ahead.
&lt;/h5&gt;
&lt;p&gt;
It is far easier to produce an adaptable architecture if you plan ahead for the adaptability.
This means thinking about your interface before you think about the implementation.
&lt;/p&gt;
&lt;p&gt;
At a minimum, start with defining your interface(s). You will need to define a seperate
interface for each logical service. If you are a SOA purist, then this is where you
bust out with the XSD editor and define your messages, operations, and portTypes.
If you are not an SOA purist, then this is where you start laying out .NET interface
definitions (yes, the language constructs that are defined with the "interface" keyword).
Even if you are going the pure-SOA route, you will want to run the xsd.exe compiler
against your schema to create some .NET stubs.... then change those from "class" to
"interface" definitions. Either way, on the .NET side you want a set of interface
definitions for the services, and class definitions for the complex structures.
&lt;/p&gt;
&lt;p&gt;
And here you must make a choice. Do you want to (A) design a completely document-centric
service, or (B) an rpc-centric service? If you want document-centric services, then
you will want to create explicit types for every operation/method, one for the input
and one for the output... even if the content is not complex. If you want RPC-centric
services, then you can save a small amount of effort by only defining explicit types
for cases where you wish to return or accept complex structures.
&lt;/p&gt;
&lt;pre&gt;&amp;nbsp; &lt;strong&gt;Design Method A&lt;/strong&gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationAResponse = {complex type or simple type...}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationARequest = {complex type or simple type...}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationA = function(OperationARequest), returns OperationAResponse&lt;/pre&gt;&lt;pre&gt;&amp;nbsp; &lt;strong&gt;Design
Method B&lt;/strong&gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationB = function(complex or simple type(s)), returns simple type or void&lt;/pre&gt;
&lt;p&gt;
One word of warning: stay away from "ref" or "out" parameters if you choose to follow
Design Method A.
&lt;/p&gt;
&lt;p&gt;
One thing you might notice about Design Method A is that all operations will have
a similar pattern, regardless of inputs and outputs. This is not coincidental. The
Request and Response structures are what we call "documents" in a document-centric
SOA (also called "&lt;em&gt;message-centric&lt;/em&gt;"). There is great flexibility and power
in a message-centric design.
&lt;/p&gt;
&lt;h5&gt;Define Seperate Endpoints and Implementations
&lt;/h5&gt;
&lt;p&gt;
This is what fouls up most attempts at designing a good service. Having the contract
pre-defined is not enough - you must also differentiate the service from the consumer.
In the real world, your service will almost always be centralized, but the consumer(s)
will be dispersed. This means that one (1) service may have multiple (N) endpoints.
An endpoint is merely an identifiable address where the implemented service functionality
can be found.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;The problem is that most people do not distinguish between the endpoint and the
implementation.&lt;/em&gt; They simple fire up a new asmx file and start dumping code into
it. This is a&amp;nbsp;&lt;strong&gt;BAD PRACTICE&lt;/strong&gt;. The asmx is simply and endpoint,
and should not be doing any work except passing the calls over to a real implementation.
In other words, the asmx should be nothing more than a &lt;a href="http://en.wikipedia.org/wiki/Facade_pattern"&gt;Facade&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
A better approach is to implement the service itself in an external class... better
yet, in an external assembly. This implementation class should implement the defined
interface, just as you would implement any other .NET interface in a class. Then,
you also implement that very same .NET interface in your asmx, however in the asmx
you simply forward the calls to an instance of the external implementation class.
Your Web Service methods become extremely simple shells that are marked up with the &lt;font face="Courier New"&gt;[WebMethod()]&lt;/font&gt; attribute
and delegate the work to the external class. Very clean and tidy.
&lt;/p&gt;
&lt;p&gt;
Once you have implemented your service like this, many more options become available.
You get the flexibility to create new endpoints, possibly with differing authorization
abilities (external facing ones might enforce WSE security, while internal ones might
not). You also get the ability to very easily expose the service via other transports...
such as Remoting. Either create a new endpoint object that derives from MarshalByRefObject,
or make the service implementation itself derive from MBRO. Then you can add a 
&lt;WELLKNOWN&gt;
entry to an application config file, and your service is now exposed via Remoting,
with an identical interface&amp;nbsp;to the web service! And finally, you enable the consumer
of your service to simply reference it directly as an assembly, if that is desired
for performance or security.
&lt;/p&gt;
&lt;h5&gt;Wrap-up
&lt;/h5&gt;
&lt;p&gt;
That wraps it up for this (somewhat basic)&amp;nbsp;discussion of how to design good services.
My next post will follow up with a concrete example of this process.&lt;br&gt;
&lt;br&gt;
In conclusion, I would also like to point out a few excellent resource books that
are relevant to the subject:
&lt;/p&gt;
&lt;p&gt;
"&lt;em&gt;Advanced .NET Remoting&lt;/em&gt;", &lt;strong&gt;Ingo Rammer&lt;/strong&gt;
&lt;br&gt;
"&lt;em&gt;Expert Service-Oriented Architecture in C#&lt;/em&gt;", &lt;strong&gt;Jeffrey Hasan&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=37cfaa85-f691-461a-8b28-7f0586ca5b0d" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,37cfaa85-f691-461a-8b28-7f0586ca5b0d.aspx</comments>
      <category>.NET</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=3783e665-5639-4450-8742-9968cff1f838</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,3783e665-5639-4450-8742-9968cff1f838.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,3783e665-5639-4450-8742-9968cff1f838.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=3783e665-5639-4450-8742-9968cff1f838</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://weblogs.asp.net/josh.robinson/">Josh</a> pointed out this cool little
Blackberry utility to me today: <a href="http://www.thebogles.com/Berry411.htm">Berry
411</a>. It's always the simple, elegant tools that are the best.
</p>
        <p>
 
</p>
        <p>
Well yeah, OK. So I admit I am finally getting the hang of the Blackberry
interface. I always said I would never get one because they were so awkward. But I
guess walking was also pretty awkward too at first.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=3783e665-5639-4450-8742-9968cff1f838" />
      </body>
      <title>Cool Blackberry Download</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,3783e665-5639-4450-8742-9968cff1f838.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/07/30/CoolBlackberryDownload.aspx</link>
      <pubDate>Sat, 30 Jul 2005 02:40:08 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://weblogs.asp.net/josh.robinson/"&gt;Josh&lt;/a&gt; pointed out this cool little
Blackberry utility to me today: &lt;a href="http://www.thebogles.com/Berry411.htm"&gt;Berry
411&lt;/a&gt;. It's always the simple, elegant tools that are the best.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Well&amp;nbsp;yeah, OK. So I admit I&amp;nbsp;am finally getting the hang of the Blackberry
interface. I always said I would never get one because they were so awkward. But&amp;nbsp;I
guess walking was also pretty awkward too at first.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=3783e665-5639-4450-8742-9968cff1f838" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,3783e665-5639-4450-8742-9968cff1f838.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=c15e1c42-68a3-4c17-ba7f-630436f8baa7</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,c15e1c42-68a3-4c17-ba7f-630436f8baa7.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,c15e1c42-68a3-4c17-ba7f-630436f8baa7.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=c15e1c42-68a3-4c17-ba7f-630436f8baa7</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Picture this:
</p>
        <p>
          <strong>Scenario 1</strong> - You are a consultant. You write software for various
clients, often remotely. Your clients pay you a lot of money, and you keep them very
happy with the exceptional work you perform for them. Because you are a meticulous
developer, and understand the value of versioning, you have been using Visual Sourcesafe
for 6 years to store every code revision you have ever made for your clients. You
also keep every one of your important emails for the last 10 years. Your Outlook .pst
file contains every significant conversation you have ever had with your clients -
and it also contains personal knowledge such as your complete contacts list and website
registration confirmations for dozens of sites, including your 401K portfolio on Ameritrade.
</p>
        <p>
          <strong>Scenario 2</strong> - You know nothing about code. You drive trucks for a
living. However, you DO like to have gadgets and gizmos, and you really love your
new Media Center Edition machine. In fact - it's so great that you have digitized
ALL of your CD collection and even bought a portable media center for while out on
the road. At this point you have over 5 gigs of music digitized, as well as the last
season of stargate and family guy to watch as you have time. You never use your CDs
anymore, and honestly have no clue where many of them are - since many have been "loaned"
or misplaced.
</p>
        <p>
Both of these fictional situations is missing something extremely important. Even
though your digitized data is extremely valuable to you, and difficult if not impossible
to recreate, you have no backup and recovery strategy!
</p>
        <p>
How to correct this oversight?
</p>
        <p>
There are several options. You could always purchase a simple external drive or tape
system and perform regular backups. This is fairly easy, but is really only slightly
better than having no backup at all... your backups are still in the same location
as the protected systems. A house fire (not as uncommon as you might think) would
wipe you out. If you are a consultant supporting a client with deep pockets (who would
be forced to sue for negligence if you lost their source code), you cannot afford
such a risk.
</p>
        <p>
A better solution is off-site backup services. With off-site services, your valuable
data is stored in a remote facility (usually encrypted). For a monthly fee, you can
configure your systems to regulary upload changes. Fees tend to be quite small - especially
for the individual consumer who often only needs a few Gig of storage. Setup and maintenance
also tend to be fairly simple - about on par with traditional tape or disk based backup
systems.
</p>
        <p>
I have recently been evaluating two vendors in this space: <a href="http://www.myncs.com/">NetCentric
Solutions</a> and <a href="http://www.storageguardian.com/index2.htm">Storage Guardian</a>.
NetCentric's offering is very easy to install and configure, but has fewer features
and a slightly higher price tag. Storage Guardian's offering on the other hand is
more difficult to install and configure (due to being more complex) but is much more
flexible in deployment.
</p>
        <p>
NetCentric supports File-system backups only, and is quite simple to get running.
They also have a nice feature that allows you to access your backup sets from any
internet location, essentially using your backup set as a file-sharing mechanism.
The NetCentric product costs about $40 a month for up to 5G of compressed data.
</p>
        <p>
Storage Guardian is a more "network aware" product. Rather than a simple single-install
program like NetCentric, this product follows a client/server design, with a server
process that performs the actual backups (oddly called "ds-client") and a client program
that performs set management and inspection (called "ds-user"). This product has the
ability to perform direct backups of SQL Server and Exchange databases, as well
as NT/2K/XP/2K3 System State, permissions and registries. The installation
is slightly complicated, and it is recommended that the installation guide actually
be read carefully prior to attempted install. The Storage Guardian product costs about
$30 a month for up to 10G of compressed data.
</p>
        <p>
I ended up going with the Storage Guardian product for my personal needs. I really
liked the ability to directly back up my Exchange and SQL databases. If you don't
need those two things however, the NetCentric solution may be a better fit - since
it's considerably easier to configure. My current volume needs are about 5G, so the
Storage Guardian solution also allows me a little more room to grow.
</p>
        <p>
In the end, $30 a month for peace of mind is a great bargain.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=c15e1c42-68a3-4c17-ba7f-630436f8baa7" />
      </body>
      <title>Protecting Assets</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,c15e1c42-68a3-4c17-ba7f-630436f8baa7.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/05/06/ProtectingAssets.aspx</link>
      <pubDate>Fri, 06 May 2005 17:37:38 GMT</pubDate>
      <description>&lt;p&gt;
Picture this:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Scenario 1&lt;/strong&gt; - You are a consultant. You write software for various
clients, often remotely. Your clients pay you a lot of money, and you keep them very
happy with the exceptional work you perform for them. Because you are a meticulous
developer, and understand the value of versioning, you have been using Visual Sourcesafe
for 6 years to store every code revision you have ever made for your clients. You
also keep every one of your important emails for the last 10 years. Your Outlook .pst
file contains every significant conversation you have ever had with your clients -
and it also contains personal knowledge such as your complete contacts list and website
registration confirmations for dozens of sites, including your 401K portfolio on Ameritrade.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Scenario 2&lt;/strong&gt; - You know nothing about code. You drive trucks for a
living. However, you DO like to have gadgets and gizmos, and you really love your
new Media Center Edition machine. In fact - it's so great that you have digitized
ALL of your CD collection and even bought a portable media center for while out on
the road. At this point you have over 5 gigs of music digitized, as well as the last
season of stargate and family guy to watch as you have time. You never use your CDs
anymore, and honestly have no clue where many of them are - since many have been "loaned"
or misplaced.
&lt;/p&gt;
&lt;p&gt;
Both of these fictional situations is missing something extremely important. Even
though your digitized data is extremely valuable to you, and difficult if not impossible
to recreate, you have no backup and recovery strategy!
&lt;/p&gt;
&lt;p&gt;
How to correct this oversight?
&lt;/p&gt;
&lt;p&gt;
There are several options. You could always purchase a simple external drive or tape
system and perform regular backups. This is fairly easy, but is really only slightly
better than having no backup at all... your backups are still in the same location
as the protected systems. A house fire (not as uncommon as you might think) would
wipe you out. If you are a consultant supporting a client with deep pockets (who would
be forced to sue for negligence if you lost their source code), you cannot afford
such a risk.
&lt;/p&gt;
&lt;p&gt;
A better solution is off-site backup services. With off-site services, your valuable
data is stored in a remote facility (usually encrypted). For a monthly fee, you can
configure your systems to regulary upload changes. Fees tend to be quite small - especially
for the individual consumer who often only needs a few Gig of storage. Setup and maintenance
also tend to be fairly simple - about on par with traditional tape or disk based backup
systems.
&lt;/p&gt;
&lt;p&gt;
I have recently been evaluating two vendors in this space: &lt;a href="http://www.myncs.com/"&gt;NetCentric
Solutions&lt;/a&gt; and &lt;a href="http://www.storageguardian.com/index2.htm"&gt;Storage Guardian&lt;/a&gt;.
NetCentric's offering is very easy to install and configure, but has fewer features
and a slightly higher price tag. Storage Guardian's offering on the other hand is
more difficult to install and configure (due to being more complex) but is much more
flexible in deployment.
&lt;/p&gt;
&lt;p&gt;
NetCentric supports File-system backups only, and is quite simple to get running.
They also have a nice feature that allows you to access your backup sets from any
internet location, essentially using your backup set as a file-sharing mechanism.
The NetCentric product costs about $40 a month for up to 5G of compressed data.
&lt;/p&gt;
&lt;p&gt;
Storage Guardian is a more "network aware" product. Rather than a simple single-install
program like NetCentric, this product follows a client/server design, with a server
process that performs the actual backups (oddly called "ds-client") and a client program
that performs set management and inspection (called "ds-user"). This product has the
ability to perform&amp;nbsp;direct backups of SQL Server and Exchange databases, as well
as&amp;nbsp;NT/2K/XP/2K3 System State, permissions&amp;nbsp;and registries.&amp;nbsp;The installation
is slightly complicated, and it is recommended that the installation guide actually
be read carefully prior to attempted install. The Storage Guardian product costs about
$30 a month for up to 10G of compressed data.
&lt;/p&gt;
&lt;p&gt;
I ended up going with the Storage Guardian product for my personal needs. I really
liked the ability to directly back up my Exchange and SQL databases. If you don't
need those two things however, the NetCentric solution may be a better fit - since
it's considerably easier to configure. My current volume needs are about 5G, so the
Storage Guardian solution also allows me a little more room to grow.
&lt;/p&gt;
&lt;p&gt;
In the end, $30 a month for peace of mind is a great bargain.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=c15e1c42-68a3-4c17-ba7f-630436f8baa7" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,c15e1c42-68a3-4c17-ba7f-630436f8baa7.aspx</comments>
      <category>General</category>
      <category>Media</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=c749f22f-c1c3-4d1f-88f4-34258de96b70</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,c749f22f-c1c3-4d1f-88f4-34258de96b70.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,c749f22f-c1c3-4d1f-88f4-34258de96b70.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=c749f22f-c1c3-4d1f-88f4-34258de96b70</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
First of all, thank you to everyone who came out tonight to the C# User Group meeting
in Atlanta. Paul and I are very pleased with how this group continues to grow.
</p>
        <p>
I am posting the slides and source code from my presentation <em>".NET Async Programming
Demystified"</em><a href="http://www.mindfusioncorp.com/weblog/content/binary/AsyncProgramming.zip">here
for download</a>.
</p>
        <p>
This is essentially the same presentation I intent to deliver to the .NET Code Camp
next month, although I will need to strip out about a quarter of the slides to keep
myself within the alloted time budgets there. I chose to present it to the C# group
first, since a large number of our attendees were not able to register for the Code
Camp (due to it selling out in only 5 days).
</p>
        <p>
I did make two corrections to my material before posting the slides:
</p>
        <ol>
          <li>
I incorrectly stated that each AppDomain has it's own thread pool. This should have
been "each <em>Process</em> has it's own thread pool".</li>
          <li>
I forgot to include the third type of Timer object - the System.Timers.Timer. Chalk
that one up to lack of sleep, I simply forgot to include it in my outline.</li>
        </ol>
        <p>
Both of these corrections are reflected in the downloadable files.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=c749f22f-c1c3-4d1f-88f4-34258de96b70" />
      </body>
      <title>Async Programming Presentation Slides and Source Code</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,c749f22f-c1c3-4d1f-88f4-34258de96b70.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/04/05/AsyncProgrammingPresentationSlidesAndSourceCode.aspx</link>
      <pubDate>Tue, 05 Apr 2005 03:29:17 GMT</pubDate>
      <description>&lt;p&gt;
First of all, thank you to everyone who came out tonight to the C# User Group meeting
in Atlanta. Paul and I are very pleased with how this group continues to grow.
&lt;/p&gt;
&lt;p&gt;
I am posting the slides and source code from my presentation &lt;em&gt;".NET Async Programming
Demystified"&lt;/em&gt; &lt;a href="http://www.mindfusioncorp.com/weblog/content/binary/AsyncProgramming.zip"&gt;here
for download&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
This is essentially the same presentation I intent to deliver to the .NET Code Camp
next month, although I will need to strip out about a quarter of the slides to keep
myself within the alloted time budgets there. I chose to present it to the C# group
first, since a large number of our attendees were not able to register for the Code
Camp (due to it selling out in only 5 days).
&lt;/p&gt;
&lt;p&gt;
I did make two corrections to my material before posting the slides:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
I incorrectly stated that each AppDomain has it's own thread pool. This should have
been "each &lt;em&gt;Process&lt;/em&gt; has it's own thread pool".&lt;/li&gt;
&lt;li&gt;
I forgot to include the third type of Timer object - the System.Timers.Timer. Chalk
that one up to lack of sleep, I simply forgot to include it in my outline.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Both of these corrections are reflected in the downloadable files.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=c749f22f-c1c3-4d1f-88f4-34258de96b70" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,c749f22f-c1c3-4d1f-88f4-34258de96b70.aspx</comments>
      <category>Events</category>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=bf8c9cd5-5ebd-4710-95be-4d5be61168cc</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,bf8c9cd5-5ebd-4710-95be-4d5be61168cc.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,bf8c9cd5-5ebd-4710-95be-4d5be61168cc.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=bf8c9cd5-5ebd-4710-95be-4d5be61168cc</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I have used CSS for years now, but I never knew about this. Sure, it's sort of implied
by the documentation, but I have never seen anyone come out and say "hey, this is
how you organize it". So here is what I learned this weekend.
</p>
        <p>
1. You can define specific hierarchies of nested tags to apply a style to. For example
"DIV.outerdiv DIV.innerdiv {color:red;}" will set the font color of a div with a class
attribute of "innerdiv" to red, but only if it is contained within another div with
a class of "outerdiv". Thats super handy for complex layouts.
</p>
        <p>
2. You can define a style more than once. The styles are then merged at runtime in
the order which they are encountered (last writer of a style property wins). This
means that you can seperate <em>layout</em> CSS from <em>colors</em> CSS and from
text, or whatever. You can have a "colors.css" file that only contains color definitions,
making it MUCH easier to update later. Super SUPER handy!
</p>
        <p>
3. You can assign styles based on element IDs, not just Classes. Everyone using CSS
knows you can use a style selector of ".somestyle" to apply a style to all elements
with a class= "somestyle"... but most don't know that you can use a selector of "#element_id"
to apply the style only to the element with id= "element_id". This is SUPERB for layout
style properties. Generally, the colors/text/etc styles are used on many elements
in a page, which is easily done using class="somestyle". But id values are <em>supposed</em> to
be unique in a page, and they are all at different positions, with different layout
rules (even though they share the same color/font/etc). Assigning layout style properties
based on element id and other properties based on class allows you to have your cake
and eat it too!
</p>
        <p>
These are very simple concepts to pick up, but they have done wonders for my web design/layout
abilities.
</p>
        <p>
And I guess I should also give the disclaimer that I didn't know these things until
I customized my <a href="http://www.dasblog.net/">dasBlog</a> theme, and saw how it's
CSS was designed. Very impressive work there.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=bf8c9cd5-5ebd-4710-95be-4d5be61168cc" />
      </body>
      <title>Getting a better handle on CSS</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,bf8c9cd5-5ebd-4710-95be-4d5be61168cc.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/03/31/GettingABetterHandleOnCSS.aspx</link>
      <pubDate>Thu, 31 Mar 2005 04:32:25 GMT</pubDate>
      <description>&lt;p&gt;
I have used CSS for years now, but I never knew about this. Sure, it's sort of implied
by the documentation, but I have never seen anyone come out and say "hey, this is
how you organize it". So here is what I learned this weekend.
&lt;/p&gt;
&lt;p&gt;
1. You can define specific hierarchies of nested tags to apply a style to. For example
"DIV.outerdiv DIV.innerdiv {color:red;}" will set the font color of a div with a class
attribute of "innerdiv" to red, but only if it is contained within another div with
a class of "outerdiv". Thats super handy for complex layouts.
&lt;/p&gt;
&lt;p&gt;
2. You can define a style more than once. The styles are then merged at runtime in
the order which they are encountered (last writer of a style property wins). This
means that you can seperate &lt;em&gt;layout&lt;/em&gt; CSS from &lt;em&gt;colors&lt;/em&gt; CSS and from
text, or whatever. You can have a "colors.css" file that only contains color definitions,
making it MUCH easier to update later. Super SUPER handy!
&lt;/p&gt;
&lt;p&gt;
3. You can assign styles based on element IDs, not just Classes. Everyone using CSS
knows you can use a style selector of ".somestyle" to apply a style to all elements
with a class= "somestyle"... but most don't know that you can use a selector of "#element_id"
to apply the style only to the element with id= "element_id". This is SUPERB for layout
style properties. Generally, the colors/text/etc styles are used on many elements
in a page, which is easily done using class="somestyle". But id values are &lt;em&gt;supposed&lt;/em&gt; to
be unique in a page, and they are all at different positions, with different layout
rules (even though they share the same color/font/etc). Assigning layout style properties
based on element id and other properties based on class allows you to have your cake
and eat it too!
&lt;/p&gt;
&lt;p&gt;
These are very simple concepts to pick up, but they have done wonders for my web design/layout
abilities.
&lt;/p&gt;
&lt;p&gt;
And I guess I should also give the disclaimer that I didn't know these things until
I customized my &lt;a href="http://www.dasblog.net/"&gt;dasBlog&lt;/a&gt; theme, and saw how it's
CSS was designed. Very impressive work there.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=bf8c9cd5-5ebd-4710-95be-4d5be61168cc" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,bf8c9cd5-5ebd-4710-95be-4d5be61168cc.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=43c53b03-8131-4ae8-a157-70b86e4ba9ed</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,43c53b03-8131-4ae8-a157-70b86e4ba9ed.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,43c53b03-8131-4ae8-a157-70b86e4ba9ed.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=43c53b03-8131-4ae8-a157-70b86e4ba9ed</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.cerkit.com/cerkitBlog/">Michael Earls</a> is <a href="http://www.pimpz.org/">the
man</a>.
</p>
        <p>
This afternoon I asked him a simple question: How do I get Master Pages type functionality
without upgrading to Fx2.0 beta?
</p>
        <p>
I am building a small administration application for a client, and I am tired of using "copy
&amp; paste templates" or "UserControl chunks" to build a reusable/consistent site
design. I know he has done this type of thing a few times in the past, which is why
I asked him.
</p>
        <p>
He gave me some very concise and (most importantly) correct insights into the ASP.NET
rendering engine, and where to place hooks to do what I wanted. He gave me just enough
information to get it working, without giving me too much. The essentials: override
the AddParsedSubobjects() method in a server control to re-parent the child page's
contents to a placeholder.
</p>
        <p>
While there are a few tricks and snags to overcome, that is essentially exactly what
I had to do. I created a new server control, changed it to inherit from Web.UI.Page,
instantiated LiteralControls for my static content, as well as a number of server
controls that I needed in my base class (for example, the Coalesys PanelBar for navigation) in
the new class's constructor. I did some footwork in the AddParsedSubobjects() method
to relocate the child page's Form contents into a new HtmlForm that I maintain within
my new class. I also had to copy the properties of the child form (enctype, name,
method, etc)... so that should the child page developer decide to change any of it,
their changes would carry over.
</p>
        <p>
I did do a few things my own way. One of the ideas Michael gave me was to use regular
expressions to construct the master page's LiteralControls (he used string constants
for each Literal, which I am sure was probably a bit tedious when a change needed
to be made). So instead of that approach, I added some well-known comment tags to
my master page's source to demarcate the literal sections. I then used my <a href="http://www.mindfusioncorp.com/weblog/PermaLink,guid,1ccd1d4f-2152-4429-91e8-e9eccfa2a9de.aspx">NVEdit
tool</a> to store the entire master page as a single template resource. A simple regular
expression was used to extract out all the literal sections (this was not hard at
all since I used well-known comments to mark the sections). As a result, I can modify
the master page layout without too much trouble (yes, it still requires a recompile).
Perhaps a future exercise could be to make it fully dynamic, with the ability to use
multiple master layouts on the fly. Hmm.
</p>
        <p>
Anyways, the other features I added was a simple way to link external CSS (a new AddStylesheetReference(string
url) method), as well as the obligatory Title property that alters the header tag
appropriately. A side bonus is that the AddParsedSubobjects code is smart enough to
read in existing Title and linked stylesheets from the child pages, and automatically
set them with no developer code required. I will likely also extend this mechanism
to support themes via CSS at a later time too. That would work nicely along with dynamic
master page sourcing...
</p>
        <p>
So I am now very happy. I effectively have master pages development in VS 2003.
I don't have the ability to see the master while editing a child page in the designer,
but I don't really care about that little bit. I can still link my child page to the
site's CSS and get the right "look and feel". This is great.
</p>
        <p>
Thanks again Michael!
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=43c53b03-8131-4ae8-a157-70b86e4ba9ed" />
      </body>
      <title>Thanks Michael!</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,43c53b03-8131-4ae8-a157-70b86e4ba9ed.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/03/28/ThanksMichael.aspx</link>
      <pubDate>Mon, 28 Mar 2005 03:56:16 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://www.cerkit.com/cerkitBlog/"&gt;Michael Earls&lt;/a&gt; is &lt;a href="http://www.pimpz.org/"&gt;the
man&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
This afternoon I asked him a simple question: How do I get Master Pages type functionality
without upgrading to Fx2.0 beta?
&lt;/p&gt;
&lt;p&gt;
I am building a small administration application for a client, and I am tired of using&amp;nbsp;"copy
&amp;amp; paste templates" or "UserControl chunks" to build a reusable/consistent site
design. I know he has done this type of thing a few times in the past, which is why
I asked him.
&lt;/p&gt;
&lt;p&gt;
He gave me some very concise and (most importantly) correct insights into the ASP.NET
rendering engine, and where to place hooks to do what I wanted. He gave me just enough
information to get it working, without giving me too much. The essentials:&amp;nbsp;override
the AddParsedSubobjects() method in a server control to re-parent the child page's
contents to a placeholder.
&lt;/p&gt;
&lt;p&gt;
While there are a few tricks and snags to overcome, that is essentially exactly what
I had to do. I created a new server control, changed it to inherit from Web.UI.Page,
instantiated LiteralControls for my static content, as well as a number of server
controls that I needed in my base class (for example, the Coalesys PanelBar for navigation)&amp;nbsp;in
the new class's constructor. I did some footwork in the AddParsedSubobjects() method
to relocate the child page's Form contents into a new HtmlForm that I maintain within
my new class. I also had to copy the properties of the child form (enctype, name,
method, etc)... so that should the child page developer decide to change any of it,
their changes would carry over.
&lt;/p&gt;
&lt;p&gt;
I did do a few things my own way. One of the ideas Michael gave me was to use regular
expressions to construct the master page's LiteralControls (he used string constants
for each Literal, which I am sure was probably a bit tedious when a change needed
to be made). So instead of that approach, I added some well-known comment tags to
my master page's source to demarcate the literal sections. I then used my &lt;a href="http://www.mindfusioncorp.com/weblog/PermaLink,guid,1ccd1d4f-2152-4429-91e8-e9eccfa2a9de.aspx"&gt;NVEdit
tool&lt;/a&gt; to store the entire master page as a single template resource. A simple regular
expression was used to extract out all the literal sections (this was not hard at
all since I used well-known comments to mark the sections). As a result, I can modify
the master page layout without too much trouble (yes, it still requires a recompile).
Perhaps a future exercise could be to make it fully dynamic, with the ability to use
multiple master layouts on the fly. Hmm.
&lt;/p&gt;
&lt;p&gt;
Anyways, the other features I added was a simple way to link external CSS (a new AddStylesheetReference(string
url) method), as well as the obligatory Title property that alters the header tag
appropriately. A side bonus is that the AddParsedSubobjects code is smart enough to
read in existing Title and linked stylesheets from the child pages, and automatically
set them with no developer code required. I will likely also extend this mechanism
to support themes via CSS at a later time too. That would work nicely along with dynamic
master page sourcing...
&lt;/p&gt;
&lt;p&gt;
So I am now very happy. I effectively&amp;nbsp;have master pages development in VS 2003.
I don't have the ability to see the master while editing a child page in the designer,
but I don't really care about that little bit. I can still link my child page to the
site's CSS and get the right "look and feel". This is great.
&lt;/p&gt;
&lt;p&gt;
Thanks again Michael!
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=43c53b03-8131-4ae8-a157-70b86e4ba9ed" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,43c53b03-8131-4ae8-a157-70b86e4ba9ed.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=4348e0c3-923c-4fa6-9902-dee3a7135b62</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,4348e0c3-923c-4fa6-9902-dee3a7135b62.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,4348e0c3-923c-4fa6-9902-dee3a7135b62.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=4348e0c3-923c-4fa6-9902-dee3a7135b62</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Part of my new job is making sure our applications meet scalability, reliability,
and performance requirements once we deploy to "the wild". Damn near anything
will work in a development or even QA environment (assuming you are like 95% of all
shops and don't bother doing load analysis until a problem comes up). But just because
something works on a development machine is no guarantee it will continue to work
once it is placed under pressure. "But it works on my machine" has ended many a developer's
career and/or project's budget.
</p>
        <p>
Anyways, I am rambling, so on to the point of this post...
</p>
        <p>
I am truly appalled at this "webservice.htc" IE behavior component. True enough,
I can visualize the thought process at Microsoft that eventually arrived at creating
this thing. But I do not agree with it at all.
</p>
        <p>
          <strong>
            <font size="3">First, what it does:</font>
          </strong>
        </p>
        <p>
If you are unfamiliar with webservice.htc, essentially it is a chunk of javascript
code that wraps calls to web services (via the XmlHttp IE COM component). It knows
all about SOAP and WSDL. In fact, in order to use a SOAP web service, you simply point
it to a WSDL document (it expects something along the lines of "BlahBlah.asmx?WSDL",
in other words - always late-bound service discovery). It then allows you to interact
with the web service using the SOAP operations ("methods"), not too unlike the "developer
experience" of using a web service proxy class in managed .NET code.
</p>
        <p>
It is very easy to use in fact.
</p>
        <p>
All you need to do is attach the behavior to any DHTML tag... for example a DIV like
this:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <strong>&lt;div id="<font color="#0000ff">MyService</font>"
style="<font color="#0000ff">display:none;behavior:url(webservice.htc);</font>" /&gt;</strong>
          </pre>
        </blockquote>
        <p>
Then in your page somewhere (anywhere, but most often done in the onLoad event of
the body tag), you load the WSDL:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <strong>&lt;body onload="<font color="#0000ff">MyService.useService('BlahBlah.asmx?WSDL',
'svcBlahBlah');</font>"&gt;....&lt;/body&gt;</strong>
          </pre>
        </blockquote>
        <p>
Then calling the operations ("methods" for OO-heads) is as simple as this code which
can be used anywheres in your page javascript:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <strong>&lt;script
language=<font color="#0000ff">javascript</font>&gt;</strong>
              <br />
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">var</span> param <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> "some
parameter...";<br />
MyService.svcBlahBlah.callService(DisplayResult, "SomeOperationOnBlahBlah", param);<br /><font color="#0000ff">function</font> DisplayResult(result)<br />
{<br />
   alert("Result: " <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">+</span> result.value);<br />
}<br /><strong>&lt;/script&gt;</strong><br /></span>
          </p>
        </blockquote>
        <p>
Now that I have explained how it works in a nutshell, let me explain why I think its
a really bad idea...
</p>
        <p>
          <strong>
            <font size="3">Second, my beef with it:</font>
          </strong>
        </p>
        <p>
Each time useService() is called, the WSDL is downloaded to the browser. Chances are,
a complete WSDL is massive overkill for the data a web application is wanting to pull
via OOB (out of band). In the web service I am looking at right now, there are four
operations supported. Each returns a simple string, and accepts one to three string
parameters. However, the WSDL is over 8k! Since each page transition in the browser
tosses all previously loaded script, this "wsdl setup" must happen at least once every
time a page is loaded that needs to make web service calls.
</p>
        <p>
On top of the WSDL cost, there is the cost of the HTC code itself. The webservice.htc
file is 50K by itself! And since it is just linked javascript, it too must be reloaded
every time a page transition or postback occurs.
</p>
        <p>
So far, those costs are fairly hidden from view of the web developer. Not many will
think adding the behavior style and calling a single method just once on a page will
incur from 50k upwards to 100k or more bandwidth (the size of that WSDL can grow quite
quickly as your web service becomes more complex). For reference, a page that is 100k <em>*in
total size*</em> is considered effectively unusable in low-bandwidth settings, such
as 56k dial-up or dedicated circuits. Not to mention if you ever hope to handle more
than say three users or so....
</p>
        <p>
On top of those hidden costs is the actual cost of the SOAP payload itself. Most developers
are at least aware of this aspect, since there has been a great deal of discussion/ranting
over the years about SOAP message bloat. In my test case here, this actually
turned out to be the lesser cost when compared to the setup overhead. Each SOAP conversation
is costing me roughly 2k for the request and 1k for the response, which honestly is
not too bad. It's worth mentioning though that these tiny costs are exacerbated by
the latency costs of the connections themselves, and if your design is inherently
"chatty", these costs will add up very quickly.
</p>
        <p>
          <strong>
            <font size="3">Real Numbers:</font>
          </strong>
        </p>
        <p>
So you might be rolling your eyes, thinking "so what. this guy is griping about a
few extra bytes, he has too much spare time to dig this crap up". I would be skeptical
as well. So I did some real analysis of this application using the simple ACT tool
that comes with Visual Studio. This examined application uses Infragistics controls
heavily, and I was expecting them them to be the worst offender, but measurements
proved otherwise:
</p>
        <p>
In ten minutes, my test ran 431 iterations of a simple "browsing" script, which logs
in, does a few searches, and pokes around most of the application pages without
modifying any data. In each test iteration, a total of 105 unique URLs were requested,
though obviously many were hit multiple times. Between the pages themselves, images,
and linked css and javascript files, a total of 82,224 requests were issued. 5,000
of those ended as "socket error", which indicates that I was hitting right up against
the limits of my testing machine (Win XP) which was starting to have trouble handling
the requests and thus dropped a few. 4,294 requests resulted in a 403 http error,
which indicates also that the server was becoming saturated.
</p>
        <p>
While only 441 calls were made to the web service in actual method calls (essentially
once per iteration), 5,485 calls were made to retrieve the WSDL! In fact, this works
out to roughly 12 times per iteration. No other resource was requested so often from
the server... the next highest were about three aspx pages each requested roughly
3,500 times (they are reused in IFrames a lot, so this is somewhat understandable).
The webservice.htc was also requested a total of 859 times, or roughly twice per iteration.
So essentially, 8% of the total # requests, and 10% of the bandwidth of this application
(even factoring in image files) was being expended simply to read a few strings of
data without forcing a server postback.
</p>
        <p>
In comparison, the notoriously bandwidth-heavy Infragistics grid, datetimepicker,
and outlookbar controls had a combined impact significantly lower than the web service
calls.
</p>
        <p>
          <strong>
            <font size="3">So, how to fix this?</font>
          </strong>
        </p>
        <p>
The best approach is to just not do this. Chances are, an application that relies
on OOB tricks probably should have been a Windows Forms application to begin with.
But assuming you are 99% through the development (nobody ever thinks about load tests
until then...), I assume a rewrite is out of the question. So, the question is "<em>how
to minimize the problem?</em>".
</p>
        <p>
There are three approaches I can think of to remedy this situation without resorting
to drastic re-architecture.
</p>
        <ol>
          <li>
Roll-Your-Own. It is rather painless in my opinion to simply define your own (or go
with "standard" XML-RPC) out of band mechanism. XmlHttp is quite easy to use, and
writing the XML DOM code to construct requests and extract results/errors is not at
all difficult. On the server end, its also not very hard to produce XML to match your
needs manually, and simply write it out to the response. Using an HttpHandler would
make it pretty lightweight too. This approach eliminates the huge webservice.htc downloads,
and also eliminates the WSDL calls, since well... there wouldn't be any WSDL. Of course,
the result is 100% proprietary, which may be considered a drawback.</li>
          <li>
Use SOAP without WSDL. An extension to approach #1, you would interact with XmlHttp
directly using your own javascript. However, you continue to use an ASMX web service
on the server. As long as the parameters are simple datatypes, you can use the HTTP
GET method and pass the parameters in the query string. Then, its just a matter of
dealing with the (relatively clean) SOAP response. No WSDL to contend with in this
approach, and no webservice.htc. You also get to use the strong tools support server-side
for the ASMX web service. The downside is that you have to keep to simple parameters,
and you have to code the response handling in javascript.</li>
          <li>
Relocate the behavior code to a parent frame. By making an outer-level frameset with
a single contained frame panel, you can link the behavior and associated WSDL calls
in that one place, and call it from within nested frames. This has the benefits of
retaining the SOAP conformance (allowing you to continue using ASMX), while reducing
the WSDL and HTC requests to once per browser session. The downside is that now you
have to pay more attention while coding. Calls to the webservice proxy have to be
made by traversing the frameset (iterating through parent frames).</li>
        </ol>
        <p>
These are all decent ways to place a band-aid on the problem. But the problem
itself is, to me, indicative of a much larger problem that I see widespread in the
industry today...
</p>
        <p>
          <strong>
            <font size="3">Misuse of SOA tools and components</font>
          </strong>
        </p>
        <p>
Web Services are a component of SOA (Service Oriented Architecture). WSDL and associated
discovery/description technologies are tools of SOA. More and more, I keep seeing
people attempt to use, or more accurately "misuse", these things. Web Services are
implemented as if there was zero cost in performance/latency/reliability. WSDL is
fetched at run-time to configure service proxies on the fly. This is NOT how these
technologies were intended to be used, and they perform and scale miserably when used
like that.
</p>
        <p>
The purpose of WSDL is to define service contracts. This is for the purpose of being
able to understand and properly interface with a service. You interpret the WSDL <em>ONCE
and ONLY ONCE</em> (preferably at design time!). Your code will obviously depend on
the semantics of the <em>contract</em> declared in the WSDL, and so it makes zero
sense to interrogate for WSDL at run-time! In fact, once you go to production, its
a pretty good idea to completely disable the WSDL handler in ASMX web services, if
nothing else than to lower your DoS vulnerability profile (after all, generating WSDL
in asmx isn't free).
</p>
        <p>
And the invocation of Web Service operations themselves is not intended for such scenarios
as OOB web browser activity. Web Services are a way of enabling applications to communicate
via messages, which is useful in Enterprise Architecture (ESB's) and Integration (EAI),
but of little value in a contained web browser application.
</p>
        <p>
Microsoft really should be more responsible and put a warning on this thing. The <a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/author/webservice/webservice.asp">documentation
on MSDN</a> reeks like a marketing brochure. It discusses all the wonderful benefits,
but makes no mention whatsoever about the potential problems. Nor does it even mention
the fact that accessing web services from a browser is a dubious idea from the outset.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=4348e0c3-923c-4fa6-9902-dee3a7135b62" />
      </body>
      <title>SOA Misunderstanding and Misuse</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,4348e0c3-923c-4fa6-9902-dee3a7135b62.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/03/06/SOAMisunderstandingAndMisuse.aspx</link>
      <pubDate>Sun, 06 Mar 2005 21:23:55 GMT</pubDate>
      <description>&lt;p&gt;
Part of my new job is making sure our applications meet scalability, reliability,
and performance requirements once we deploy to&amp;nbsp;"the wild". Damn near anything
will work in a development or even QA environment (assuming you are like 95% of all
shops and don't bother doing load analysis until a problem comes up). But just because
something works on a development machine is no guarantee it will continue to work
once it is placed under pressure. "But it works on my machine" has ended many a developer's
career and/or project's budget.
&lt;/p&gt;
&lt;p&gt;
Anyways, I am rambling, so on to the point of this post...
&lt;/p&gt;
&lt;p&gt;
I am truly appalled at this&amp;nbsp;"webservice.htc" IE behavior component. True enough,
I can visualize the thought process at Microsoft that eventually arrived at creating
this thing. But I do not agree with it at all.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size=3&gt;First, what it does:&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
If you are unfamiliar with webservice.htc, essentially it is a chunk of javascript
code that wraps calls to web services (via the XmlHttp IE COM component). It knows
all about SOAP and WSDL. In fact, in order to use a SOAP web service, you simply point
it to a WSDL document (it expects something along the lines of "BlahBlah.asmx?WSDL",
in other words - always late-bound service discovery). It then allows you to interact
with the web service using the SOAP operations ("methods"), not too unlike the "developer
experience" of using a web service proxy class in managed .NET code.
&lt;/p&gt;
&lt;p&gt;
It is very easy to use in fact.
&lt;/p&gt;
&lt;p&gt;
All you need to do is attach the behavior to any DHTML tag... for example a DIV like
this:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;strong&gt;&amp;lt;div id="&lt;font color=#0000ff&gt;MyService&lt;/font&gt;"
style="&lt;font color=#0000ff&gt;display:none;behavior:url(webservice.htc);&lt;/font&gt;" /&amp;gt;&lt;/strong&gt;&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Then in your page somewhere (anywhere, but most often done in the onLoad event of
the body tag), you load the WSDL:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;strong&gt;&amp;lt;body onload="&lt;font color=#0000ff&gt;MyService.useService('BlahBlah.asmx?WSDL',
'svcBlahBlah');&lt;/font&gt;"&amp;gt;....&amp;lt;/body&amp;gt;&lt;/strong&gt;&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Then calling the operations ("methods" for OO-heads) is as simple as this code which
can be used anywheres in your page javascript:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;strong&gt;&amp;lt;script
language=&lt;font color=#0000ff&gt;javascript&lt;/font&gt;&amp;gt;&lt;/strong&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;var&lt;/span&gt; param &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; "some
parameter...";&lt;br&gt;
MyService.svcBlahBlah.callService(DisplayResult, "SomeOperationOnBlahBlah", param);&lt;br&gt;
&lt;font color=#0000ff&gt;function&lt;/font&gt; DisplayResult(result)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;alert("Result: " &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;+&lt;/span&gt; result.value);&lt;br&gt;
}&lt;br&gt;
&lt;strong&gt;&amp;lt;/script&amp;gt;&lt;/strong&gt;
&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Now that I have explained how it works in a nutshell, let me explain why I think its
a really bad idea...
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size=3&gt;Second, my beef with it:&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Each time useService() is called, the WSDL is downloaded to the browser. Chances are,
a complete WSDL is massive overkill for the data a web application is wanting to pull
via OOB (out of band). In the web service I am looking at right now, there are four
operations supported. Each returns a simple string, and accepts one to three string
parameters. However, the WSDL is over 8k! Since each page transition in the browser
tosses all previously loaded script, this "wsdl setup" must happen at least once every
time a page is loaded that needs to make web service calls.
&lt;/p&gt;
&lt;p&gt;
On top of the WSDL cost, there is the cost of the HTC code itself. The webservice.htc
file is 50K by itself! And since it is just linked javascript, it too must be reloaded
every time a page transition or postback occurs.
&lt;/p&gt;
&lt;p&gt;
So far, those costs are fairly hidden from view of the web developer. Not many will
think adding the behavior style and calling a single method just once on a page will
incur from 50k upwards to 100k or more bandwidth (the size of that WSDL can grow quite
quickly as your web service becomes more complex). For reference, a page that is 100k &lt;em&gt;*in
total size*&lt;/em&gt; is considered effectively unusable in low-bandwidth settings, such
as 56k dial-up or dedicated circuits. Not to mention if you ever hope to handle more
than say three users or so....
&lt;/p&gt;
&lt;p&gt;
On top of those hidden costs is the actual cost of the SOAP payload itself. Most developers
are at least aware of this aspect, since there has been a great deal of discussion/ranting
over the years about SOAP&amp;nbsp;message bloat. In my test case here, this actually
turned out to be the lesser cost when compared to the setup overhead. Each SOAP conversation
is costing me roughly 2k for the request and 1k for the response, which honestly is
not too bad. It's worth mentioning though that these tiny costs are exacerbated by
the latency costs of the connections themselves, and if your design is inherently
"chatty", these costs will add up very quickly.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size=3&gt;Real Numbers:&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
So you might be rolling your eyes, thinking "so what. this guy is griping about a
few extra bytes, he has too much spare time to dig this crap up". I would be skeptical
as well. So I did some real analysis of this application using the simple ACT tool
that comes with Visual Studio. This examined application uses Infragistics controls
heavily, and I was expecting them them to be the worst offender, but measurements
proved otherwise:
&lt;/p&gt;
&lt;p&gt;
In ten minutes, my test ran 431 iterations of a simple "browsing" script, which logs
in, does a few searches, and pokes around most of the application pages&amp;nbsp;without
modifying any data. In each test iteration, a total of 105 unique URLs were requested,
though obviously many were hit multiple times. Between the pages themselves, images,
and linked css and javascript files, a total of 82,224 requests were issued. 5,000
of those ended as "socket error", which indicates that I was hitting right up against
the limits of my testing machine (Win XP) which was starting to have trouble handling
the requests and thus dropped a few. 4,294 requests resulted in a 403 http error,
which indicates also that the server was becoming saturated.
&lt;/p&gt;
&lt;p&gt;
While only 441 calls were made to the web service in actual method calls (essentially
once per iteration), 5,485 calls were made to retrieve the WSDL! In fact, this works
out to roughly 12 times per iteration. No other resource was requested so often from
the server... the next highest were about three aspx pages each requested roughly
3,500 times (they are reused in IFrames a lot, so this is somewhat understandable).
The webservice.htc was also requested a total of 859 times, or roughly twice per iteration.
So essentially, 8% of the total # requests, and 10% of the bandwidth of this application
(even factoring in image files) was being expended simply to read a few strings of
data without forcing a server postback.
&lt;/p&gt;
&lt;p&gt;
In comparison, the notoriously bandwidth-heavy Infragistics grid, datetimepicker,
and outlookbar controls had a combined impact significantly lower than the web service
calls.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size=3&gt;So, how to fix this?&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
The best approach is to just not do this. Chances are, an application that relies
on OOB tricks probably should have been a Windows Forms application to begin with.
But assuming you are 99% through the development (nobody ever thinks about load tests
until then...), I assume a rewrite is out of the question. So, the question is "&lt;em&gt;how
to minimize the problem?&lt;/em&gt;".
&lt;/p&gt;
&lt;p&gt;
There are three approaches I can think of to remedy this situation without resorting
to drastic re-architecture.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Roll-Your-Own. It is rather painless in my opinion to simply define your own (or go
with "standard" XML-RPC) out of band mechanism. XmlHttp is quite easy to use, and
writing the XML DOM code to construct requests and extract results/errors is not at
all difficult. On the server end, its also not very hard to produce XML to match your
needs manually, and simply write it out to the response. Using an HttpHandler would
make it pretty lightweight too. This approach eliminates the huge webservice.htc downloads,
and also eliminates the WSDL calls, since well... there wouldn't be any WSDL. Of course,
the result is 100% proprietary, which may be considered a drawback.&lt;/li&gt;
&lt;li&gt;
Use SOAP without WSDL. An extension to approach #1, you would interact with XmlHttp
directly using your own javascript. However, you continue to use an ASMX web service
on the server. As long as the parameters are simple datatypes, you can use the HTTP
GET method and pass the parameters in the query string. Then, its just a matter of
dealing with the (relatively clean) SOAP response. No WSDL to contend with in this
approach, and no webservice.htc. You also get to use the strong tools support server-side
for the ASMX web service. The downside is that you have to keep to simple parameters,
and you have to code the response handling in javascript.&lt;/li&gt;
&lt;li&gt;
Relocate the behavior code to a parent frame. By making an outer-level frameset with
a single contained frame panel, you can link the behavior and associated WSDL calls
in that one place, and call it from within nested frames. This has the benefits of
retaining the SOAP conformance (allowing you to continue using ASMX), while reducing
the WSDL and HTC requests to once per browser session. The downside is that now you
have to pay more attention while coding. Calls to the webservice proxy have to be
made by traversing the frameset (iterating through parent frames).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
These&amp;nbsp;are all&amp;nbsp;decent ways to place a band-aid on the problem. But the problem
itself is, to me, indicative of a much larger problem that I see widespread in the
industry today...
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size=3&gt;Misuse of SOA tools and components&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Web Services are a component of SOA (Service Oriented Architecture). WSDL and associated
discovery/description technologies are tools of SOA. More and more, I keep seeing
people attempt to use, or more accurately "misuse", these things. Web Services are
implemented as if there was zero cost in performance/latency/reliability. WSDL is
fetched at run-time to configure service proxies on the fly. This is NOT how these
technologies were intended to be used, and they perform and scale miserably when used
like that.
&lt;/p&gt;
&lt;p&gt;
The purpose of WSDL is to define service contracts. This is for the purpose of being
able to understand and properly interface with a service. You interpret the WSDL &lt;em&gt;ONCE
and ONLY ONCE&lt;/em&gt; (preferably at design time!). Your code will obviously depend on
the semantics of the &lt;em&gt;contract&lt;/em&gt; declared in the WSDL, and so it makes zero
sense to interrogate for WSDL at run-time! In fact, once you go to production, its
a pretty good idea to completely disable the WSDL handler in ASMX web services, if
nothing else than to lower your DoS vulnerability profile (after all, generating WSDL
in asmx isn't free).
&lt;/p&gt;
&lt;p&gt;
And the invocation of Web Service operations themselves is not intended for such scenarios
as OOB web browser activity. Web Services are a way of enabling applications to communicate
via messages, which is useful in Enterprise Architecture (ESB's) and Integration (EAI),
but of little value in a contained web browser application.
&lt;/p&gt;
&lt;p&gt;
Microsoft really should be more responsible and put a warning on this thing. The &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/author/webservice/webservice.asp"&gt;documentation
on MSDN&lt;/a&gt; reeks like a marketing brochure. It discusses all the wonderful benefits,
but makes no mention whatsoever about the potential problems. Nor does it even mention
the fact that accessing web services from a browser is a dubious idea from the outset.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=4348e0c3-923c-4fa6-9902-dee3a7135b62" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,4348e0c3-923c-4fa6-9902-dee3a7135b62.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=2e0f3720-20c3-4766-8917-5e1d3069b8eb</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,2e0f3720-20c3-4766-8917-5e1d3069b8eb.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,2e0f3720-20c3-4766-8917-5e1d3069b8eb.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=2e0f3720-20c3-4766-8917-5e1d3069b8eb</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This will work in SQL 2005...
</p>
        <p>
 
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <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">
                <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">Create</span>
                  <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">trigger</span> trgHmm1 <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">on</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">DATABASE</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">for</span> CREATE_TABLE,
DROP_TABLE, ALTER_TABLE<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">AS</span><br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   ROLLBACK</span>;<br /><br />
GO</span>
              </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">
                <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">C</span>reate</span>
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">trigger</span> trgHmm2 <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">on</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">DATABASE</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">for</span> CREATE_TRIGGER,
DROP_TRIGGER<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">AS</span><br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   ROLLBACK</span>;<br /><br />
GO<br /></span>
          </p>
        </blockquote>
        <font size="2">
          <p>
not sure about this one though:
</p>
          <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
            <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">Create</span>
                <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">trigger</span> trgHmm3 <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">on</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">DATABASE</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">for</span> CREATE_TRIGGER,
DROP_TRIGGER, DISABLE_TRIGGER<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">AS</span><br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   ROLLBACK</span>;<br /><br />
GO</span>
            </p>
          </blockquote>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <p>
 
</p>
            <p>
Kinda makes a strong case for really keeping tight control over who has db_ddladmin
in a database doesn't it?
</p>
            <p>
              <br />
 
</p>
          </span>
        </font>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=2e0f3720-20c3-4766-8917-5e1d3069b8eb" />
      </body>
      <title>Oh dear....</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,2e0f3720-20c3-4766-8917-5e1d3069b8eb.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/02/16/OhDear.aspx</link>
      <pubDate>Wed, 16 Feb 2005 23:34:07 GMT</pubDate>
      <description>&lt;p&gt;
This will work in SQL 2005...
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&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;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;Create&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;trigger&lt;/span&gt; trgHmm1 &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;on&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;DATABASE&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;for&lt;/span&gt; CREATE_TABLE,
DROP_TABLE, ALTER_TABLE&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;AS&lt;/span&gt;
&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;ROLLBACK&lt;/span&gt;;&lt;br&gt;
&lt;br&gt;
GO&lt;/span&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;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;C&lt;/span&gt;reate&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;trigger&lt;/span&gt; trgHmm2 &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;on&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;DATABASE&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;for&lt;/span&gt; CREATE_TRIGGER,
DROP_TRIGGER&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;AS&lt;/span&gt;
&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;ROLLBACK&lt;/span&gt;;&lt;br&gt;
&lt;br&gt;
GO&lt;br&gt;
&lt;/p&gt;
&gt;&lt;/blockquote&gt;&lt;font size=2&gt; 
&lt;p&gt;
not sure about this one though:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&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;Create&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;trigger&lt;/span&gt; trgHmm3 &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;on&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;DATABASE&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;for&lt;/span&gt; CREATE_TRIGGER,
DROP_TRIGGER, DISABLE_TRIGGER&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;AS&lt;/span&gt;
&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;ROLLBACK&lt;/span&gt;;&lt;br&gt;
&lt;br&gt;
GO&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; 
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Kinda makes a strong case for really keeping tight control over who has db_ddladmin
in a database doesn't it?
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;/span&gt;&lt;/font&gt;&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=2e0f3720-20c3-4766-8917-5e1d3069b8eb" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,2e0f3720-20c3-4766-8917-5e1d3069b8eb.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=1ccd1d4f-2152-4429-91e8-e9eccfa2a9de</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,1ccd1d4f-2152-4429-91e8-e9eccfa2a9de.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,1ccd1d4f-2152-4429-91e8-e9eccfa2a9de.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=1ccd1d4f-2152-4429-91e8-e9eccfa2a9de</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The Powerpoint Presentation and Source Code I used in monday's Visual Studio Integration
topic can now be downloaded from <a href="http://www.mindfusioncorp.com/download/NVEditPresentationAndSourceCode.zip">this
link</a>.
</p>
        <p>
If you just want to install the NVEdit Add-In (with Core Library and Help File), you
can download it from <a href="http://www.mindfusioncorp.com/download/NVEditSetup.msi">this
link</a>.
</p>
        <p>
If you have no idea what I am talking about:
</p>
        <p>
NVEdit is a simple Visual Studio 2003 Add-In that I created as a working example for <a href="http://www.mindfusioncorp.com/weblog/PermaLink,guid,6ea4eaf6-e63c-4234-9ec3-8f47c86e3612.aspx">my
presentation</a> to the <a href="http://www.atlantacsharp.org/default.aspx">Atlanta
C# Users Group</a>. This Add-In allows you to store large "non-volatile" textual data
(SQL queries, XML/XSD documents, etc) as an embedded resource in your assemblies.
The NVEditor keeps seperate name/value collections (Dictionaries) for SQL, XML,
XSL, XSD, and HTML. The values are accessible in a very easy manner at runtime using
static members, not too unlike the ConfigurationSettings class of the .NET Framework.
Unlike the ConfigurationSettings class however, the NVData values are not stored in
the .config file (which is succeptible to tampering).
</p>
        <p>
The whole idea is that this gives you a very viable alternative to cramming stuff
that doesn't belong into .config files or into hard-coded string constants.
</p>
        <p>
Here you can see a screen capture of the simple NVEditor UI:
</p>
        <p>
          <a href="http://www.mindfusioncorp.com/download/NVEditSetup.msi">
            <img height="336" alt="NVEditUI.jpg" src="http://www.mindfusioncorp.com/weblog/content/binary/NVEditUI.jpg" width="742" border="1" />
          </a>
        </p>
        <p>
I apologize for the delay in getting this uploaded. I tried (again) to get the RichTextBox
to perform colorizing the way I wanted it, and it just wasn't working out (jeez that
control really sucks). All of that stuff is ripped out now, and I cleaned up a few
other bits since my presentation.
</p>
        <p>
And I also compiled a help file that gets installed as well now (Hooray for <a href="http://ndoc.sourceforge.net/">NDoc</a>!).
Even though it really didn't need a help file. I mean, come on, this is a pretty darn
simple tool!
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=1ccd1d4f-2152-4429-91e8-e9eccfa2a9de" />
      </body>
      <title>NVEdit Downloads available now</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,1ccd1d4f-2152-4429-91e8-e9eccfa2a9de.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/02/10/NVEditDownloadsAvailableNow.aspx</link>
      <pubDate>Thu, 10 Feb 2005 07:13:11 GMT</pubDate>
      <description>&lt;p&gt;
The Powerpoint Presentation and Source Code I used in monday's Visual Studio Integration
topic can now be downloaded from &lt;a href="http://www.mindfusioncorp.com/download/NVEditPresentationAndSourceCode.zip"&gt;this
link&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
If you just want to install the NVEdit Add-In (with Core Library and Help File), you
can download it from &lt;a href="http://www.mindfusioncorp.com/download/NVEditSetup.msi"&gt;this
link&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
If you have no idea what I am talking about:
&lt;/p&gt;
&lt;p&gt;
NVEdit is a simple Visual Studio 2003 Add-In that I created as a working example for &lt;a href="http://www.mindfusioncorp.com/weblog/PermaLink,guid,6ea4eaf6-e63c-4234-9ec3-8f47c86e3612.aspx"&gt;my
presentation&lt;/a&gt; to the &lt;a href="http://www.atlantacsharp.org/default.aspx"&gt;Atlanta
C# Users Group&lt;/a&gt;. This Add-In allows you to store large "non-volatile" textual data
(SQL queries, XML/XSD documents, etc) as an embedded resource in your assemblies.
The NVEditor keeps seperate name/value collections (Dictionaries)&amp;nbsp;for SQL, XML,
XSL, XSD, and HTML. The values are accessible in a very easy manner at runtime using
static members, not too unlike the ConfigurationSettings class of the .NET Framework.
Unlike the ConfigurationSettings class however, the NVData values are not stored in
the .config file (which is succeptible to tampering).
&lt;/p&gt;
&lt;p&gt;
The whole idea is that this gives you a very viable alternative to cramming stuff
that doesn't belong into .config files or into hard-coded string constants.
&lt;/p&gt;
&lt;p&gt;
Here you can see a screen capture of the simple NVEditor UI:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.mindfusioncorp.com/download/NVEditSetup.msi"&gt;&lt;img height=336 alt=NVEditUI.jpg src="http://www.mindfusioncorp.com/weblog/content/binary/NVEditUI.jpg" width=742 border=1&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I apologize for the delay in getting this uploaded. I tried (again) to get the RichTextBox
to perform colorizing the way I wanted it, and it just wasn't working out (jeez that
control really sucks). All of that stuff is ripped out now, and I cleaned up a few
other bits since my presentation.
&lt;/p&gt;
&lt;p&gt;
And I also compiled a help file that gets installed as well now (Hooray for &lt;a href="http://ndoc.sourceforge.net/"&gt;NDoc&lt;/a&gt;!).
Even though it really didn't need a help file. I mean, come on, this is a pretty darn
simple tool!
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=1ccd1d4f-2152-4429-91e8-e9eccfa2a9de" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,1ccd1d4f-2152-4429-91e8-e9eccfa2a9de.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=6ea4eaf6-e63c-4234-9ec3-8f47c86e3612</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,6ea4eaf6-e63c-4234-9ec3-8f47c86e3612.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,6ea4eaf6-e63c-4234-9ec3-8f47c86e3612.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=6ea4eaf6-e63c-4234-9ec3-8f47c86e3612</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This coming monday, I expect to be doing a presentation to the local C# group. The
last time I presented to the group, it was a hastily prepared practical examination
of <a href="http://www.mindfusioncorp.com/weblog/PermaLink,guid,bcff05b6-62c7-43ac-be27-abec04929a2d.aspx">WSE2
programming</a> (without ASMX), schema-oriented messaging, service agents, and other
basics of using WSE2 in a SOA environment.
</p>
        <p>
The presentation this month is completely different.
</p>
        <p>
This time, I will define a common issue/concern with application design: the
handling of non-volatile textual data. Stuff like SQL queries, HTML fragments, template
XML documents, and so forth that often pepper the codebase of our projects, making
maintenance difficult.
</p>
        <p>
I will present a solution to this issue in two parts: A simple core library to provide
an extremely friendly "developer experience", and also a Visual Studio Add-In that
works hand-in-hand with the core library to make the solution very simple to use.
</p>
        <p>
We will talk about the issues I encountered while building the core library, the process
of building and deploying a VS Add-In, and also the issues that may arise during construction
of an Add-In.
</p>
        <p>
At the conclusion, we will end up with a functional and useful tool that can be employed
in our code projects, along with a better understanding of how sometimes extending
the Visual Studio environment can provide a good return on investment.
</p>
        <p>
So, if this subject interests you at all (I find it extremely interesting - but
I am truly a geek), or if you simply want to get your hands on this useful project
tool, then make sure to attend this months <a href="http://www.atlantacsharp.org/default.aspx">Atlanta
C# User Group</a> meeting!
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=6ea4eaf6-e63c-4234-9ec3-8f47c86e3612" />
      </body>
      <title>Upcoming Atlanta C# User Group presentation</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,6ea4eaf6-e63c-4234-9ec3-8f47c86e3612.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/02/03/UpcomingAtlantaCUserGroupPresentation.aspx</link>
      <pubDate>Thu, 03 Feb 2005 22:10:37 GMT</pubDate>
      <description>&lt;p&gt;
This coming monday, I expect to be doing a presentation to the local C# group. The
last time I presented to the group, it was a hastily prepared practical examination
of &lt;a href="http://www.mindfusioncorp.com/weblog/PermaLink,guid,bcff05b6-62c7-43ac-be27-abec04929a2d.aspx"&gt;WSE2
programming&lt;/a&gt; (without ASMX), schema-oriented messaging, service agents, and other
basics of using WSE2 in a SOA environment.
&lt;/p&gt;
&lt;p&gt;
The presentation this month is completely different.
&lt;/p&gt;
&lt;p&gt;
This time, I will&amp;nbsp;define a common issue/concern with application design: the
handling of non-volatile textual data. Stuff like SQL queries, HTML fragments, template
XML documents, and so forth that often pepper the codebase of our projects, making
maintenance difficult.
&lt;/p&gt;
&lt;p&gt;
I will present a solution to this issue in two parts: A simple core library to provide
an extremely friendly "developer experience", and also a Visual Studio Add-In that
works hand-in-hand with the core library to make the solution very simple to use.
&lt;/p&gt;
&lt;p&gt;
We will talk about the issues I encountered while building the core library, the process
of building and deploying a VS Add-In, and also the issues that may arise during construction
of an Add-In.
&lt;/p&gt;
&lt;p&gt;
At the conclusion, we will end up with a functional and useful tool that can be employed
in our code projects, along with a better understanding of how sometimes extending
the Visual Studio environment can provide a good return on investment.
&lt;/p&gt;
&lt;p&gt;
So, if this subject&amp;nbsp;interests you at all (I find it extremely interesting - but
I am truly a geek), or if you simply want to get your hands on this useful project
tool, then make sure to attend this months &lt;a href="http://www.atlantacsharp.org/default.aspx"&gt;Atlanta
C# User Group&lt;/a&gt; meeting!
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=6ea4eaf6-e63c-4234-9ec3-8f47c86e3612" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,6ea4eaf6-e63c-4234-9ec3-8f47c86e3612.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=da9cfe64-a2e4-4f2c-9791-165f95f4b2e6</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,da9cfe64-a2e4-4f2c-9791-165f95f4b2e6.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,da9cfe64-a2e4-4f2c-9791-165f95f4b2e6.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=da9cfe64-a2e4-4f2c-9791-165f95f4b2e6</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
What a stupid and obscure bug in VS.NET 2003. Thankfully someone figured it out and
posted <a href="http://breaman.net/index.php?p=7">the fix</a> on their blog (which
didn't take all that long to find in Google). Making a note of it here in case it
happens again. Who would have ever thought a DLL from the <em><strong>Visual C++ directory
tree</strong></em> in Visual Studio would get unregistered simply by running a VS
add-in deployment package install/uninstall a few times... and then would keep <em><strong>C#
project wizards</strong></em> from working??
</p>
        <p>
At least the fix is very simple and quick:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>regsvr32 "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\vcpackages\csproj.dll"</pre>
        </blockquote>
        <p>
Yes, thats c<strong>S</strong>proj.dll in the <strong>VC7</strong> folder.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=da9cfe64-a2e4-4f2c-9791-165f95f4b2e6" />
      </body>
      <title>"library not registered" when creating new c# project item or project</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,da9cfe64-a2e4-4f2c-9791-165f95f4b2e6.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/01/24/libraryNotRegisteredWhenCreatingNewCProjectItemOrProject.aspx</link>
      <pubDate>Mon, 24 Jan 2005 06:16:19 GMT</pubDate>
      <description>&lt;p&gt;
What a stupid and obscure bug in VS.NET 2003. Thankfully someone figured it out and
posted &lt;a href="http://breaman.net/index.php?p=7"&gt;the fix&lt;/a&gt; on their blog (which
didn't take all that long to find in Google). Making a note of it here in case it
happens again. Who would have ever thought a DLL from the &lt;em&gt;&lt;strong&gt;Visual C++ directory
tree&lt;/strong&gt;&lt;/em&gt; in Visual Studio would get unregistered simply by running a VS
add-in deployment package install/uninstall a few times... and then would keep &lt;em&gt;&lt;strong&gt;C#
project wizards&lt;/strong&gt;&lt;/em&gt; from working??
&lt;/p&gt;
&lt;p&gt;
At least the fix is very simple and quick:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;regsvr32 "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\vcpackages\csproj.dll"&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Yes, thats c&lt;strong&gt;S&lt;/strong&gt;proj.dll in the &lt;strong&gt;VC7&lt;/strong&gt; folder.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=da9cfe64-a2e4-4f2c-9791-165f95f4b2e6" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,da9cfe64-a2e4-4f2c-9791-165f95f4b2e6.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=7315f703-ab37-4f1d-a5e2-2d5123621492</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,7315f703-ab37-4f1d-a5e2-2d5123621492.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,7315f703-ab37-4f1d-a5e2-2d5123621492.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=7315f703-ab37-4f1d-a5e2-2d5123621492</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I couple weeks ago, I <a href="http://www.mindfusioncorp.com/weblog/PermaLink.aspx?guid=0ac519c7-97c9-492a-8cd9-d4d8555df089">recounted
some trouble</a> I was experiencing with the .NET garbage collector. My efforts to
dispose and clean up objects, and eliminate unnecessary allocations (essentially,
to be miserly with resources) brought a great deal of stability, performance, and
peace of mind.
</p>
        <p>
However, while much more rare, I still continued to experience random crashes in the
application. This time, however, I was able to get Windbg to trap the TerminateProcess,
allowing me to perform post-mortem. Here is what I discovered:
</p>
        <p>
In one screen of my application, there is a PictureBox. This screen is displayed while
the application is performing lengthy operations, the PictureBox contained an animated
GIF. The purpose of this was to keep the user preoccupied while waiting (just like
the waving flag at the top right of your browser while pulling down a page). Sounds
pretty innocuous.
</p>
        <p>
Well, as it turns out... behind the scenes, either the framework or Windows itself
(I did not dig into the PictureBox MSIL to check) actually spins up a thread to pump
the frame changes of the animation. Yes, this is a recipe for trouble. A rogue thread
running in the system, whose obvious task is to update the GUI (it is pumping
the animation). Hard Application crashes are a well-known side-effect of a background
thread that does not synchronize all shared (UI) resource access with the owning thread.
</p>
        <p>
So what was happening (confirmed by the smattering of PictureBox and lots of native
WinAPI calls over the thread that triggered the crash) is that the animation pump
thread was not properly coordinating with the UI thread that actually owned the PictureBox.
Or perhaps it was behaving well under normal circumstances, but it was not observing
the Garbage Collector's request to pause while the GC does it's thing. You see...
the crashes all also happened to occur while the GC was performing a heap walk. While
the GC thread is active, all other threads are *supposed* to be paused. But the animation
thread was not. And thereby the waking of that animation thread to pump another animation
frame, if it happened to wake while the GC was still walking the heap, would cause
a very nasty crash.
</p>
        <p>
Simply replacing the graphical content of the PictureBox with a static image (such
as a JPG) eliminated the problem by virtue of the offending thread never being created
in the first place (it is only created if you have an animated image loaded).
</p>
        <p>
So my primary lesson from this is to simply not use an animated GIF in a PictureBox
control. My secondary lesson is that it is still a very wise thing to explicitly clean
up after yourself using Dispose() and Clear() on objects that support those semantics,
and setting references to null for all non-value types as soon as they are no longer
needed. Work *with* the garbage collector, not against it!
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=7315f703-ab37-4f1d-a5e2-2d5123621492" />
      </body>
      <title>More garbage collector woes</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,7315f703-ab37-4f1d-a5e2-2d5123621492.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/01/11/MoreGarbageCollectorWoes.aspx</link>
      <pubDate>Tue, 11 Jan 2005 22:30:52 GMT</pubDate>
      <description>&lt;p&gt;
I couple weeks ago, I &lt;a href="http://www.mindfusioncorp.com/weblog/PermaLink.aspx?guid=0ac519c7-97c9-492a-8cd9-d4d8555df089"&gt;recounted
some trouble&lt;/a&gt; I was experiencing with the .NET garbage collector. My efforts to
dispose and clean up objects, and eliminate unnecessary allocations (essentially,
to be miserly with resources) brought a great deal of stability, performance, and
peace of mind.
&lt;/p&gt;
&lt;p&gt;
However, while much more rare, I still continued to experience random crashes in the
application. This time, however, I was able to get Windbg to trap the TerminateProcess,
allowing me to perform post-mortem. Here is what I discovered:
&lt;/p&gt;
&lt;p&gt;
In one screen of my application, there is a PictureBox. This screen is displayed while
the application is performing lengthy operations, the PictureBox contained an animated
GIF. The purpose of this was to keep the user preoccupied while waiting (just like
the waving flag at the top right of your browser while pulling down a page). Sounds
pretty innocuous.
&lt;/p&gt;
&lt;p&gt;
Well, as it turns out... behind the scenes, either the framework or Windows itself
(I did not dig into the PictureBox MSIL to check) actually spins up a thread to pump
the frame changes of the animation. Yes, this is a recipe for trouble. A rogue thread
running in the system, whose&amp;nbsp;obvious task&amp;nbsp;is to update the GUI (it is pumping
the animation). Hard Application crashes are a well-known side-effect of a background
thread that does not synchronize all shared (UI) resource access with the owning thread.
&lt;/p&gt;
&lt;p&gt;
So what was happening (confirmed by the smattering of PictureBox and lots of native
WinAPI calls over the thread that triggered the crash) is that the animation pump
thread was not properly coordinating with the UI thread that actually owned the PictureBox.
Or perhaps it was behaving well under normal circumstances, but it was not observing
the Garbage Collector's request to pause while the GC does it's thing. You see...
the crashes all also happened to occur while the GC was performing a heap walk. While
the GC thread is active, all other threads are *supposed* to be paused. But the animation
thread was not. And thereby the waking of that animation thread to pump another animation
frame, if it happened to wake while the GC was still walking the heap, would cause
a very nasty crash.
&lt;/p&gt;
&lt;p&gt;
Simply replacing the graphical content of the PictureBox with a static image (such
as a JPG) eliminated the problem by virtue of the offending thread never being created
in the first place (it is only created if you have an animated image loaded).
&lt;/p&gt;
&lt;p&gt;
So my primary lesson from this is to simply not use an animated GIF in a PictureBox
control. My secondary lesson is that it is still a very wise thing to explicitly clean
up after yourself using Dispose() and Clear() on objects that support those semantics,
and setting references to null for all non-value types as soon as they are no longer
needed. Work *with* the garbage collector, not against it!
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=7315f703-ab37-4f1d-a5e2-2d5123621492" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,7315f703-ab37-4f1d-a5e2-2d5123621492.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.mindfusioncorp.com/weblog/Trackback.aspx?guid=0721931f-c7c2-4af2-a855-5762b3f53640</trackback:ping>
      <pingback:server>http://www.mindfusioncorp.com/weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.mindfusioncorp.com/weblog/PermaLink,guid,0721931f-c7c2-4af2-a855-5762b3f53640.aspx</pingback:target>
      <dc:creator>Keith Rome</dc:creator>
      <wfw:comment>http://www.mindfusioncorp.com/weblog/CommentView,guid,0721931f-c7c2-4af2-a855-5762b3f53640.aspx</wfw:comment>
      <wfw:commentRss>http://www.mindfusioncorp.com/weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=0721931f-c7c2-4af2-a855-5762b3f53640</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In my recent pilgrimage through the .NET memory model, the garbage collection process,
and the fine art of improving performance through runtime profiling and heap inspection,
I came across this little piece of knowledge that may one day (maybe today?) benefit
you as well. This is a short discussion of the subtle and rarely mentioned static
function:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <strong>String.Intern()</strong>
          </pre>
        </blockquote>
        <p>
From the MSDN documentation, this method is explained as such:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <em>“The <strong>Intern</strong> method uses the intern pool to search for a
string equal to the value of str. If such a string exists, its reference in the intern
pool is returned. If the string does not exist, a reference to str is added to the
intern pool, then that reference is returned.”</em>
          </p>
        </blockquote>
        <p>
Sounds innocuous, but this little core feature may end up having great impact on your
applications. Essentially, when you use String.Intern(), instead of making a copy
of the string data on the managed heap, you instead are returned a reference to a
shared copy of that same literal string. When you embed literal string values (<em><font color="#0066ff">string</font> myString
= “some value”</em>) in your program code, the compiler automatically
does this for you. Embedded literal strings will be “interned” for you
without any additional effort.
</p>
        <p>
So you might be wondering, “OK so now why do I care about this, if the compiler
already does this for me?”. The answer is that the compiler only handles <em>hard-coded</em> string
values. Consider this snippet of code:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <font color="#0066ff">public
string</font>[] BurnBabyBurn(<font color="#0066ff">string</font> Input)<br />
{<br />
    <font color="#0066ff">string</font>[] MyHugeArrayOfJunk = <font color="#0066ff">new</font><font color="#0066ff">string</font>[2000];<br />
    <font color="#0066ff">for</font> (<font color="#0066ff">int</font> Index
= 0; Index &lt; 2000; Index++)<br />
    {<br />
        MyHugeArrayOfJunk[Index] = Input;<br />
    }<br />
   <font color="#0066ff">return</font> MyHugeArrayOfJunk;<br />
}</pre>
          <pre>[...]</pre>
          <pre>
            <font color="#0066ff">string</font>[] test = BurnBabyBurn("0123456789");<br /></pre>
        </blockquote>
        <p>
As you have probably guessed, this will make 2000 copies of the same literal string
“0123456789“. Not very friendly to your memory footprint. So let us alter
the previous code sample to make use of <strong>String.Intern()</strong>:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <pre>
            <font color="#0066ff">public
string</font>[] ByNiceToMe(<font color="#0066ff">string</font> Input)<br />
{<br />
    <font color="#0066ff">string</font>[] MySmallerArrayOfJunk = <font color="#0066ff">new</font><font color="#0066ff">string</font>[2000];<br />
    <font color="#0066ff">for</font> (<font color="#0066ff">int</font> Index
= 0; Index &lt; 2000; Index++)<br />
    {<br />
        MySmallerArrayOfJunk[Index] = String.Intern(Input);<br />
    }<br />
    <font color="#0066ff">return</font> MySmallerArrayOfJunk;<br />
}</pre>
          <pre>[...]</pre>
          <pre>
            <font color="#0066ff">string</font>[] test = BeNiceToMe("0123456789");<br /></pre>
        </blockquote>
        <p>
The difference is significant. This second version of the same logic will now make
2000 references to the same string value, rather than 2000 copies of it. This is a
huge difference in terms of memory allocation on the managed heap (don't believe me?
Try both routines and use CLR Profiler to see how much String data is sitting on your
heap!).
</p>
        <p>
Now sure, this example is simple and contrived (you really wouldnt ever build a 2000
element string array with the same values would you?). However, it illustrates a very
useful way to reduce your memory churn in an application (and therefore reduced footprint,
GC time, etc). Supposing you had a DataSet filled with values. Suppose there were
10 string columns, and 500 rows. Assume much of those 5000 string values were duplicates
(result of enumeration domains, looked up values, etc)... I wonder what the memory
savings (and GC savings when you Dispose() it!) would be? A hint: <strong>big enough
to pay attention to</strong>.
</p>
        <img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=0721931f-c7c2-4af2-a855-5762b3f53640" />
      </body>
      <title>Tips and Tricks: String.Intern()</title>
      <guid isPermaLink="false">http://www.mindfusioncorp.com/weblog/PermaLink,guid,0721931f-c7c2-4af2-a855-5762b3f53640.aspx</guid>
      <link>http://www.mindfusioncorp.com/weblog/2005/01/02/TipsAndTricksStringIntern.aspx</link>
      <pubDate>Sun, 02 Jan 2005 02:10:46 GMT</pubDate>
      <description>&lt;p&gt;
In my recent pilgrimage through the .NET memory model, the garbage collection process,
and the fine art of improving performance through runtime profiling and heap inspection,
I came across this little piece of knowledge that may one day (maybe today?) benefit
you as well. This is a short discussion of the subtle and rarely mentioned static
function:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;strong&gt;String.Intern()&lt;/strong&gt;&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
From the MSDN documentation, this method is explained as such:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;em&gt;&amp;#8220;The &lt;strong&gt;Intern&lt;/strong&gt; method uses the intern pool to search for a
string equal to the value of str. If such a string exists, its reference in the intern
pool is returned. If the string does not exist, a reference to str is added to the
intern pool, then that reference is returned.&amp;#8221;&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Sounds innocuous, but this little core feature may end up having great impact on your
applications. Essentially, when you use String.Intern(), instead of making a copy
of the string data on the managed heap, you instead are returned a reference to a
shared copy of that same literal string. When you embed literal string values (&lt;em&gt;&lt;font color=#0066ff&gt;string&lt;/font&gt; myString
= &amp;#8220;some value&amp;#8221;&lt;/em&gt;) in your program code, the compiler automatically
does this for you. Embedded literal strings will be &amp;#8220;interned&amp;#8221; for you
without any additional effort.
&lt;/p&gt;
&lt;p&gt;
So you might be wondering, &amp;#8220;OK so now why do I care about this, if the compiler
already does this for me?&amp;#8221;. The answer is that the compiler only handles &lt;em&gt;hard-coded&lt;/em&gt; string
values. Consider this snippet of code:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font color=#0066ff&gt;public string&lt;/font&gt;[]
BurnBabyBurn(&lt;font color=#0066ff&gt;string&lt;/font&gt; Input)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0066ff&gt;string&lt;/font&gt;[] MyHugeArrayOfJunk = &lt;font color=#0066ff&gt;new&lt;/font&gt; &lt;font color=#0066ff&gt;string&lt;/font&gt;[2000];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0066ff&gt;for&lt;/font&gt; (&lt;font color=#0066ff&gt;int&lt;/font&gt; Index
= 0; Index &amp;lt; 2000; Index++)&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; MyHugeArrayOfJunk[Index] = Input;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#0066ff&gt;return&lt;/font&gt; MyHugeArrayOfJunk;&lt;br&gt;
}&lt;/pre&gt;&lt;pre&gt;[...]&lt;/pre&gt;&lt;pre&gt;&lt;font color=#0066ff&gt;string&lt;/font&gt;[] test = BurnBabyBurn("0123456789");&lt;br&gt;
&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
As you have probably guessed, this will make 2000 copies of the same literal string
&amp;#8220;0123456789&amp;#8220;. Not very friendly to your memory footprint. So let us alter
the previous code sample to make use of &lt;strong&gt;String.Intern()&lt;/strong&gt;:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font color=#0066ff&gt;public string&lt;/font&gt;[]
ByNiceToMe(&lt;font color=#0066ff&gt;string&lt;/font&gt; Input)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0066ff&gt;string&lt;/font&gt;[] MySmallerArrayOfJunk = &lt;font color=#0066ff&gt;new&lt;/font&gt; &lt;font color=#0066ff&gt;string&lt;/font&gt;[2000];&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0066ff&gt;for&lt;/font&gt; (&lt;font color=#0066ff&gt;int&lt;/font&gt; Index
= 0; Index &amp;lt; 2000; Index++)&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; MySmallerArrayOfJunk[Index] = String.Intern(Input);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#0066ff&gt;return&lt;/font&gt; MySmallerArrayOfJunk;&lt;br&gt;
}&lt;/pre&gt;&lt;pre&gt;[...]&lt;/pre&gt;&lt;pre&gt;&lt;font color=#0066ff&gt;string&lt;/font&gt;[] test = BeNiceToMe("0123456789");&lt;br&gt;
&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
The difference is significant. This second version of the same logic will now make
2000 references to the same string value, rather than 2000 copies of it. This is a
huge difference in terms of memory allocation on the managed heap (don't believe me?
Try both routines and use CLR Profiler to see how much String data is sitting on your
heap!).
&lt;/p&gt;
&lt;p&gt;
Now sure, this example is simple and contrived (you really wouldnt ever build a 2000
element string array with the same values would you?). However, it illustrates a very
useful way to reduce your memory churn in an application (and therefore reduced footprint,
GC time, etc). Supposing you had a DataSet filled with values. Suppose there were
10 string columns, and 500 rows. Assume much of those 5000 string values were duplicates
(result of enumeration domains, looked up values, etc)... I wonder what the memory
savings (and GC savings when you Dispose() it!) would be? A hint: &lt;strong&gt;big enough
to pay attention to&lt;/strong&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.mindfusioncorp.com/weblog/aggbug.ashx?id=0721931f-c7c2-4af2-a855-5762b3f53640" /&gt;</description>
      <comments>http://www.mindfusioncorp.com/weblog/CommentView,guid,0721931f-c7c2-4af2-a855-5762b3f53640.aspx</comments>
      <category>General</category>
      <category>Tips and Tricks</category>
    </item>
  </channel>
</rss>