<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Elegant Code &#187; Tony Rasa</title>
	<atom:link href="http://elegantcode.com/author/trasa/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 20 Jul 2010 12:52:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MvcFutures</title>
		<link>http://elegantcode.com/2010/03/13/mvcfutures/</link>
		<comments>http://elegantcode.com/2010/03/13/mvcfutures/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 17:49:42 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[ExpressionHelper]]></category>
		<category><![CDATA[MvcFutures]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/03/13/mvcfutures/</guid>
		<description><![CDATA[ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET MVC 2 has been released (yay).&#160; One of the pieces I like about it is in the MvcFutures assembly.&#160; MvcFutures is where the MVC team puts code for features that may or may not make it into a future version of the MVC framework – undocumented, somewhat risky, but hey you get all the source code if you find yourself painted into a corner.</p>
<p>One of the long-standing MVC practices has been ‘Shun Magic Strings.’&#160; For example, rather than specifying Controller/Action names in an ActionLink by string, we’ve always used an Expression&lt;Action&lt;TController&gt;&gt; instead to define the Controller class and Action method “in code.”&#160; If the action changes in the future, this gives you somewhat better abilities to discover the problem sooner vs. later.&#160; </p>
<p>MvcFutures includes a version of this idea, taken to the next level:&#160; you provide the expression with the arguments you want passed to the action included – you don’t provide a 2nd anonymous type defining the arguments.&#160; This gets rid of the somewhat confusing “null” arguments inside the expression, and just looks better overall.&#160; Plus, if the arguments to the action change, you’ll get better warning of that as well.</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&lt;asp:Content ID=<span style="color: #006080">&quot;Content2&quot;</span> ContentPlaceHolderID=<span style="color: #006080">&quot;MainContent&quot;</span> runat=<span style="color: #006080">&quot;server&quot;</span>&gt;    &lt;h2&gt;Magic Strings are Evil&lt;/h2&gt;    &lt;p&gt;        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(16), <span style="color: #006080">&quot;A Number&quot;</span>) %&gt;        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(32), <span style="color: #006080">&quot;Another Number&quot;</span>) %&gt;        &lt;%= Html.ActionLink&lt;HomeController&gt;(c =&gt; c.FavoriteNumber(42), <span style="color: #006080">&quot;Yet Another Number&quot;</span>) %&gt;            &lt;/p&gt;&lt;/asp:Content&gt;</pre>
<p></div>
<p>I like this method MUCH better.&#160; </p>
<p>The implementation that makes this happen is in Microsoft.Web.Mvc.Internal.ExpressionHelper.&#160; Which even though it’s in an “Internal” namespace, is neither marked Internal, Sealed, or otherwise made unavailable (hallelujah).&#160; So you can use this trick for all sorts of things.</p>
<p>There is also a System.Web.Mvc.ExpressionHelper in the official MVC assembly, which is used to implement the smart Html.TextBoxFor(m =&gt; m.Property) functionality.&#160; This class is also NOT internal, not sealed, not obfuscated and hidden away.&#160; We’ve used it to extend the Html.[control]For() abilities to some other control types.&#160; Very useful stuff.&#160; Plus its just interesting code to read.</p>
<p><strong>One potentially big caveat:</strong>&#160; I’m told that the Html.ActionLink&lt;TController&gt;() methods don’t work if you’re using Areas in your MVC application.&#160; I haven’t tried this myself, we aren’t using Areas in any of our MVC 2 applications yet.&#160; That might be why this functionality is hidden in MvcFutures and not out with the rest of the smart expression code.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/03/13/mvcfutures/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>
<p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>
<p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>
<p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>
<p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>
<p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>
<p>&#160;</p>
<p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>
<p>&#160;</p>
<p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>
<p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Restricted Pan and Zoom in WPF</title>
		<link>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</link>
		<comments>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 04:47:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[ScaleTransform]]></category>
		<category><![CDATA[TranslateTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/</guid>
		<description><![CDATA[After running into animation problems in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This Pan and Zoom code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/">running into animation problems</a> in Silverlight 3 and 4, I’m implementing my user interface using full blown WPF.&#160; This <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">Pan and Zoom</a> code works great, with a minor tweak and one issue: I need to control the allowable zoom ranges, and I don’t want the user to be able to pan the image “right off of the map”, instead I need a hard border on all four sides.&#160; And these hard-stops need to pay attention to the current zoom level as well.</p>
<h4>Minimum and Maximum Zoom</h4>
<p>This part is easy – I added two properties, MinimumZoom and MaximumZoom, default them to double.MinValue and double.MaxValue, and some trivial code in DoZoom to keep the scale values in line:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> PanAndZoomViewer() {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>   MaximumZoom = <span style="color: #0000ff">double</span>.MaxValue;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   MinimumZoom = <span style="color: #0000ff">double</span>.MinValue;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MaximumZoom { get; set; }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">double</span> MinimumZoom { get; set; }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoZoom(<span style="color: #0000ff">double</span> deltaZoom, </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>                    Point mousePosition, </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>                    Point physicalPosition) {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #008000">// Keep Zoom within bounds declared by Minimum/MaximumZoom</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">double</span> currentZoom = zoomTransform.ScaleX;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   currentZoom *= deltaZoom;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   <span style="color: #0000ff">if</span> (currentZoom &lt; MinimumZoom)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>     currentZoom = MinimumZoom;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (currentZoom &gt; MaximumZoom)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     currentZoom = MaximumZoom;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>   <span style="color: #008000">// do zoom animation stuff...</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> }</pre>
<p><!--CRLF--></div>
</div>
<h4>Limiting Pan Transform</h4>
<p>This required slightly more thought, and some graph paper.&#160; Having a clue about how WPF deals with its coordinate systems would have been helpful too.&#160; I have a Canvas as the Content of my PanAndZoomViewer.&#160; No matter what panning &amp; zooming happens, this Canvas will always have a fixed Height and Width.&#160; The Origin in our setup is always going to be the upper left corner of the Canvas, and remember that in the coordinate system used by Windows, “up” and “left” from that point are negative values.&#160; (The Y axis is the opposite of what you’d expect).&#160; Here’s a lame Paint.NET picture to help you understand:</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint.NET FTW!" border="0" alt="Paint.NET FTW!" src="http://elegantcode.com/wp-content/uploads/2010/01/Coordinates_thumb.png" width="244" height="184" /></a> </p>
<p>The Red View area is the part of the map canvas you’re zoomed into and viewing.&#160; The blue area is the entire map.&#160; I don’t want you to be able to move the Red rectangle beyond the boundaries of the Blue Rectangle, because instead of viewing the map you’d be viewing the dining room table, or the Red Rectangle would fall off the table onto the floor, or something.</p>
<p>Handling the Left and Top boundaries of the Blue Rectangle are easy enough, at any zoom level.&#160; If you were to move the Red Rectangle to beyond either of those edges, then one or both of the values for (ToX, ToY) would be positive (past the Origin corner).&#160; So we reset positive values back to zero and then animate to keep things nice and smooth.</p>
<h4>Pan Right, Bottom</h4>
<p>The other two edges are slightly less intuitive, at least to me.&#160; Consider the Right edge of the Red Rectangle View: I don’t want this edge passing over the Blue Rectangle.&#160; This puts a “maximum” value on the distance from the Left Edge of the Red Rectangle (at X = 0), and the Left Edge of the Blue Rectangle.&#160; Except that this value would be negative being to the left of the origin, so it’s really a minimum.&#160; (Trivial arithmetic, I know, and yet I still messed it up the first time.)&#160; </p>
<p>So, the minimum allowed ToX value is content.Width &#8211; (content.Width * scale).&#160; If you try to move the Red Rectangle farther away, we just snap it back to the edge.&#160; Same thing with the minimum Y values.</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2010/01/pan.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Paint..WTF" border="0" alt="Paint..WTF" src="http://elegantcode.com/wp-content/uploads/2010/01/pan_thumb.png" width="244" height="184" /></a> </p>
<h4></h4>
<h4>The Result</h4>
<p>The code to handle this looks something like this:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> control_MouseMove(<span style="color: #0000ff">object</span> sender, MouseEventArgs e)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (!IsMouseCaptured)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span>; <span style="color: #008000">// don't care.</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// if the mouse is captured then move the content by changing the translate transform.  </span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #008000">// use the Pan Animation to animate to the new location based on the delta between the </span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #008000">// starting point of the mouse and the current point.</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     Point physicalPoint = e.GetPosition(<span style="color: #0000ff">this</span>);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #008000">// where you'd like to move the top left corner of the view to</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">double</span> toX = physicalPoint.X - ScreenStartPoint.X + startOffset.X;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">double</span> toY = physicalPoint.Y - ScreenStartPoint.Y + startOffset.Y;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     Console.WriteLine(<span style="color: #006080">&quot;You're attempting to move to &quot;</span> + toX + <span style="color: #006080">&quot;,&quot;</span> + toY);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>     <span style="color: #0000ff">double</span> scaleValue = zoomTransform.ScaleX;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>     var content = (FrameworkElement)Content;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #008000">// minimum values we can shift the origin to - </span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     <span style="color: #008000">// maximum values is always 0 (we don't want the left side of the content</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #008000">// ever being beyond the left part of the view</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">double</span> minToX = content.Width - (content.Width * scaleValue);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">double</span> minToY = content.Height - (content.Height * scaleValue);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     <span style="color: #008000">// correct any invalid amounts:</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">if</span> (toX &gt; 0)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         toX = 0;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toX &lt; minToX)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>         toX = minToX;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>     <span style="color: #0000ff">if</span> (toY &gt; 0)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         toY = 0;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (toY &lt; minToY)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         toY = minToY;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span>     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreatePanAnimation(toX),</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37">  37:</span>                                       HandoffBehavior.Compose);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38">  38:</span>     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreatePanAnimation(toY),</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39">  39:</span>                                       HandoffBehavior.Compose);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40">  40:</span> }</pre>
<p><!--CRLF--></div>
</div>
<h4>All The Source Code</h4>
<p><iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomWpfTest.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/17/restricted-pan-and-zoom-in-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odd Behavior with ScaleTransform.CenterXY in SilverLight 3</title>
		<link>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</link>
		<comments>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 04:52:43 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[DoubleAnimation]]></category>
		<category><![CDATA[ScaleTransform]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/</guid>
		<description><![CDATA[Lately I’ve been working on an AI project, parts of which might get turned into a Boise Code Camp presentation, hopefully.&#160; Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.&#160; A [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I’ve been working on an AI project, parts of which might get turned into a <a href="http://www.boisecodecamp.com/" target="_blank">Boise Code Camp presentation</a>, hopefully.&#160; Rather than just debugging via Console.Write, I want to see what the AI is up to using one of those new-fangled Graphical User Interfaces that I’ve heard so much about, specifically via Silverlight.&#160; A major requirement is to be able to zoom in and out of a canvas, along with the ability to pan around the canvas.&#160; If you’ve played an RTS like Starcraft, you’ll know what I mean.&#160; I thought that this would be easy, certainly far easier than debugging A* pathfinding.&#160; As usual, I was wrong.</p>
<p>To zoom in or out, use the mouse wheel while hovering over the map.&#160; Zooming In should bring you into the point you are hovering over &#8211; “zoom in here.”&#160; This is implemented via a ScaleTransform, plus an animation to keep things nice and smooth.&#160; The ScaleTransform exposes two properties, CenterX and CenterY, to make this happen.&#160;&#160; </p>
<p>And in fact, when you first zoom in to a section of the map, the zoom does exactly that.&#160; The problem is – zoom back out, now move to a different section of the map and attempt to zoom in – the animation completely ignores the new CenterX and Y values and will always use the previous Center value.&#160; This problem was also confirmed using the latest release of Silverlight 4.</p>
<p>If I remove the animation completely and just alter the ScaleTransform directly, the CenterXY code works fine.&#160; However this was causing other problems…</p>
<p>The Pan and Zoom functionality seemed like it was much easier to get working in WPF however – and since I didn’t have a strict requirement to be using Silverlight… I will post a working Pan/Zoom Canvas example, largely based on code from <a href="http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx" target="_blank">this article</a> on Joe Wood’s blog.</p>
<p>Three different sample sln’s showing the problem available over here:</p>
<p> <iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-3c6a8372a874449b.skydrive.live.com/embedicon.aspx/.Public/ZoomPanHeadaches.zip" frameborder="0" marginwidth="0" scrolling="no"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/16/odd-behavior-with-scaletransform-centerxy-in-silverlight-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OpenCV cvLoadImage IOError</title>
		<link>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</link>
		<comments>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 16:31:26 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[openCV]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/</guid>
		<description><![CDATA[I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced OpenCV.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.
The bad news:&#160; I’m writing this on a Windows box and [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a project that involves computer vision algorithms.&#160; Fortunately, really smart people have done all the hard work and produced <a href="http://opencv.willowgarage.com/wiki/" target="_blank">OpenCV</a>.&#160; Even better, there are a set of Python bindings, which makes a big difference because my project is written using Python.</p>
<p>The bad news:&#160; I’m writing this on a Windows box and support for some things is sketchy or just non-existent.&#160; Also, using Python vs. this C library puts a big distance between “what you think is happening” and “what is happening,” so debugging leaves you wondering if the problem is your code, Eclipse somehow messing things up, Python, the Python bindings, somewhere within openCV, or just broken or incomplete support for Windows.</p>
<p>So imagine my confusion when this simple program:</p>
<pre class="csharpcode">import cv
img = cv.LoadImage(<span class="str">&quot;img.tif&quot;</span>)</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Generates <span class="csharpcode">IOError: [Errno 2] No such file or directory: &#8216;img.tif&#8217;</span></p>
<p>I mean, what’s simpler than just loading a file from disk?!&#160; </p>
<p>I found many people reporting this error, but no solutions other than “The file or directory doesn’t exist or isn’t readable…”</p>
<p>So, after checking (and rechecking) that the file does indeed exist, and then after using the full path to the file and getting the same error, I tried to find where the error was originating through all these layers.</p>
<p>I tried opening the image file using <a href="http://www.pythonware.com/products/pil/" target="_blank">PIL</a> and then converting the image over to OpenCV format, which did not generate an error, except that the resulting image wouldn’t quite survive the process – so I guess that doesn’t count as “working.”&#160; Displaying the image using Windows Photo Viewer worked fine.&#160; Out of desperation I grabbed a random image off of the Internet and tried to open it with OpenCV &#8212; and it worked.</p>
<p>Hmm, where did my original images come from?&#160; I screen-grabbed them off of another application, and then to save time &#8211; rather than waiting for Gimp to open &#8211; I just used MSPAINT.EXE to … oh, damn.&#160; “Short Cuts make for Long Journeys.”&#160; The original file was corrupt, just enough so that openCV would be unable to load it, but not so much that other programs and libs couldn’t load “something.”</p>
<p>So, <em>ignore the text of that error message </em>and read it as “openCV, for some reason that it won’t describe, could not load your image.&#160; Maybe the file is not there, or maybe you messed it up by being sloppy?”&#160; </p>
<p>Re-capturing the image using Gimp and PNG fixed the problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/03/opencv-cvloadimage-ioerror/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Removing WSUS</title>
		<link>http://elegantcode.com/2009/12/01/removing-wsus/</link>
		<comments>http://elegantcode.com/2009/12/01/removing-wsus/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 21:53:49 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[WSUS]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/12/01/removing-wsus/</guid>
		<description><![CDATA[A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, the company I work for experimented with setting up a Windows Server Update Service (WSUS).&#160; The idea is that you have one server that goes out and downloads all of the hotfixes, service packs, and so on for your network – then each of your client machines goes directly to the local WSUS server to get the weekly dose of patches, configurable by various group policies, and with monitoring to make sure that everything is going smoothly.&#160; At the time we set it up, we were having crushing bandwidth problems – two servers downloading a service pack would pretty much disable the building…</p>
<p>Over time, the bandwidth problems were fixed, and as sometimes happens the WSUS server crumbled to dust.&#160; For the most part nobody noticed – new servers and clients were not configured with the WSUS policy, downloading their hotfixes direct from Microsoft through plentiful bandwidth.&#160; Unfortunately, older server and clients were left in the dark, sending cries out to a WSUS URL that will never respond&#8230;&#160; oops</p>
<h4>To Fix (and get your automatic updates to work again):</h4>
<p>Delete the registry key at “HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate”.&#160; For fun, restart the “Windows Update” service (not sure if this is necessary).&#160; </p>
<p>I found <a href="http://www.d.umn.edu/itss/security/sus/" target="_blank">this VBS file</a> to be useful in figuring out if a server was still trying to use an old WSUS install, or if the problem was group-policy related.&#160; </p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/12/01/removing-wsus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure Summary</title>
		<link>http://elegantcode.com/2009/11/16/azure-summary/</link>
		<comments>http://elegantcode.com/2009/11/16/azure-summary/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 05:30:14 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/16/azure-summary/</guid>
		<description><![CDATA[I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked today, “what’s this whole ‘Microsoft Azure’ thing about?”&#160; I haven’t done anything with Azure, EC2, or Google Apps Engine, but why let my ignorance stop me from blogging about it?&#160; So here’s a brief summary of what I understand about these cloud technologies – I find the whole idea fascinating and am looking for an excuse to do more with one of these implementations.&#160;&#160; Consider this a plea for my friends, the Elegant Code Peanut Gallery, to help bring understanding to us all.</p>
<h4>The tl;dr version</h4>
<p>Azure involves a classic tradeoff: being able to scale very effectively and not having to make major capital investments, vs. having to pay more to your cloud computing environment for the convenience of it.&#160; It’s suitable for some applications and businesses, but certainly not all.&#160; To make the most of it, you should (or, must) architect your application around the whole cloud-notion to begin with.&#160; How much, and how bad it’ll hurt, depends on platform and your application.</p>
<h4>The Long Winded Version</h4>
<p>Let’s say you’re a big online retailer, selling books online (as an example I just made up).&#160;&#160;&#160; For 3 months of the year, your servers are completely slammed with orders – you need lots of bandwidth, lots of CPU, everything.&#160; I’m talking about renting out a big data center for $BidMoney a month, hiring SysAdmins, NetAdmins, all of that.&#160;&#160;&#160; The other 9 months of the year, its boring.&#160; You could just have a server under your desk, and hire some high school kid to keep it running.</p>
<p>This is why Amazon’s EC2 was invented (and why Microsoft is competing with them with Azure).&#160;&#160; Rather than buying racks of servers, hiring staff to keep it running, and so on &#8211; for stuff that you won’t need for most of the year, you deploy your application to Azure – when times are busy, you spool up additional servers easily.&#160; When the rush is over, just throw those extra instances away.</p>
<p>Your startup get mentioned in the WSJ?&#160; Add servers to deal with the traffic, so you don’t look stupid with “Server Unavailable” errors.&#160; Any sort of business model that is built around ‘bursts’ makes a lot of sense for this.</p>
<p>The tradeoff:&#160; Cost.&#160; You pay for CPU time, storage space, transactions, bandwidth.&#160; Each of these are really small numbers like “$0.15 / GB stored / month” and “$0.01 / 10k transactions” but they can add up quickly &#8211; a Death of a Thousand Cuts.&#160; Plus, with EC2 and Azure, the CPU time is not “cpu time doing something useful,” it is “<a href="http://www.microsoft.com/windowsazure/pricing/" target="_blank">amount of hours the virtual server was running</a>.”&#160;&#160; So if your app spends most of its time doing nothing…</p>
<p>For a small app with little traffic, this could add up to $100s / month, instead of just paying $VeryLittle/month for really lousy shared hosting, or a little more for less-lousy virtual hosting.&#160;&#160; And as I understand it, all of these services are “No Refunds” so if you get hit with a big wave of traffic, or forget to turn a server off when you were done with it, or whatever, … too bad, pay up!&#160; </p>
<p>It’s not all bad though – Google App Engine is free for 500 MB of storage and 5 million page views, and when you’re ready for more you can set up a quota and daily budget so you don’t get any nasty surprises.&#160; And while Azure is in CTP, its without charge (with a few modest quotas applied).&#160; So, you can start writing your Facebook-killer app right now, and deal with the costs later <img src='http://elegantcode.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h4>Application Design</h4>
<p>With Google App Engine and Amazon EC2, and mostly with Microsoft Azure, you must design your applications with cloud operation up front.&#160; It’s not exactly trivial to take an app written for a more traditional web server/database structure and deploy it to the cloud: you should be using the cloud’s data access APIs, not storing anything on the server itself, and have ways to get your data to and from the cloud (racking up transaction fees in the process).&#160; And don’t forget that your data is out there in hostile territory – how are you going to <a href="http://techboise.com/hows-your-crypto" target="_blank">keep it safe</a>?&#160; Plus your choice of cloud dictates what languages and platforms you can choose from.</p>
<p>I said “mostly” because with Azure you can pay a little extra to get access to “SQL Azure” if you need relational database storage.&#160; Which I think is great, although you’d have to balance those costs against the effort of using a more transaction based storage model.</p>
<p>&#160;</p>
<p>So there you go, a tiny bit of understanding packed into a dangerous form of leaping conclusions.&#160; <img src='http://elegantcode.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/16/azure-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StructureMap and SharePoint</title>
		<link>http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/</link>
		<comments>http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 18:00:22 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[StructureMap]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/</guid>
		<description><![CDATA[I’ve started doing some SharePoint development and have brought some of my favorite tools and practices with me.&#160; Like unit tests.&#160; And IoC.&#160; And that other SOLID stuff.&#160; 
I’m writing a very basic WebPart to get started with SharePoint – this web part will display a list of links to other applications that the user [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve started doing some SharePoint development and have brought some of my favorite tools and practices with me.&#160; Like unit tests.&#160; And IoC.&#160; And that other SOLID stuff.&#160; </p>
<p>I’m writing a very basic WebPart to get started with SharePoint – this web part will display a list of links to other applications that the user is authorized to use.&#160; The source of this data (names, URLs, etc.) comes from an external-to-SharePoint system, accessed through another C# assembly.&#160; Once the web part gets the data there is some more processing to be done – we need to do more than just blindly display a list of URLs.&#160; Rather than get into details I’m just going to do some handwaving here and say that “if you have access to X, then {stuff happens}, or if you have access to Y then {other stuff happens}.”&#160; You know, business logic, stuff that is good to test.</p>
<p>the first thing I need to do is get business logic out of the WebPart and into something that I can write without having to reset AppPools over and over, not to mention have some unit tests to verify I’m going in the right direction.&#160; So, I created a standard application service class which has a dependency on the external authorization system, via constructor injection.&#160; </p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> AuthorizedAppsService : IAuthorizedAppsService
{
  <span class="kwrd">private</span> <span class="kwrd">readonly</span> ExternalAuthorizeService authService;

  <span class="kwrd">public</span> AuthorizedAppsService(
    ExternalAuthorizeService authService)
  {
    <span class="kwrd">this</span>.authService = authService;
  }

  <span class="kwrd">public</span> AuthorizedApplications GetAuthorizedApplications(
                                  <span class="kwrd">string</span> userName)
  {
    var allApps = authService.AuthorizedApplications(userName);
    <span class="rem">// business logic stuff happens here</span>
    <span class="kwrd">return</span> thoseResultsWeJustFiguredOut;
  }
}</pre>
<p>Next, I created a StructureMap Registry class to scan my assemblies, as well as adding in the details of how to create this external authorize service, using the typical method:<br />
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: x-small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyRegistry : Registry
{
  <span class="kwrd">public</span> MyRegistry()
  {
    Scan(scanner =&gt; {
      scanner.TheCallingAssembly();
      scanner.AssemblyContainingType(<span class="kwrd">typeof</span>(MyRegistry));
      scanner.WithDefaultConventions();
      });

    ForRequestedType&lt;ExternalAuthorizeService&gt;()
      .AsSingletons()
      .TheDefault.Is.ConstructedBy(c =&gt; Provider.GetService());

    <span class="rem">// other dependency configuration...</span>
  }
  <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> InitializeForSharepoint()
  {
    ObjectFactory.Initialize(init =&gt; init.AddRegistry&lt;MyRegistry&gt;());
    ObjectFactory.AssertConfigurationIsValid();
  }
}</pre>
<p>And then, what remains is to have SharePoint call my StructureMap initialization when my SharePoint application starts up.&#160; In an MVC or WebForms app, I’d just add code to the appropriate place in Global.asax.cs, but in SharePointLand, this is looked down on.&#160; Instead, the preferred mechanism seems to be to use an HttpModule and a FeatureReceiver to plug the Module into the app’s web.config.</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyStartupModule : IHttpModule
{
  <span class="kwrd">public</span> <span class="kwrd">void</span> Init(HttpApplication context)
  {
        ConfigureOtherStuff();
        MyRegistry.InitializeForSharepoint();
  }
  <span class="kwrd">public</span> <span class="kwrd">void</span> Dispose() { }
}</pre>
<p>And then the FeatureReceiver to alter the app’s Web.Config looks something like this (note I borrowed most of this code from another sample SharePoint project:</p>
<p>&#160;</p>
<pre class="csharpcode"><span class="rem">//</span>
<span class="rem">// this is borrowing heavily from http://www.codeplex.com/SPAXO</span>
<span class="rem">// </span>
<span class="kwrd">public</span> <span class="kwrd">class</span> StartupFeatureReceiver : SPFeatureReceiver
{
  <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> FeatureActivated(
        SPFeatureReceiverProperties properties)
  {
    var webApp = properties.Feature.Parent <span class="kwrd">as</span> SPWebApplication;
    AddWebConfigEntry(webApp);
    UpdateApp(webApp);
  }

  <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> FeatureDeactivating(
        SPFeatureReceiverProperties properties)
  {
    var webApp = properties.Feature.Parent <span class="kwrd">as</span> SPWebApplication;
    RemoveWebConfigEntry(webApp);
    UpdateApp(webApp);
  }

  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> AddWebConfigEntry(SPWebApplication webApp)
  {
    SPWebConfigModification mod = GetModification();
    var existingModifications =
             <span class="kwrd">new</span> List&lt;SPWebConfigModification&gt;(
                      webApp.WebConfigModifications);
    <span class="kwrd">if</span> (existingModifications.FindIndex(
                    <span class="kwrd">value</span> =&gt;
                        <span class="kwrd">value</span>.Name == mod.Name &amp;&amp;
                        <span class="kwrd">value</span>.Value == mod.Value &amp;&amp;
                        <span class="kwrd">value</span>.Owner == mod.Owner) == -1)
    {
      <span class="rem">// If the modifcation does not already exist </span>
      <span class="rem">// add the entry to the config</span>
      webApp.WebConfigModifications.Add(mod);
    }
  }

  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> RemoveWebConfigEntry(
            SPWebApplication webApp)
  {
    SPWebConfigModification mod = GetModification();
    webApp.WebConfigModifications.Remove(mod);
  }

  <span class="kwrd">private</span> <span class="kwrd">static</span> SPWebConfigModification GetModification()
  {
    <span class="kwrd">string</span> asmName = <span class="kwrd">typeof</span>(StartupModule).AssemblyQualifiedName;
    <span class="kwrd">string</span> typeName = <span class="kwrd">typeof</span>(StartupModule).FullName;

    <span class="kwrd">return</span> <span class="kwrd">new</span> SPWebConfigModification
      {
        Path = <span class="str">&quot;configuration/system.web/httpModules&quot;</span>,
        Name = String.Format(CultureInfo.InvariantCulture,
                <span class="str">&quot;add[@name='{0}'][@type='{1}']&quot;</span>,
                typeName, asmName),
        Sequence = 0,
        Owner = asmName,
        Type = SPWebConfigModification.
                    SPWebConfigModificationType.EnsureChildNode,
        Value = String.Format(CultureInfo.InvariantCulture,
                  <span class="str">&quot;&lt;add name='{0}' type='{1}' /&gt;&quot;</span>,
                  typeName, asmName)
      };
  }

  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> UpdateApp(SPWebApplication webApp)
  {
    <span class="rem">// Update the Web App and apply the changes </span>
    <span class="rem">// to all servers in the farm</span>
    webApp.Update();
    webApp.Farm.Services
        .GetValue&lt;SPWebService&gt;()
        .ApplyWebConfigModifications();
  }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/09/structuremap-and-sharepoint/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Windows Server 2008 R2 is Windows 7 &#8220;Server&#8221;</title>
		<link>http://elegantcode.com/2009/10/02/windows-server-2008-r2-is-windows-7-server/</link>
		<comments>http://elegantcode.com/2009/10/02/windows-server-2008-r2-is-windows-7-server/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 15:53:15 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[w2k8]]></category>
		<category><![CDATA[win2k8R2]]></category>
		<category><![CDATA[win7]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/10/02/windows-server-2008-r2-is-windows-7-server/</guid>
		<description><![CDATA[Sometimes people get tripped up by this – at the least, its a little confusing.&#160; A brief history lesson:
First there was Windows Server 2003.&#160; And then in 2005, Microsoft released something of a super-service-pack with new functionality, patches, and other stuff.&#160; It was much more than a regular service pack, full of optional components that [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes people get tripped up by this – at the least, its a little confusing.&#160; A brief history lesson:</p>
<p>First there was Windows Server 2003.&#160; And then in 2005, Microsoft released something of a super-service-pack with new functionality, patches, and other stuff.&#160; It was much more than a regular service pack, full of optional components that shipped on a 2nd CD.&#160; So, it was name “Windows Server 2003 R2.”&#160; But underneath, it’s still Windows Server 2003 at the core.</p>
<p>You might think that Windows Server 2008 R2 follows the same naming convention.&#160; But you’d be wrong.</p>
<p>Windows Server 2008 R2 is not “Windows Server 2008 + More Good Stuff,” it’s actually much more like “Windows 7 – Server Edition.”&#160; The core is a different (though of course related) operating system.&#160; </p>
<p>Why did Microsoft do this?&#160; I’m sure they have good reasons… investment in the Windows 2008 ‘brand,’ major/minor naming schedules, and so on.&#160; </p>
<p>I’m sure that Windows 2008 R2 is a wonderful operating system.&#160; Windows 7 seems pretty nice, after all.&#160; But, don’t be fooled by the name and think that upgrading from Windows 2008 to Windows 2008 R2 is no big deal, its a full blown OS upgrade.&#160; </p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/10/02/windows-server-2008-r2-is-windows-7-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cooking Bacon, Part 2</title>
		<link>http://elegantcode.com/2009/08/24/cooking-bacon-part-2/</link>
		<comments>http://elegantcode.com/2009/08/24/cooking-bacon-part-2/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 04:24:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/24/cooking-bacon-part-2/</guid>
		<description><![CDATA[“The taste of Bacon is the taste of Freedom.”    &#160; &#8212; unknown 
I hope you read that in Leonard Nimoy’s voice, from his work on Civilization IV.&#160; “Our scientists have unlocked the secrets of Bacon!&#160; Now we can cook bacon!”
So after attempting to cook bacon in carbon dioxide, the next logical step [...]]]></description>
			<content:encoded><![CDATA[<p><em>“The taste of Bacon is the taste of Freedom.”</em>    <br />&#160; &#8212; unknown </p>
<p>I hope you read that in <a href="http://www.youtube.com/watch?v=XZlWmYe8HM4&amp;feature=player_embedded" target="_blank">Leonard Nimoy’s</a> voice, from his work on Civilization IV.&#160; “Our scientists have unlocked the secrets of Bacon!&#160; Now we can cook bacon!”</p>
<p>So after attempting to <a href="http://elegantcode.com/2009/08/22/cooking-bacon-part-1/">cook bacon in carbon dioxide</a>, the next logical step was to repeat the experiment in a vacuum.&#160; Would the absence of an atmosphere (more or less) alter the taste of bacon?&#160; If this worked, this could be another alternative to having robots cook bacon unattended without the risk of fire.</p>
<p>Fortunately Dave Gapen over at <a href="http://www.reuseum.com/" target="_blank">The Reuseum</a> happened to have a working vacuum chamber, and was willing to let us experiment with it as long as we cleaned up the mess afterwards.&#160; </p>
<p>The plan was simple: insert Foreman grill into chamber.&#160; Remove air via a hand pump.&#160; Cook bacon.&#160; Eat bacon.</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0498.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="What a Vacuum Chamber Might Look Like" border="0" alt="What a Vacuum Chamber Might Look Like" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0498_thumb.jpg" width="184" height="244" /></a> <a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0495.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="The grill just barely fits.  Yay" border="0" alt="The grill just barely fits.  Yay" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0495_thumb.jpg" width="184" height="244" /></a> </p>
<p>First thing: the chamber has holes for connecting pumps and other handy scientific devices, one of which we need to run the grill power cord through.&#160; And then manage to seal up the remains of the whole.&#160; And to do that, the power cord needs to come off the grill, be threaded through mentioned hole, and then seal the hole up with copious amounts of silicone caulk.</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0497.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Preparing the Chamber" border="0" alt="Preparing the Chamber" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0497_thumb.jpg" width="184" height="244" /></a> <a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0501.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Power Goes Here" border="0" alt="Power Goes Here" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0501_thumb.jpg" width="184" height="244" /></a> <a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0499.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Removing Power Cord" border="0" alt="Removing Power Cord" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0499_thumb.jpg" width="184" height="244" /></a> </p>
</p>
</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0505.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="This is what SCIENCE looks like" border="0" alt="This is what SCIENCE looks like" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0505_thumb.jpg" width="184" height="244" /></a> </p>
<p>With the box wired for sound, and some time to kill waiting for our sealant to hold, it was time to cook the Control Bacon.&#160; One comment with the previous attempt was that the grill was colder cooking the CO2 bacon than the control bacon, which could explain the lack of crispiness.&#160; So this time, we allowed the grill to heat up for 2 minutes sans-bacon, and then cooked the control bacon first.</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0519.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Bacon in Open Container" border="0" alt="Bacon in Open Container" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0519_thumb.jpg" width="244" height="184" /></a> <a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0520.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Its MORE Bacon!" border="0" alt="Its MORE Bacon!" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0520_thumb.jpg" width="244" height="184" /></a> </p>
<p>The control bacon cooked for 15 minutes.&#160; It was good, as one expects from control bacon.&#160;&#160; Hail, Bacon!</p>
<p>Control bacon eaten, now it’s time to set up our vacuum.&#160; Uncooked bacon was placed on the grill, the chamber cover was placed and sealed, and I started using the hand pump to get as much air out of the chamber as possible.</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0521.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="The Bacon Chamber" border="0" alt="The Bacon Chamber" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0521_thumb.jpg" width="244" height="184" /></a> <a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0523.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Bacon Chamber" border="0" alt="Bacon Chamber" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0523_thumb.jpg" width="244" height="184" /></a> </p>
<p>Here’s the part where things start to go wrong: cranking the hand pump is hard work, and I didn’t have access to (and sure wasn’t going to buy) a compressor or electric pump or something that would have been more efficient.&#160; I was able to get the gauge up to 200 mmHg and maintain it there, but getting more of a vacuum than that was a lot of work.&#160; And since it didn’t seem like this setup was going to get much better than that, I flipped the switch to apply power to the grill.&#160; Commence bacon!</p>
<p><a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0528.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Pump Gauge" border="0" alt="Pump Gauge" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0528_thumb.jpg" width="184" height="244" /></a> <a href="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0526.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Condensation" border="0" alt="Condensation" src="http://elegantcode.com/wp-content/uploads/2009/08/IMG_0526_thumb.jpg" width="244" height="184" /></a> </p>
<p>After 5 minutes, I could begin smelling the bacon cooking through the hand pump – along with a smell sort of like industrial grease.&#160; Not very pleasant.&#160; Would the bacon flavor be tainted?</p>
<p>I had to pump continuously to maintain pressure, at one point I was able to get the gauge up to 300 mmHg, but then the silicone seal developed an audible leak.&#160; </p>
<p>15 minutes elapse – vacuum bacon removed.&#160; It appeared to have suffered no side effects from its exposure to low pressure.&#160; The taste and other qualities of the bacon was as you’d expect from any other sort of bacon.&#160; Bacon is stronger than it’s environment.</p>
<h4>Results</h4>
<p>The gauge is measuring the pressure difference between the outside and the inside.&#160; STP is defined as 760 mmHg at room temperature.&#160; If we assume that the outside is STP (and we haven’t been very rigorous with numbers up to this point, so why start now?) then that’d mean that the pressure inside was 760 – 200 mmHg = 560 mmHg, or 0.74 atmospheres.&#160; Not the sort of vacuum I was hoping for…</p>
<p>The preheating and cooking order seems to have controlled for temperature, so that’s one less problem.&#160; If I were to repeat this experiment, I’d let the seals set overnight (at least) so we could get less pressure in there.&#160; Also, this really calls for a more powerful pump than what we had – unfortunately that just wasn’t going to happen with the time and money available.&#160; </p>
<p>But, it was an excellent excuse to eat more bacon, visit the Reuseum, and DO SCIENCE!</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/cooking-bacon-part-2/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
