<?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>Huddled Masses &#187; Forms</title>
	<atom:link href="http://huddledmasses.org/tag/forms/feed/" rel="self" type="application/rss+xml" />
	<link>http://huddledmasses.org</link>
	<description>You can do more than breathe for free...</description>
	<lastBuildDate>Sat, 28 Jan 2012 21:37:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<cloud domain='huddledmasses.org' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>WPF From PowerShell &#8211; Select-Grid</title>
		<link>http://huddledmasses.org/wpf-from-powershell-select-grid/</link>
		<comments>http://huddledmasses.org/wpf-from-powershell-select-grid/#comments</comments>
		<pubDate>Tue, 20 May 2008 21:09:30 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Forms]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/?p=537</guid>
		<description><![CDATA[After looking over the scripts I&#8217;ve pasted in the last few days it struck me that all of them load the UI from XAML &#8212; and for the most part, you can do pretty much whatever you need to do in WPF in pure PowerShell if you want to. To demonstrate this, I wrote a [...]]]></description>
			<content:encoded><![CDATA[	<p>After looking over the scripts I&#8217;ve pasted in the last few days it struck me that all of them load the UI from <span class="caps">XAML</span> &#8212; and for the most part, you can do pretty much whatever you need to do in <span class="caps">WPF</span> in pure PowerShell if you want to.</p>

	<p><a href='http://HuddledMasses.org/wpf-from-powershell-select-grid/select-grid-screenshot/'><img src="http://HuddledMasses.org/wordpress/wp-content/uploads/2008/05/select-grid-screenshot-mini.png" alt="Select-Grid Screenshot" title="select-grid-screenshot-mini" class="alignleft wp-image-542" style="float: left;"/></a>To demonstrate this, I wrote a simple Out-Grid script.  But then I got carried away, and wrote the script I&#8217;ve shown in this screenshot.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':-D' class='wp-smiley' />   The resulting script not only illustrates how to code <span class="caps">WPF</span> in PowerShell without <span class="caps">XAML</span>, it also illustrates one of the few areas where you&#8217;re much better off loading from <span class="caps">XAML</span> than writing the plain code &#8212; and that&#8217;s a DataTemplate. It <strong>is</strong> possible to write them in code, but believe it or not, some of their features are accessible only from <span class="caps">XAML</span>.</p>

	<p> <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[new]' class='wp-smiley' />  I&#8217;ve updated both the script and the screenshot to correct a bug I noticed last night after I posted this &#8230; so if you tried this and got a lot more columns than you had bargained for &#8230; here is the <a href='http://HuddledMasses.org/?attachment_id=539' rel='attachment wp-att-539'>Select-Grid script</a> again.   <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[new]' class='wp-smiley' />  I updated it <em>again</em> just now to switch my <code>Set-PsDebug</code> statement for a <code>Set-StrictMode</code> statement, after reading Jeffrey Snover&#8217;s post about <a href="http://blogs.msdn.com/powershell/archive/2008/05/21/strict-mode.aspx">strict mode best practices</a>.</p>

	<p>I&#8217;m not going to paste the <em>whole</em> script in-line, but I thought I&#8217;d paste some of it here so that I could give a little explanation of what&#8217;s happening, in case you need a little help figuring it out&#8230;</p>

	<h3>Using modules &#8230;</h3>

	<p>Some of you may know that normally in a script like this we would put the &#8220;utility&#8221; functions inside the <code>BEGIN</code> block so-as to encapsulate them from your main runspace, and may be wondering why I didn&#8217;t in this case.  It&#8217;s because the new CTP2 of PowerShell has this concept called a &#8220;module&#8221; ... which is somewhat like a script snapin &#8212; basically it allows you to have functions in the script which don&#8217;t end up in the main runspace, but which are still available to the other functions (or cmdlets, in this case) in the script.  </p>

	<p>I will write a separate post about how <a href="/powershell-modules/">PowerShell Modules</a> work, and what you can do with them &#8230; it&#8217;s too complicated to get into here.  Suffice it to say that all I had to do to the script is add a line at the bottom: <code>Export-ModuleMember Select-Grid</code> and rename it to  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[new]' class='wp-smiley' />  <a href='http://HuddledMasses.org/wpf-from-powershell-select-grid/select-grid-2/' rel='attachment wp-att-544'>Select-Grid.psm1</a> and put it in a specific location: Documents\WindowsPowerShell\Packages\Select-Grid\Select-Grid.psm1  &#8212; but of course, I couldn&#8217;t resist cleaning it up a bit as I was writing about it (if you grabbed it before v3.4, you should grab it again &#8212; look in the comment at the top).</p>

	<p>Having done that, all you have to do is run <code>Add-Module Select-Grid</code> instead of dot-sourcing it, and then run it as before (see <a href="http://HuddledMasses.org/wordpress/wp-content/uploads/2008/05/select-grid-screenshot.png">the screenshot</a>).</p>

	<h3>Let&#8217;s talk about <em>code</em> bay-bee &#8230;</h3>

	<p>There&#8217;s a few things I wanted to point out in the module&#8217;s code, so lets get to that.<span id="more-537"></span>  The first thing is that the main code is in a cmdlet, rather than a function &#8212; mostly because the cmdlet automatically handles both command arguments and pipeline arguments and allows me to handle them both the same way.  Since I want to handle all of the input at once, my <code>BEGIN</code> and <code>PROCESS</code> blocks are basically empty, serving only to collect the inputs.</p>

	<p>One caveat I will point out: The <span class="caps">CTP</span> has a problem where it strips the <acronym title="Extended Type System">ETS</acronym> attributes from things when you specify the type. So if you write a cmdlet with a parameter types like <code>[System.IO.FileSystemInfo]</code>, and then add data to them with Add-Member, that data won&#8217;t show up in the script cmdlet.  Hopefully this will be considered an <a href="https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=345387&#38;SiteID=99">important bug</a> and will be fixed in the next CTP/Beta.  The workaround in the meantime is to just use <code>[PSObject]</code> when you want to get the <span class="caps">ETS</span> attributes.</p>

	<p>So, lets review the important bits of this &#8230;</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$window</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #003366;">Window</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">SizeToContent</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;WidthAndHeight&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">SnapsToDevicePixels</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$true</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Content</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #003366;">Controls</span>.<span style="color: #003366;">ListView</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Title</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Title</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Title</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Title</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$outputObjects</span><span style="color: #333;">&#91;</span><span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">GetType</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span>.<span style="color: #003366;">Name</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">### The ListView takes ViewBase object which controls the layout and appearance</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">### We'll use a GridView</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Content</span>.<span style="color: #003366;">View</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #003366;">Controls</span>.<span style="color: #003366;">GridView</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Content</span>.<span style="color: #003366;">View</span>.<span style="color: #003366;">AllowsColumnReorder</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$true</span></div>

	<p>This constructs the window, and the only things I&#8217;ll point out here is that I used SizeToContent so that the window would automatically adjust it&#8217;s size, and I put the ListView and GridView directly into their containers, instead of assigning them to variables first.  It might help you to have a <code>$grid</code> or a <code>$list</code> variable to work with in the rest of the code (eg: instead of <code>$window.Content.View = new...GridView</code>, you&#8217;d be doing <code>$list.View = $grid</code>), but since this is PowerShell and not C#, I don&#8217;t end up having to <em>manually</em> cast things to use their specific properties, so this actually keeps my code cleaner.  In C# this would be a mess, because the <code>View</code> property is only a property of a ListView type, so you would have to cast the <code>$Window.Content</code> to a ListView in order to use that property, and then &#8230; well, lets just say the last line of that code would end up something like this (assuming you were <strong>using</strong> the namespaces and didn&#8217;t have to type them out):</p>

	<div class="csharp code csharp" style="font-family:monospace;"><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span>GridView<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span>ListView<span style="color: #000000;">&#41;</span>window.<span style="color: #0000FF;">Content</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">View</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">AllowsColumnReorder</span> <span style="color: #008000;">=</span> <span style="color: #0600FF;">true</span></div>

	<p>The next interesting feature of this code (at least, in my opinion) is the <code>Get-PropertyTypes</code> function &#8212; I won&#8217;t elaborate much here, but the purpose of this code is to get a hash of the property <em>names</em> and <em>types</em> when the user specifies a list of properties to show.  The main reason I did this that I was having problems sorting columns with missing values, so I go through the values and add a NoteProperty with an appropriate default (for which I need to know the variable&#8217;s type).</p>

	<p>We then construct columns for each property we want to bind to.  This could be drastically simplified if we didn&#8217;t need the sorting, but since we do, it looks like this:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Name</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$Properties</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## For each property, make a column &nbsp; &nbsp; &nbsp; &nbsp; </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$gvc</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #003366;">Controls</span>.<span style="color: #003366;">GridViewColumn</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## And bind the data ... </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$gvc</span>.<span style="color: #003366;">DisplayMemberBinding</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #666699; font-weight: bold;">Data</span>.<span style="color: #003366;">Binding</span> <span style="color: #660033; font-weight: bold;">$Name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## In order to add sorting, we need to create the header ourselves</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$gvc</span>.<span style="color: #003366;">Header</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #003366;">Controls</span>.<span style="color: #003366;">GridViewColumnHeader</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$gvc</span>.<span style="color: #003366;">Header</span>.<span style="color: #003366;">Content</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">##</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Add a click handler to enable sorting ...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$gvc</span>.<span style="color: #003366;">Header</span>.<span style="color: #003366;">add_click</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$view</span> <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>System.<span style="color: #003366;">Windows</span>.<span style="color: #666699; font-weight: bold;">Data</span>.<span style="color: #003366;">CollectionViewSource</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">GetDefaultView</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$outputObjects</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$view</span>.<span style="color: #003366;">SortDescriptions</span>.<span style="color: #660033;">Clear</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$view</span>.<span style="color: #003366;">SortDescriptions</span>.<span style="color: #003366;">Add</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">SortDescription</span></span> <span style="color: #660033; font-weight: bold;">$this</span>.<span style="color: #003366;">Content</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$view</span>.<span style="color: #003366;">Refresh</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Use that column in the view</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Content</span>.<span style="color: #003366;">View</span>.<span style="color: #003366;">Columns</span>.<span style="color: #003366;">Add</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$gvc</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>That block only has one thing worth mentioning that might not be clear from the comments: to avoid double-sorting the data, we have to <code>Clear()</code> the SortDescriptions before we add a new one (otherwise it sorts when we add, and then sorts again when we remove the old SortDescription). Since we need to know the <em>direction</em> that the current sort is in, I refactored it into a module-level variable, and wrote a <code>New-SortDescription</code> function which creates the SortDescription based on that &#8230; allowing me to clear without first capturing the current sort direction, and then add the SortDescription straight to the GridView.  Script modules rock &#8212; they are essentially a &#8220;class&#8221; semantic for PowerShell, with private member variables and everything.</p>

	<p>The last thing I should write about is the CellTemplate magic.  If you pass a <code>Graph</code> parameter to the cmdlet, it puts a custom CellTemplate on each column you name. If you specified the <code>Properties</code> parameter, you have to be careful to only specify column names which you also included there, and in general, they have to be numeric columns in order for this to work.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$obj</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$outputObjects</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">Member</span></span> NoteProperty <span style="color: #009900;">&quot;$($property)Percent&quot;</span> <span style="color: #333;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #333;">&#40;</span>$<span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$obj</span>.$<span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$property</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-as</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">double</span><span style="color: #333;">&#93;</span></span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">/</span> $<span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$max</span>.<span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$property</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-input</span> <span style="color: #660033; font-weight: bold;">$obj</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$column</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$gridview</span>.<span style="color: #003366;">Columns</span> <span style="color: #66cc66;">|</span> ? <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Header</span>.<span style="color: #003366;">Content</span> <span style="color: #000066;">-eq</span> <span style="color: #660033; font-weight: bold;">$property</span> <span style="color: #333;">&#125;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## dump the binding and use a template instead... (this shouldn't be necessary)...</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$column</span>.<span style="color: #003366;">DisplayMemberBinding</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$null</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$column</span>.<span style="color: #003366;">CellTemplate</span> <span style="color: #66cc66;">=</span> `<br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Windows.<span style="color: #003366;">Markup</span>.<span style="color: #003366;">XamlReader</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">Load</span><span style="color: #333;">&#40;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366; font-weight: bold;">Xml</span>.<span style="color: #003366;">XmlNodeReader</span> <span style="color: #333;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">Xml</span><span style="color: #333;">&#93;</span></span><span style="color: #009900;">&quot;&lt;DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;Grid&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Rectangle Margin='-6,0' VerticalAlignment='Stretch' RenderTransformOrigin='0,1' &gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;Rectangle.Fill&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;LinearGradientBrush StartPoint='0,0' EndPoint='1,0'&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;GradientStop Color='#FFFF4500' Offset='0' /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;GradientStop Color='#FFFF8585' Offset='1' /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/LinearGradientBrush&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/Rectangle.Fill&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;Rectangle.RenderTransform&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;ScaleTransform ScaleX='{Binding $($property)Percent}' ScaleY='1' /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/Rectangle.RenderTransform&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/Rectangle&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;TextBlock Width='100' Margin='-6,0' TextAlignment='Right' Text='{Binding $property}' /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/Grid&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/DataTemplate&gt;&quot;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span></div>

	<p>There&#8217;s really only three lines of code here (not counting the Xaml), so lets review them. First we add a &#8220;PropertyPercent&#8221; NoteProperty to each output object for each &#8220;Property&#8221; that we want to graph, and populate it with the appropriate value.  Then, we find the appropriate column in the GridView that we&#8217;ve already set up &#8212; and remove it&#8217;s DisplayMemberBinding.  If we don&#8217;t remove the binding, the CellTemplate has no effect.</p>

	<p>Finally, we add the CellTemplate.  The magic is that the cell template has a colored <code>Rectangle</code> behind a <code>TextBlock</code>, and uses a <code>ScaleTransform</code> &#8212; bound to the &#8220;PropertyPercent&#8221; NoteProperty we created earlier &#8212; to scale the width of the Rectangle.  I can&#8217;t stress enough that this is just one of hundreds of possible visualizations you could use, so let me give you a few ideas, and then you should go find a friend that&#8217;s an artist or a designer and get them to spend some time playing with Expression Blend &#8230;</p>

	<ol>
		<li>You could have a DataTransform that converted numbers to colors, and bind the TextBlock&#8217;s <code>BackgroundBrush</code> to that so each cell is simply colored differently (eg: to color cells from red to blue based on a temperature value).</li>
		<li>You could databind the FontSize of a TextBlock based on a numeric value in a non-displayed property, so you could show words with relative size (like a &#8220;Tag Cloud&#8221;).</li>
	</ol>
	<ol>
		<li>You could databind the Angle property of the RotateTransform on a pair of lines or shapes to create an analog clock to display times</li>
	</ol>

	<p>So many possibilities &#8230;</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/wpf-from-powershell-select-grid/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>WPF From PowerShell &#8211; Something Useful</title>
		<link>http://huddledmasses.org/wpf-from-powershell-something-useful/</link>
		<comments>http://huddledmasses.org/wpf-from-powershell-something-useful/#comments</comments>
		<pubDate>Wed, 14 May 2008 18:37:57 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Forms]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/?p=530</guid>
		<description><![CDATA[After posting my last post, I started thinking that perhaps I shouldn&#8217;t really have started with something so splashy . So I started thinking about what I could use as a proper example &#8212; not of what WPF can do, but of what you might want to use WPF for in PowerShell. I came up [...]]]></description>
			<content:encoded><![CDATA[	<p>After posting <a href="/wpf-from-powershell-updating-windows/">my last post</a>, I started thinking that perhaps I shouldn&#8217;t really have started with something so splashy  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[rolleyes]' class='wp-smiley' /> .  So I started thinking about what I could use as a proper example &#8212; not of what <span class="caps">WPF</span> can do, but of what you might want to use <span class="caps">WPF</span> for in PowerShell.</p>

	<p>I came up with two really obvious ideas which I think are both good demonstrations of useful things to do from PowerShell, and are good examples of something that really just doesn&#8217;t work with WinForms.</p>

	<h3>User Input prompts</h3>

	<p>I&#8217;ll write more about this in future posts, but for now, take as an ultimate example the <a href="http://thepowershellguy.com/blogs/posh/archive/2008/05/13/powershell-wmi-exporer-wpf-edition.aspx">latest post from mow, The PowerShell Guy</a> in which he rewrites his PowerShell <a href="http://thepowershellguy.com/blogs/posh/archive/tags/WMI+Explorer/"><span class="caps">WMI</span> Explorer</a> to be <span class="caps">WPF</span> based &#8212; it seems to not only run faster, but be based on less code (of course, that might just be because he&#8217;s gained experience since the first version).</p>

	<h3>Data-bound Graphs</h3>

	<p><a href='http://HuddledMasses.org/wpf-from-powershell-something-useful/out-bargraph/' rel="attachment wp-att-531"><img src="http://HuddledMasses.org/wordpress/wp-content/uploads/2008/05/out-bargraph.png" alt="A WPF databound bar graph dialog from PowerShell" title="out-bargraph" class="alignleft size-thumbnail wp-image-531" style="float:left; width:400px;" /></a>There are dozens of ways you can do data-bound graphs in PowerShell &#8212; including 3d &#8212; but the simplest to demonstrate (and coincidentally the easiest for me to come up with a use-case for) is a plain bar graph.  I&#8217;ve written a <a href='http://HuddledMasses.org/wpf-from-powershell-something-useful/graph/' rel='attachment wp-att-533'>simple graph window in XAML</a>, and created a script <a href='http://HuddledMasses.org/wordpress/wp-content/uploads/2008/05/out-bargraph.ps1'><code>Out-BarGraph</code></a> which lets you send data to it &#8230; but there are, as the Genie says, some caveats, provisos, addendums, and quid pro quos.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' />  <span id="more-530"></span></p>

	<p>The main catch is that you <strong>have</strong> to specify the ScriptBlock parameters so that the script can figure out which properties to use as the Labels and Values &#8212; the purpose of this script is not to provide the most efficient way to bind PowerShell data to <span class="caps">WPF</span>, but rather to bind the data in a way that is easily translatable to new data types &#8212; because of this, you can use the script with file sizes, web traffic logs, performance monitor data, etc.</p>

	<p>The second catch is that we export the data to a temp file. In order to make it easy to handle multiple data-types, the <span class="caps">WPF</span> actually databinds to <span class="caps">XML</span> which we create by using PowerShell&#8217;s built in <code>Export-CliXml</code> cmdlet. The only constraint that whatever is exported must have three specific properties (Label, Value, Percentage) which the <code>Out-GraphableXml</code> function in the script calculates using script blocks you provide. I chose to do this so that you could see that you could create the xml from anywhere easily &#8230; but <em>you</em> could choose to databind to actual objects instead.</p>

	<p>Finally, there are a few additional constraints. This bar graph doesn&#8217;t update itself &#8212; it&#8217;s just a static graph of a given set of data.  It can&#8217;t represent negative numbers.  You <strong>must</strong> provide the <em>percentage</em> attribute as a number between 0 and 1 (again, in my example script the <code>Out-GraphableXml</code> function in the script calculates the percent based on the largest value).</p>

	<h4>The Script</h4>

	<p>Having laid out the shortcomings of the script, let me present it to you here in full glory.  Unlike the downloadable version linked above, this script includes the <span class="caps">XAML</span> source in-line as a <code>Data</code> block, so the entire script and UI code are in a single file.  Scroll to the end of the script for some explanations&#8230;</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;">#requires -version 2</span><br />
<span style="color: #666666; font-style: italic;">## Out-BarGraph.ps1</span><br />
<span style="color: #666666; font-style: italic;">## A script to generate WPF bargraphs using XAML</span><br />
<span style="color: #666666; font-style: italic;">## REQUIRES graph.xaml ( included here as a DATA section )</span><br />
<span style="color: #666666; font-style: italic;">########################################################################################################################</span><br />
<span style="color: #666666; font-style: italic;">## Example Usage</span><br />
<span style="color: #666666; font-style: italic;">## ls | Out-BarGraph &quot;File Sizes in Bytes&quot; -Label {$_.Name} -Value {$_.Length}</span><br />
<span style="color: #666666; font-style: italic;">########################################################################################################################</span><br />
<span style="color: #666666; font-style: italic;">## Version History</span><br />
<span style="color: #666666; font-style: italic;">## 1.4 &nbsp; - Embedded XAML in script</span><br />
<span style="color: #666666; font-style: italic;">## 1.3 &nbsp; - Added [scriptblock] parameters, removing need for data to be a custom psobject</span><br />
<span style="color: #666666; font-style: italic;">## 1.2 &nbsp; - Wrapper script now sets all values</span><br />
<span style="color: #666666; font-style: italic;">## 1.1.3 - Added data-bound &quot;scale&quot; labels</span><br />
<span style="color: #666666; font-style: italic;">## 1.1.2 - Added data-bound caption</span><br />
<span style="color: #666666; font-style: italic;">## 1.1.1 - Added data-bound labels</span><br />
<span style="color: #666666; font-style: italic;">## 1.1 &nbsp; - Got data-binding to the graph working</span><br />
<span style="color: #666666; font-style: italic;">## 1.0 &nbsp; - First working version, no live data binding</span><br />
<span style="color: #666666; font-style: italic;">########################################################################################################################</span><br />
<br />
<span style="color: #666699; font-weight: bold;">Param</span><span style="color: #333;">&#40;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$caption</span><span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;A bar-graph from WPF&quot;</span>, <br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$data</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span>, <br />
&nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">scriptblock</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Label</span> <span style="color: #66cc66;">=</span> $<span style="color: #333;">&#40;</span><span style="color: #666699; font-weight: bold;">Throw</span> <span style="color: #009900;">&quot;You must specify the 'Label' scriptblock&quot;</span><span style="color: #333;">&#41;</span>,<br />
&nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">scriptblock</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Value</span> <span style="color: #66cc66;">=</span> $<span style="color: #333;">&#40;</span><span style="color: #666699; font-weight: bold;">Throw</span> <span style="color: #009900;">&quot;You must specify the 'Value' scriptblock&quot;</span><span style="color: #333;">&#41;</span>,<br />
&nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$sideways</span><br />
<span style="color: #333;">&#41;</span><br />
<span style="color: #666699; font-weight: bold;">BEGIN</span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666699; font-weight: bold;">DATA</span> XAML <span style="color: #333;">&#123;</span><br />
@<span style="color: #009900;">&quot;&lt;Window &nbsp;xmlns=&quot;</span>http:<span style="color: #66cc66;">//</span>schemas.<span style="color: #003366;">microsoft</span>.<span style="color: #003366;">com</span><span style="color: #66cc66;">/</span>winfx<span style="color: #66cc66;">/</span><span style="color: #cc66cc;">2006</span><span style="color: #66cc66;">/</span>xaml<span style="color: #66cc66;">/</span>presentation<span style="color: #009900;">&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns:x=&quot;</span>http:<span style="color: #66cc66;">//</span>schemas.<span style="color: #003366;">microsoft</span>.<span style="color: #003366;">com</span><span style="color: #66cc66;">/</span>winfx<span style="color: #66cc66;">/</span><span style="color: #cc66cc;">2006</span><span style="color: #66cc66;">/</span>xaml<span style="color: #009900;">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns:system=&quot;</span>clr<span style="color: #66cc66;">-</span>namespace:System;assembly<span style="color: #66cc66;">=</span>mscorlib<span style="color: #009900;">&quot; WindowStartupLocation='CenterScreen' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;WindowStyle=&quot;</span>ToolWindow<span style="color: #009900;">&quot; ShowInTaskbar='True' SizeToContent='Width' Height=&quot;</span><span style="color: #cc66cc;">400</span><span style="color: #009900;">&quot; Width=&quot;</span><span style="color: #cc66cc;">600</span><span style="color: #009900;">&quot;&gt;<br />
&nbsp; &nbsp;&lt;Window.Resources&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;system:String x:Key=&quot;</span>GraphCaption<span style="color: #009900;">&quot;&gt;-&lt;/system:String&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;RotateTransform x:Key=&quot;</span>Vertical<span style="color: #009900;">&quot; Angle=&quot;</span><span style="color: #66cc66;">-</span><span style="color: #cc66cc;">90</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;RotateTransform x:Key=&quot;</span>Sideways<span style="color: #009900;">&quot; Angle=&quot;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;XmlNamespaceMappingCollection x:Key=&quot;</span>PowerShellMappings<span style="color: #009900;">&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;XmlNamespaceMapping Uri=&quot;</span>http:<span style="color: #66cc66;">//</span>schemas.<span style="color: #003366;">microsoft</span>.<span style="color: #003366;">com</span><span style="color: #66cc66;">/</span><span style="color: #003366; font-weight: bold;">powershell</span><span style="color: #66cc66;">/</span><span style="color: #cc66cc;">2004</span><span style="color: #66cc66;">/</span>04<span style="color: #009900;">&quot; Prefix=&quot;</span><span style="color: #660033;">ps</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;/XmlNamespaceMappingCollection&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;XmlDataProvider x:Key=&quot;</span><span style="color: #666699; font-weight: bold;">Data</span><span style="color: #009900;">&quot; XPath=&quot;</span><span style="color: #66cc66;">/</span><span style="color: #660033;">ps</span>:Objs<span style="color: #66cc66;">/</span><span style="color: #660033;">ps</span>:Obj<span style="color: #009900;">&quot; XmlNamespaceManager=&quot;</span><span style="color: #333;">&#123;</span>StaticResource PowerShellMappings<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Source=&quot;</span>C:\Users\JBennett\Documents\WindowsPowerShell\Scripts\Demo\<span style="color: #666699; font-weight: bold;">data</span>.<span style="color: #003366; font-weight: bold;">xml</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;XmlDataProvider x:Key=&quot;</span>scale<span style="color: #009900;">&quot; XPath=&quot;</span><span style="color: #66cc66;">/</span>scale<span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;DataTemplate x:Key=&quot;</span>SeriesLabels<span style="color: #009900;">&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Height=&quot;</span><span style="color: #cc66cc;">28</span><span style="color: #009900;">&quot; Margin=&quot;</span><span style="color: #cc66cc;">5</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span><span style="color: #009900;">&quot; HorizontalContentAlignment=&quot;</span>Right<span style="color: #009900;">&quot; LayoutTransform=&quot;</span><span style="color: #333;">&#123;</span>StaticResource Vertical<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding &nbsp;XPath<span style="color: #66cc66;">=*/*</span><span style="color: #333;">&#91;</span>@N\<span style="color: #66cc66;">=</span>\<span style="color: #009900;">'Label\'</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;/DataTemplate&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;DataTemplate x:Key=&quot;</span>bars<span style="color: #009900;">&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Rectangle Width=&quot;</span><span style="color: #cc66cc;">28</span><span style="color: #009900;">&quot; Margin=&quot;</span><span style="color: #cc66cc;">5</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span><span style="color: #009900;">&quot; Fill=&quot;</span>Red<span style="color: #009900;">&quot; RenderTransformOrigin=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">1</span><span style="color: #009900;">&quot; ToolTip=&quot;</span><span style="color: #333;">&#123;</span>Binding XPath<span style="color: #66cc66;">=*/*</span><span style="color: #333;">&#91;</span>@N\<span style="color: #66cc66;">=</span>\<span style="color: #009900;">'Value\'</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#125;</span><span style="color: #009900;">&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;Rectangle.RenderTransform&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;ScaleTransform x:Name=&quot;</span>Scaler<span style="color: #009900;">&quot; ScaleX=&quot;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&quot; ScaleY=&quot;</span><span style="color: #333;">&#123;</span>Binding XPath<span style="color: #66cc66;">=*/*</span><span style="color: #333;">&#91;</span>@N\<span style="color: #66cc66;">=</span>\<span style="color: #009900;">'Percent\'</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/Rectangle.RenderTransform&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/Rectangle&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;/DataTemplate&gt;<br />
&nbsp; &nbsp;&lt;/Window.Resources&gt;<br />
&lt;DockPanel Margin=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&quot;&gt;<br />
&lt;Label DockPanel.Dock=&quot;</span>Top<span style="color: #009900;">&quot; HorizontalAlignment=&quot;</span>Center<span style="color: #009900;">&quot; FontFamily=&quot;</span>Garamond<span style="color: #009900;">&quot; FontSize=&quot;</span><span style="color: #cc66cc;">20</span><span style="color: #009900;">&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp;Content=&quot;</span><span style="color: #333;">&#123;</span>DynamicResource GraphCaption<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;Grid LayoutTransform=&quot;</span><span style="color: #333;">&#123;</span>DynamicResource Sideways<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; Name=&quot;</span>Graph<span style="color: #009900;">&quot; ShowGridLines=&quot;</span>True<span style="color: #009900;">&quot; &gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Grid.ColumnDefinitions&gt;&lt;ColumnDefinition Width=&quot;</span>Auto<span style="color: #009900;">&quot;/&gt;&lt;ColumnDefinition Width=&quot;</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;/Grid.ColumnDefinitions&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Grid.RowDefinitions&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">*</span><span style="color: #009900;">&quot;/&gt;&lt;RowDefinition Height=&quot;</span>Auto<span style="color: #009900;">&quot;/&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/Grid.RowDefinitions&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">5</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">5</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">6</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">6</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">7</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">7</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">8</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">8</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">9</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;Label Grid.Row=&quot;</span><span style="color: #cc66cc;">9</span><span style="color: #009900;">&quot; Padding=&quot;</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">&quot; Content=&quot;</span><span style="color: #333;">&#123;</span>Binding Source<span style="color: #66cc66;">=</span><span style="color: #333;">&#123;</span>StaticResource scale<span style="color: #333;">&#125;</span>, XPath<span style="color: #66cc66;">=//</span>Mark<span style="color: #333;">&#91;</span><span style="color: #cc66cc;">10</span><span style="color: #333;">&#93;</span><span style="color: #66cc66;">/</span>@Label<span style="color: #333;">&#125;</span><span style="color: #009900;">&quot;/&gt; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;ItemsControl Name=&quot;</span>Bars<span style="color: #009900;">&quot; Grid.RowSpan=&quot;</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&quot; Grid.Column=&quot;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&quot; Background=&quot;</span><span style="color: #666666; font-style: italic;">#FFD7F39F&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ItemsSource<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;{Binding Source={StaticResource Data}}&quot;</span> ItemTemplate<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;{StaticResource bars}&quot;</span> <span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;</span>ItemsControl.<span style="color: #003366;">ItemsPanel</span><span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>ItemsPanelTemplate<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;</span>StackPanel Orientation<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;Horizontal&quot;</span><span style="color: #66cc66;">/&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;/</span>ItemsPanelTemplate<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;/</span>ItemsControl.<span style="color: #003366;">ItemsPanel</span><span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;/</span>ItemsControl<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;</span>ItemsControl Name<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;SeriesLabels&quot;</span> Grid.<span style="color: #003366;">Column</span><span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;1&quot;</span> Grid.<span style="color: #003366;">Row</span><span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;11&quot;</span> Margin<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;0,0,0,0&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ItemsSource<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;{Binding Source={StaticResource Data}}&quot;</span> ItemTemplate<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;{StaticResource SeriesLabels}&quot;</span> <span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>ItemsControl.<span style="color: #003366;">ItemsPanel</span><span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;</span>ItemsPanelTemplate<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>StackPanel Orientation<span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;Horizontal&quot;</span><span style="color: #66cc66;">/&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;/</span>ItemsPanelTemplate<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;/</span>ItemsControl.<span style="color: #003366;">ItemsPanel</span><span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;/</span>ItemsControl<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;/</span>Grid<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp;<span style="color: #66cc66;">&lt;/</span>DockPanel<span style="color: #66cc66;">&gt;</span><br />
<span style="color: #66cc66;">&lt;/</span>Window<span style="color: #66cc66;">&gt;</span><br />
<span style="color: #009900;">&quot;@<br />
}<br />
&nbsp; &nbsp;function Out-GraphableXml ($data, [ref]$max, [scriptblock]$Label, [scriptblock]$Value) {<br />
&nbsp; &nbsp; &nbsp; ### Get a &quot;</span>Max<span style="color: #009900;">&quot; number which should be the next big round number (eg: 5,10,50,100,150 ...)<br />
&nbsp; &nbsp; &nbsp; $max.Value = ($data | Sort-Object {&amp;$Value -as [double]} -Desc | Select-Object @{n=&quot;</span>Value<span style="color: #009900;">&quot;;e=$Value} -First 1).Value -as [double]<br />
&nbsp; &nbsp; &nbsp; if( $max.Value -gt 1 ) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$siz = [Math]::Pow( 10, [Math]::Truncate($max.Value).ToString().Length -1 ) / 2<br />
&nbsp; &nbsp; &nbsp; } else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$siz = (.5 / (10 * ($max.Value.ToString().Length - 2 - $max.Value.ToString().TrimStart(&quot;</span>0.<span style="color: #009900;">&quot;).Length)))<br />
&nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; $max.Value = [Math]::Ceiling( $max.Value / $siz ) * $siz<br />
<br />
&nbsp; &nbsp; &nbsp; ## Export the data ...<br />
&nbsp; &nbsp; &nbsp; $path = [IO.Path]::GetTempFileName()<br />
&nbsp; &nbsp; &nbsp; $data | Select-Object @{n=&quot;</span>Value<span style="color: #009900;">&quot;;e=$Value},@{n=&quot;</span>Label<span style="color: #009900;">&quot;;e=$Label},@{n=&quot;</span>Percent<span style="color: #009900;">&quot;;e={($_ | &amp;$Value)/$max.Value}} | export-clixml $path<br />
&nbsp; &nbsp; &nbsp; return $path<br />
&nbsp; &nbsp;}<br />
}<br />
<br />
PROCESS {<br />
&nbsp; &nbsp;if($_) {<br />
&nbsp; &nbsp; &nbsp; $data += $_<br />
&nbsp; &nbsp;}<br />
}<br />
END {<br />
&nbsp; &nbsp;Write-Host &quot;</span>Loading XAML window...<span style="color: #009900;">&quot; -fore Cyan<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;### Import the WPF assemblies<br />
&nbsp; &nbsp;Add-Type -Assembly PresentationFramework<br />
&nbsp; &nbsp;Add-Type -Assembly PresentationCore<br />
&nbsp; &nbsp;## I've removed the xaml to a separate document because it's getting too big for my example :)<br />
&nbsp; &nbsp;$graph = [Windows.Markup.XamlReader]::Load( (New-Object System.Xml.XmlNodeReader ([Xml]$XAML)) )<br />
&nbsp; &nbsp;$graph.Resources.Data.Source = Out-GraphableXml $data ([ref]$max) $Label $Value<br />
<br />
&nbsp; &nbsp;### Generate 10 labels ...<br />
&nbsp; &nbsp;$graph.Resources.scale.Document = &amp;{ <br />
&nbsp; &nbsp; &nbsp; &quot;</span><span style="color: #66cc66;">&lt;</span>scale xmlns<span style="color: #66cc66;">=</span><span style="color: #009900;">''</span><span style="color: #66cc66;">&gt;</span><span style="color: #009900;">&quot;<br />
&nbsp; &nbsp;10..1 | ForEach-Object { &quot;</span><span style="color: #66cc66;">&lt;</span>Mark Label<span style="color: #66cc66;">=</span><span style="color: #009900;">'$(($max/10)*$_)'</span> <span style="color: #66cc66;">/&gt;</span><span style="color: #009900;">&quot; }<br />
&nbsp; &nbsp; &nbsp; &quot;</span><span style="color: #66cc66;">&lt;/</span>scale<span style="color: #66cc66;">&gt;</span><span style="color: #009900;">&quot;<br />
&nbsp; &nbsp;}<br />
&nbsp; &nbsp;### And set the caption<br />
&nbsp; &nbsp;$graph.Resources.GraphCaption = $caption<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;### Maybe rotate the whole thing<br />
&nbsp; &nbsp;if($sideways) {<br />
&nbsp; &nbsp; &nbsp; $graph.Resources.Sideways.Angle = 90<br />
&nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp;$graph.ShowDialog()<br />
&nbsp; &nbsp;# Don't forget to delete that temp file...<br />
&nbsp; &nbsp;Remove-Item $graph.Resources.Data.Source.AbsolutePath<br />
}</span></div>

	<h4>Some <span class="caps">XAML</span> Tips</h4>

	<p>I learned a few things about <span class="caps">XAML</span> markup while doing this. 
	<ol>
		<li>If you bind to an <span class="caps">XML</span> data source that&#8217;s in-line in your <span class="caps">XAML</span>, you do so using the <code>x:XData</code> element, and then a single root element <em>inside</em> that.  You <em>must</em> specify a blank <code>xmlns</code> parameter on that root element, or it won&#8217;t work.  However, when you bind to an eternal <span class="caps">XML</span> document, as in our case &#8212; you need to specify the <span class="caps">XML</span> namespaces using a <code>XmlNamespaceMapping</code> collection &#8212; and you <strong>must</strong> use a prefix, and then repeat that prefix throughout your Xaml whenever you specify an XPath.  However, attributes don&#8217;t require the prefix (I&#8217;m not actually sure why) so in the code above I simply used wildcards for practically every element.</li>
		<li>When you specify attribute <em>tests</em> (like /Node[<code>attribute=&#39;value&#39;]) in binding markup, you get an error because of the equals sign and quotes, but you can just escape them with a backslash, or you can use a </code>Binding@ element and put the test in the XPath attribute (which doesn&#8217;t need escaping).</li>
		<li>The <span class="caps">XAML</span> Grid element is the only element that supports proportional sizing and supports making all the things in a column (or row) the size of the largest item. It&#8217;s a pain to work with by hand because you have to specify each <code>RowDefinition</code> and <code>ColumnDefinition</code> and then assign each child control a <code>Grid.Column</code> and <code>Grid.Row</code> and possibly even a <code>Grid.ColumnSpan</code> or <code>Grid.RowSpan</code> &#8230;</li>
	</ol>
	<ol>
		<li>If you only learn two of the &#8220;complicated&#8221; controls, learn about Grid and <a href="http://www.drwpf.com/blog/Home/tabid/36/EntryID/13/Default.aspx">ItemsControl</a>.</li>
	</ol></p>

	<h4>Some PowerShell <span class="caps">WPF</span> Tips</h4>

	<ol>
		<li>You can generate <span class="caps">XML</span> using <a href="http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.aspx">XDocument</a> instead of <a href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx">XmlDocument</a>, but to be perfectly honest, since you&#8217;re already moving slow, the simplest way to write <span class="caps">XML</span> in PowerShell is to just use here-strings.  In fact, if you need to generate a bunch of rows of <span class="caps">XML</span>, this snippet should help send you in the right direction:<div class="posh code posh" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">XML</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$xml</span> <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&amp;</span><span style="color: #333;">&#123;</span> <br />
<span style="color: #009900;">&quot;&lt;?xml version='1.0' encoding='UTF-8'?&gt;&quot;</span><br />
<span style="color: #009900;">&quot;&lt;scale xmlns=''&gt;&quot;</span><br />
10..1 <span style="color: #66cc66;">|</span> ForEach<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;&lt;Mark Label='$(($max/10)*$_)' /&gt;&quot;</span> <span style="color: #333;">&#125;</span><br />
<span style="color: #009900;">&quot;&lt;/scale&gt;&quot;</span><br />
<span style="color: #333;">&#125;</span></div></li>
		<li>Although the <code>about_data_section</code> help says that you can use [XML]&#8221;...&#8221; as a literal in a Data section &#8212; you can&#8217;t.  Just get used to casting it on the way out &#8230;  Also, </li>
		<li>If you need to cast a parameter to a function, (or specify it as a reference parameter) you have to enclose it in parenthesis: <code>Out-GraphableXml $data ([ref]$max) $Label $Value</code> &#8212; it&#8217;s not enough to put the type there.</li>
		<li>Don&#8217;t forget, reference parameters in PowerShell are actually a <strong>type</strong> (PSReference), and to access the variable inside a PSReference variable <code>$foo</code>, you have to use <code>$foo.Value</code>.</li>
	</ol>
	<ol>
		<li>Sometimes, the Dispatcher.Invoke trick isn&#8217;t enough &#8212; in the case of this data-bound form, it needs to go through at least 3 cycles of handling events before it will finish drawing:<div class="posh code posh" style="font-family:monospace;"><span style="color: #660033; font-weight: bold;">$graph</span>.<span style="color: #003366;">Show</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
1..3 <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span><span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$graph</span>.<span style="color: #003366;">Dispatcher</span>.<span style="color: #003366;">Invoke</span><span style="color: #333;">&#40;</span> <span style="color: #009900;">&quot;Render&quot;</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Windows.<span style="color: #003366;">Input</span>.<span style="color: #003366;">InputEventHandler</span><span style="color: #333;">&#93;</span></span><span style="color: #333;">&#123;</span> <span style="color: #333;">&#125;</span>, <span style="color: #660033; font-weight: bold;">$null</span>, <span style="color: #660033; font-weight: bold;">$null</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span></div></li>
	</ol>

]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/wpf-from-powershell-something-useful/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>WPF From PowerShell &#8211; Updating Windows</title>
		<link>http://huddledmasses.org/wpf-from-powershell-updating-windows/</link>
		<comments>http://huddledmasses.org/wpf-from-powershell-updating-windows/#comments</comments>
		<pubDate>Fri, 09 May 2008 04:32:20 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Forms]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/?p=524</guid>
		<description><![CDATA[In my last post I wrote about how you could make a WPF Splash screen window in PowerShell, but I stated that: &#8220;if the images are remote, the WPF window has to download them, and therefore won&#8217;t work&#8221; correctly. I had played with downloading images directly by setting the Source attribute of the image to [...]]]></description>
			<content:encoded><![CDATA[	<p>In my last post I wrote about how you could <a href="http://huddledmasses.org/wpf-from-powershell-a-splash-screen/">make a <span class="caps">WPF</span> Splash screen window in PowerShell</a>, but I stated that: &#8220;if the images are remote, the <span class="caps">WPF</span> window has to download them, and therefore won&#8217;t work&#8221; correctly.  I had played with downloading images directly by setting the <code>Source</code> attribute of the image to the image <span class="caps">URL</span>, and hadn&#8217;t been able to find a way to get the threading to work well enough to actually download the image.  </p>

	<p>Well, I figured that out, so I thought I&#8217;d go ahead and share &#8230; basically, all you have to do is call Invoke() on the window&#8217;s dispatcher.  The reason that works is that <span class="caps">WPF</span> handles events and &#8220;work&#8221; in general in the order it needs to be done, so since the most important thing is drawing the UI it will do that first, and since your UI is based on downloading the image, it will take care of that first.</p>

	<h6>This is PowerShell v2 CTP2 code&#8230;</h6>

	<p>All of this code is written to target the CTP2 release of PowerShell v2 &#8212; it <em>will not</em> work in PowerShell v1 or even in v2 CTP1 &#8230; and it <em>may not</em> work in later releases, although I expect it will.  Also, as with any code which uses <span class="caps">WPF</span> from PowerShell, these code examples require you to launch PowerShell with the -<span class="caps">STA</span> option.</p>

	<p>Having said that, lets just straight to a <span class="caps">WPF</span> example <span id="more-524"></span></p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">function</span> demo2 <span style="color: #333;">&#123;</span><br />
<span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">Type</span></span> <span style="color: #000066;">-Assembly</span> PresentationFramework<br />
<br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">xml</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$xaml</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;&lt;Window xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'<br />
&nbsp; &nbsp;WindowStyle='None' AllowsTransparency='True' Opacity='0.8' Topmost='True'<br />
&nbsp; &nbsp;SizeToContent='WidthAndHeight' WindowStartupLocation='CenterOwner' ShowInTaskbar='False'&gt;<br />
&lt;Image Height='177' Source='http://dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/00000/5000/500/5651/5651.strip.print.gif' /&gt;<br />
&lt;/Window&gt;&quot;</span><br />
<br />
<span style="color: #660033; font-weight: bold;">$splash</span> <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Windows.<span style="color: #003366;">Markup</span>.<span style="color: #003366;">XamlReader</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">Load</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366; font-weight: bold;">Xml</span>.<span style="color: #003366;">XmlNodeReader</span> <span style="color: #660033; font-weight: bold;">$xaml</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$splash</span>.<span style="color: #003366;">Show</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$splash</span>.<span style="color: #003366;">Dispatcher</span>.<span style="color: #003366;">Invoke</span><span style="color: #333;">&#40;</span> <span style="color: #009900;">&quot;Render&quot;</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Windows.<span style="color: #003366;">Input</span>.<span style="color: #003366;">InputEventHandler</span><span style="color: #333;">&#93;</span></span><span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$splash</span>.<span style="color: #003366;">UpdateLayout</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span>, <span style="color: #660033; font-weight: bold;">$null</span>, <span style="color: #660033; font-weight: bold;">$null</span><span style="color: #333;">&#41;</span><br />
<span style="color: #0066cc; font-style: italic;">Start-<span style="font-style: normal;">Sleep</span></span> <span style="color: #cc66cc;">3</span> &nbsp; <span style="color: #666666; font-style: italic;"># imagine this is a long script &nbsp;... running</span><br />
<span style="color: #660033; font-weight: bold;">$splash</span>.<span style="color: #003366;">Hide</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #666666; font-style: italic;"># and at the end, you just get rid of it</span><br />
<span style="color: #333;">&#125;</span></div>

	<p>That&#8217;s almost as simple as it could get, but let me explain a few things which I left out previously, in case you&#8217;re new to <span class="caps">XAML</span> or even <span class="caps">WPF</span>.  The <strong>Window</strong> tag is one of several acceptable root tags in <span class="caps">XAML</span>, but it&#8217;s the only one which will let you pop up a new window (in PoshConsole, you can display <span class="caps">XAML</span> inline using <code>Out-WPF</code>, and you can use almost any <span class="caps">XAML</span> nodes, but for now, lets focus on what works in general in the CTP2 console).  The <code>xmlns</code> attribute is required in order for the xml to be verifiable to the schema, but in <span class="caps">XAML</span> it&#8217;s particularly important because without it, this would just be <span class="caps">XML</span> &#8212;not Xaml&#8212; and wouldn&#8217;t produce UI.</p>

	<h3><span class="caps">WPF</span> Windows</h3>

	<p>There&#8217;s several fun tricks you can do in <span class="caps">WPF</span> with the Window that you can&#8217;t do in Windows Forms without a lot of hacking. <code>ShowInTaskbar</code> is hardly worth mentioning (it just does what it says). The <code>Opacity</code> attribute is kind of cool &#8212; it just controls the translucency level (valid values are from 0 to 1, but below the smaller values aren&#8217;t really very useful) &#8212; but you can animate this pretty easily to cause your windows to fade in and out.  But there are a few that are more impressive:</p>

	<h4>Size To Content</h4>

	<p>One of my favorite features of <span class="caps">WPF</span> windows it that you can use <code>SizeToContent</code> to have the form automatically take the size of whatever is inside it (which is really useful when you&#8217;re loading images off the web).  You have to be careful with this though, because <a href="http://www.wpflearningexperience.com/?p=41"><span class="caps">WPF</span> is resolution independent</a> but it&#8217;s also aware of how many pixels-per-inch images have been saved with.  Typically, if you have a png file, it&#8217;s been saved at something like 200 or 300 pixels per inch to make it printable &#8230; but your screen&#8217;s resolution is only (<a href="http://www.wpflearningexperience.com/?p=41">approximately</a>) 96 pixels-per-inch.  This results in images being displayed, by default &#8230; at <span class="caps">HUGE</span> sizes compared to what you expect. Caveat emptor.</p>

	<h4>Transparency</h4>

	<p>A <span class="caps">WPF</span> window with <code>AllowsTransparency</code> set to true can be non-rectangular!  It&#8217;s <strong>very</strong> important that you understand this isn&#8217;t about allowing translucency (that is, it has nothing to do with the Opacity setting). With this setting on, your window will basically not exist in any spot where there&#8217;s no color (See demo4 below). It will be not only be invisible &#8212; mouse-clicks won&#8217;t register.  You&#8217;ll also be able to have true per-pixel transparency, with the ability to set the alpha level of each pixel, since <span class="caps">WPF</span> colors can be specified as #<span class="caps">AARRGGBB</span> quads.</p>

	<h4>WindowStyle</h4>

	<p>This wouldn&#8217;t merit mentioning, except that it has a tie-in with Transparency. You can set the <code>WindowStyle</code> in Windows Forms too, and just like Windows Forms, the valuesfor <span class="caps">WPF</span> are None, SingleBorderWindow, ThreeDBorderWindow, and ToolWindow &#8230; however, if you use AllowsTransparency, the only valid value for WindowStyle is &#8220;None.&#8221;</p>

	<h4>Startup Location</h4>

	<p>As with <code>WindowStyle</code>, this attribute is mostly special because of it&#8217;s exceptions. You can use <code>WindowStartupLocation</code> to specify where you want the form to appear. Valid values are Manual, CenterScreen, and CenterOwner.  CenterScreen is the obvious choice for a splash screen, but I should point out something about the other two as well. CenterOwner means to center the window on it&#8217;s parent window &#8230; but it only works with other <span class="caps">WPF</span> windows. If you don&#8217;t set the owner to a <span class="caps">WPF</span> window, CenterOwner works just like Manual.  The Manual setting allows you to specify the window position with the <code>Top</code> and <code>Left</code> attributes, or just let Windows position you in the default location.</p>

	<h3>Events and Delegates</h3>

	<p>There&#8217;s one line of code in the sample above which bears explaining &#8212; the call to <code>Dispatcher.Invoke</code>. The point of this call is to basically transfer the thread control to the window for a moment. In fact, the signature of the Invoke method is that it takes a <em>priority</em> (I use render because it&#8217;s basically immediate), a <em>delegate</em> (I pass a scriptblock), and arguments for the scriptblock.  PowerShell will let you <em>easily</em> cast a scriptblock to a delegate method which takes two <code>object</code> parameters and doesn&#8217;t return a value &#8230; but it won&#8217;t let you convert them to any other method without using reflection and <code>IL.Emit</code>.  Thus, we cast our scriptblock to any handy delegate type, and pass <code>$null</code> for both parameters.</p>

	<h3>But that Invoke() stuff is ugly</h3>

	<p>Of course, we don&#8217;t like having to manually update the window by calling Invoke(), but I still haven&#8217;t figured out how to spin out another thread safely &#8230; so the only other option is to just give control to the window (actually I think this could be done with background jobs, but I can&#8217;t seem to get the WinRM <span class="caps">CTP</span> configured properly).</p>

	<p>Giving control to the window is actually the <em>normal</em> way of doing UI programming &#8230; and isn&#8217;t really a very big deal in PowerShell &#8212; you can write your event handlers for the controls on the window, and then call ShowDialog() and you&#8217;re off.  Just to give you an example, I&#8217;ve tweaked an old <span class="caps">WPF</span> sample I had and ported it to PowerShell &#8230;  the <a href='http://HuddledMasses.org/wpf-from-powershell-updating-windows/clock/' rel='attachment wp-att-528'>xaml file is here</a> and I&#8217;ll paste the code (with comments) inline, but if you may also <a href='http://HuddledMasses.org/wpf-from-powershell-updating-windows/demo-wpf4/' rel='attachment wp-att-529'>download the PowerShell script</a>.  You need both files for it to work, because the clock.xaml file is the only argument to the demo-wpf4.ps1 script  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' /> </p>

	<p>Check it out:</p>

	<p><img src="http://huddledmasses.org/images/2008-05-09_0029.png" title="A clock, with working CPU and RAM bars" alt="A clock, with working CPU and RAM bars" width="783" height="312" /></p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;">### Import the WPF assemblies</span><br />
<span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">Type</span></span> <span style="color: #000066;">-Assembly</span> PresentationFramework<br />
<span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">Type</span></span> <span style="color: #000066;">-Assembly</span> PresentationCore<br />
<br />
<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Initializing Performance Counters, please have patience&quot;</span> <span style="color: #000066;">-fore</span> Cyan<br />
<span style="color: #660033; font-weight: bold;">$script</span>:cpu <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Diagnostics</span>.<span style="color: #003366;">PerformanceCounter</span> <span style="color: #009900;">&quot;Processor&quot;</span>, <span style="color: #009900;">&quot;% Processor Time&quot;</span>, <span style="color: #009900;">&quot;_Total&quot;</span><br />
<span style="color: #660033; font-weight: bold;">$script</span>:ram <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Diagnostics</span>.<span style="color: #003366;">PerformanceCounter</span> <span style="color: #009900;">&quot;Memory&quot;</span>, <span style="color: #009900;">&quot;Available KBytes&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## get initial values, because the counters don't work until the second call</span><br />
<span style="color: #660033; font-weight: bold;">$null</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$script</span>:cpu.<span style="color: #003366;">NextValue</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$null</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$script</span>:ram.<span style="color: #003366;">NextValue</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$script</span>:maxram <span style="color: #66cc66;">=</span> <span style="color: #333;">&#40;</span><span style="color: #660033;">gwmi</span> Win32_OperatingSystem<span style="color: #333;">&#41;</span>.<span style="color: #003366;">TotalVisibleMemorySize</span><br />
<br />
<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Loading XAML window...&quot;</span> <span style="color: #000066;">-fore</span> Cyan<br />
<span style="color: #666666; font-style: italic;">## I've removed the xaml to a separate document because it's getting too big for my example :)</span><br />
<br />
<span style="color: #660033; font-weight: bold;">$clock</span> <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Windows.<span style="color: #003366;">Markup</span>.<span style="color: #003366;">XamlReader</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">Load</span><span style="color: #333;">&#40;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366; font-weight: bold;">Xml</span>.<span style="color: #003366;">XmlNodeReader</span> <span style="color: #333;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">Xml</span><span style="color: #333;">&#93;</span></span><span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Content</span></span> <span style="color: #009900;">&quot;C:\Users\Joel\Documents\WindowsPowerShell\Scripts\Demo\clock.xaml&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#41;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Create a script block which will update the UI</span><br />
<span style="color: #660033; font-weight: bold;">$counter</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>;<br />
<span style="color: #660033; font-weight: bold;">$updateBlock</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Update the clock</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Resources</span><span style="color: #333;">&#91;</span><span style="color: #009900;">&quot;Time&quot;</span><span style="color: #333;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>DateTime<span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">Now</span>.<span style="color: #003366;">ToString</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;hh:MM.ss&quot;</span><span style="color: #333;">&#41;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># We only want to update the counters at most once a second</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Otherwise their values are invalid and ...</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># The CPU counter fluctuates from 0 to the real number</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$counter</span><span style="color: #66cc66;">++</span> <span style="color: #000066;">-eq</span> <span style="color: #cc66cc;">4</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$counter</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Update the CPU counter</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$cu</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$cpu</span>.<span style="color: #003366;">NextValue</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Resources</span>.<span style="color: #003366;">CpuP</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$cu</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">100</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Resources</span>.<span style="color: #003366;">Cpu</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;{0:0.0}%&quot;</span> <span style="color: #000066;">-f</span> <span style="color: #660033; font-weight: bold;">$cu</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#$clock.FindResource(&quot;CpuStory&quot;).Begin($clock)</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Update the RAM counter</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$rm</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$ram</span>.<span style="color: #003366;">NextValue</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Resources</span>.<span style="color: #003366;">RamP</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$rm</span> <span style="color: #66cc66;">/</span> <span style="color: #660033; font-weight: bold;">$maxram</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Resources</span>.<span style="color: #003366;">Ram</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;{0:0.00}Mb&quot;</span> <span style="color: #000066;">-f</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$rm</span><span style="color: #66cc66;">/</span>1MB<span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#$clock.FindResource(&quot;RamStory&quot;).Begin()</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Hook up some event handlers </span><br />
<span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Add_SourceInitialized</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Before the window's even displayed ...</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## We'll create a timer</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$timer</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #003366;">Threading</span>.<span style="color: #003366;">DispatcherTimer</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Which will fire 4 times every second</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$timer</span>.<span style="color: #003366;">Interval</span> <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>TimeSpan<span style="color: #333;">&#93;</span></span><span style="color: #009900;">&quot;0:0:0.25&quot;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## And will invoke the $updateBlock</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$timer</span>.<span style="color: #003366;">Add_Tick</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$updateBlock</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Now start the timer running</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$timer</span>.<span style="color: #660033;">Start</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$timer</span>.<span style="color: #003366;">IsEnabled</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Clock is running. Don't forget: RIGHT-CLICK to close it.&quot;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Close</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Error</span></span> <span style="color: #009900;">&quot;Timer didn't start&quot;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #333;">&#41;</span><br />
<br />
<span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Add_MouseLeftButtonDown</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Handled</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$true</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">DragMove</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #666666; font-style: italic;"># WPF Magic!</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Add_MouseRightButtonDown</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Handled</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$true</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$timer</span>.<span style="color: #003366;">Stop</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> &nbsp;<span style="color: #666666; font-style: italic;"># we'd like to stop that timer now, thanks.</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">Close</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #666666; font-style: italic;"># and close the windows</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #333;">&#41;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Lets go ahead and invoke that update block </span><br />
<span style="color: #66cc66;">&amp;</span><span style="color: #660033; font-weight: bold;">$updateBlock</span><br />
<span style="color: #666666; font-style: italic;">## And then show the window</span><br />
<span style="color: #660033; font-weight: bold;">$clock</span>.<span style="color: #003366;">ShowDialog</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span></div>

	<h4> <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[new]' class='wp-smiley' />  Post Script</h4>

	<p>I should probably mention that I coded the <span class="caps">XAML</span> for that clock by hand, using <a href="http://www.kaxaml.com/">kaxaml</a>, rather than using Expression Blend &#8212; I don&#8217;t necessarily recommend it, but it&#8217;s good practice once in a while.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' />   <span class="caps">XAML</span> supports a lot of animations, and I spent almost an entire day trying different things to create a smooth animation for the <span class="caps">CPU</span> and <span class="caps">RAM</span> bars which would let them animate smoothly from one value to the next.  In the end I decided it would have to be written in code rather than <span class="caps">XAML</span> markup, and would complicate things even more than they already were.</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/wpf-from-powershell-updating-windows/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

