<?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"
	>

<channel>
	<title>Emphess .NET</title>
	<atom:link href="http://www.emphess.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.emphess.net</link>
	<description>Inaugurating Partial Template Specialization on Simulated Covariance For Volatile Data ... Sometime ;)</description>
	<pubDate>Wed, 17 Sep 2008 10:35:31 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>WPF Direct3D Interop</title>
		<link>http://www.emphess.net/2008/05/28/wpf_direct3d_interop/</link>
		<comments>http://www.emphess.net/2008/05/28/wpf_direct3d_interop/#comments</comments>
		<pubDate>Wed, 28 May 2008 11:49:10 +0000</pubDate>
		<dc:creator>Christoph Menge</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Direct3D]]></category>

		<category><![CDATA[DirectX]]></category>

		<category><![CDATA[Overlay]]></category>

		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://www.emphess.net/?p=38</guid>
		<description><![CDATA[There are some very interesting posts I missed the last days. Since .NET 3.5 SP1 perfectly integrates WPF with DirectX, a number of cool effects can finally be applied:
http://www.codeproject.com/KB/WPF/WPFPixelShader.aspx
http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx
http://weblogs.asp.net/scottgu/archive/2008/05/12/visual-studio-2008-and-net-framework-3-5-service-pack-1-beta.aspx
Some of those effects were on Dax Pandhi&#8217;s wish list for WPF (http://blog.nukeation.com/post/My-wishlist-for-the-next-release-of-WPF.aspx) for quite some time.
More importantly, the integration of WPF and Direct3D might eliminate the [...]]]></description>
			<content:encoded><![CDATA[<p>There are some very interesting posts I missed the last days. Since .NET 3.5 SP1 perfectly integrates WPF with DirectX, a number of cool effects can finally be applied:<br />
<a href="http://www.codeproject.com/KB/WPF/WPFPixelShader.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/www.codeproject.com');">http://www.codeproject.com/KB/WPF/WPFPixelShader.aspx</a></p>
<p><a href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/blogs.msdn.com');">http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx</a></p>
<p><a href="http://weblogs.asp.net/scottgu/archive/2008/05/12/visual-studio-2008-and-net-framework-3-5-service-pack-1-beta.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/weblogs.asp.net');">http://weblogs.asp.net/scottgu/archive/2008/05/12/visual-studio-2008-and-net-framework-3-5-service-pack-1-beta.aspx</a></p>
<p>Some of those effects were on Dax Pandhi&#8217;s wish list for WPF (<a href="http://blog.nukeation.com/post/My-wishlist-for-the-next-release-of-WPF.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/blog.nukeation.com');">http://blog.nukeation.com/post/My-wishlist-for-the-next-release-of-WPF.aspx</a>) for quite some time.</p>
<p>More importantly, the integration of WPF and Direct3D might eliminate the need for a custom overlay control for the MenuKiller Control, which is a major performance hog (I currently use an overlay similar to this: <a href="http://blogs.msdn.com/pantal/archive/2007/07/31/managed-directx-interop-with-wpf-part-2.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/blogs.msdn.com');">http://blogs.msdn.com/pantal/archive/2007/07/31/managed-directx-interop-with-wpf-part-2.aspx</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.emphess.net/2008/05/28/wpf_direct3d_interop/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A MenuKiller Control - Draft</title>
		<link>http://www.emphess.net/2008/05/04/a-menukiller-control-draft/</link>
		<comments>http://www.emphess.net/2008/05/04/a-menukiller-control-draft/#comments</comments>
		<pubDate>Sun, 04 May 2008 20:52:51 +0000</pubDate>
		<dc:creator>Christoph Menge</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Custom Controls]]></category>

		<category><![CDATA[Differentiated UX]]></category>

		<category><![CDATA[DUX]]></category>

		<category><![CDATA[Menu Killer]]></category>

		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://www.emphess.net/?p=37</guid>
		<description><![CDATA[This is just a draft on my upcoming article. I have asked a number of WPF Gurus to help me out on this&#8230;
Introduction

In an effort to take user experience to the next level, designers have come up with ideas on how to solve old problems in a new way. In the last few months, the [...]]]></description>
			<content:encoded><![CDATA[<p>This is just a draft on my upcoming article. I have asked a number of <a href="http://wpfdisciples.wordpress.com/" onclick="javascript:pageTracker._trackPageview ('/outbound/wpfdisciples.wordpress.com');">WPF Gurus</a> to help me out on this&#8230;</p>
<h2>Introduction</h2>
<p>
In an effort to take user experience to the next level, designers have come up with ideas on how to solve old problems in a new way. In the last few months, the term &#8220;Differentiated User Experience&#8221; or simply &#8220;Differentiated UX&#8221; has come up to describe these efforts.
</p>
<p>
One of the beforementioned UI designers is Dax Pandhi, who published an article <a href="http://blog.nukeation.com/post/UX-Concepts---Rethinking-the-Button.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/blog.nukeation.com');">&#8220;Rethinking the Button&#8221;</a> on <a href="http://blog.nukeation.com/default.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/blog.nukeation.com');">his blog</a> which introduced a new control he calls <code>MenuKiller</code>. This control is certainly more than a replacement for the <code>Menu</code> and <code>ContextMenu</code>, as it can be used in ways that are quite different. However, it turns out that changing the way things are typically done is indeed not so easy.
</p>
<p><img src="http://www.emphess.net/wp-content/uploads/2008/05/MenuKiller1.jpg" alt="A Screenshot of the MenuKiller" /></p>
<p>
This article gives an overview of my implementation of the <code>MenuKiller</code> and presents a small sample application. It&#8217;s written in C# using .NET 3.5 and Visual Studio 2008. What is presented here is not a full-fledged control, since there are quite a number of open todos. Yet, I hope that this motivates the use of different controls and serves as a good starting point for other WPF control development.
</p>
<p><span id="more-37"></span></p>
<h2>Download</h2>
<p>The current code can be <a href="http://www.emphess.net/wp-content/uploads/2008/05/MenuKillerDraft.zip">downloaded here</a>.</p>
<h2>Scope &amp; Prerequsities</h2>
<p>
Since this is a custom control which is meant to redefine significant parts of user experience, it is not trivial to implement. Hence, knowledge of WPF basics is helpful, but I attempted to present the basics while still giving some more advanced tips. Although this control is merely the result of my begginer&#8217;s journey into WPF, it took me quite some time to write and it involved a lot of reading, programming and experimenting.
</p>
<p>
Also, for a better explanation of the goal we try to achieve, I strongly recommend Dax&#8217;s article. While the screenshot should already give you an idea, the article provides significantly more insight.
</p>
<p>
This control uses a very different approach to control alignment. This is the most critical point of this article. Either I did this because I was completely lost and didn&#8217;t see a better solution or this approach is a necessity of the complicated arrange behaviour this control employs. I am quite happy with the last iteration of this, before I managed to cut down code size by almost 70% through refactoring. I also dropped some &#8216;heavy&#8217; features.
</p>
<h3>Design Aims</h3>
<ul>
<li> Using the control in XAML should be very similar to using a TreeView.</li>
<li> It should allow for rich and dynamic content, as well as animation.</li>
<li> Databinding must be possible.</li>
<li> Templating is also a requirement.</li>
<li> The importance of the Visual Studio designer is low.</li>
</ul>
<h3>Our Options</h3>
<p>
When reading the <a href="http://msdn2.microsoft.com/en-us/library/ms745025.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/msdn2.microsoft.com');">MSDN on custom control authoring</a>, Microsoft presents a lot of options on how to avoid authoring a custom control. These options include Rich Content, Styles, Data Templates, Control Templates and Triggers. Microsoft does not directly encourage you to write a control, probably in an effort to prevent people from writing controls contrary to the idea of WPF. However, I have come to the conclusion that it is best for this control to use a custom control approach, despite -or even because of- the possibilities of WPF. This control is implemented with the idea in mind that you might want to create a control which does not come with source, yet can be customized easily.
</p>
<p>
Next, it is important not to re-invent the wheel, primarily because it is error-prone and the result might not fit into the framework as it should.
</p>
<p>
So what does our control do? Essentially, it shows a hierarchically organized collection of command-bound items circularly arranged around a center object.
</p>
<p>
That does, I agree, sound a little overcomplicated, but it is the full statement. Let&#8217;s see what we can get from it:</p>
<ul>
<li> Hierarchically organized: Since the control presents different &#8216;levels&#8217;, we need to model a hierarchy. This is reminiscent of a <code>TreeView</code>, obviously. <code>TreeView</code>s are derived from <code>ItemsControl</code>, so we might also want to take these into account. Note that <code>TreeView</code>s need container objects (<code>TreeViewItem</code>s) to store the hierarchy information while still allowing rich content.</li>
<li>Circularly arranged: Since this involves solely the arrangement of items, we might want to separate this problem into a custom panel, commonly called a CircularPanel.</li>
<li>around a center object: While this might look like a simple statement, it will prove to be one of the hardest tasks in the creation of our MenuKiller. Normal controls can have one of four alignments horizontally and vertically. These alignments are relative to their respective parent. The canvas, on the other hand, allows items to be positioned arbitrarily within its bounds.</li>
</ul>
<h2>The TreeView</h2>
<p>
A normal <code>TreeView</code> is an <code>ItemsControl</code>, which typically has <code>TreeViewItem</code>s. These are, again, <code>ItemsControl</code>s (or more specifically <code>HeaderedItemsControl</code>s), thereby representing the desired tree structure. For our control, however, the MenuKiller itself is not an <code>ItemsControl</code>: It can only have one root item. Therefore, it is a <code>ContentControl</code> and we will not derive from <code>TreeView</code>.
</p>
<p>
The <code>MenuKillerItem</code>s, on the other hand, are in fact <code>ItemsControl</code>s, thereby being a good candidate for the parent of our <code>MenuKillerItem</code>s. Although we won&#8217;t derive from <code>TreeView</code>, a small comparison of the two might be enlightening, yet keeping in mind that the behaviour of the MenuKiller is, not suprisingly, very similar to that of a normal <code>Menu</code> or <code>ContextMenu</code>.
</p>
<ul>
<li>While the TreeView is typically used for selection purposes, a MenuKiller is used for activation of actions. This can be a button press or -toggle, depending on the <code>CanExecute()</code> on the <code>Command</code></li>
<li>Unlike <code>TreeViewItem</code>s, Items in the MenuKiller cannot be selected. More importantly, nodes that have children are fundamentally different from those that haven&#8217;t, because they are used only for grouping purposes. (Note: It&#8217;s possible to do <a href="http://www.hardcodet.net/2008/03/prevent-wpf-tree-node-selection" onclick="javascript:pageTracker._trackPageview ('/outbound/www.hardcodet.net');">grouping with TreeViews</a>, too, but that is not their default behaviour.</li>
<li>Most <code>TreeView</code>s are embedded in a scroll container, a MenuKiller on the other hand must not live in a scroll container. It also has a much tighter constraint in terms of item count.</li>
</ul>
<p>
It is obvious that the difference between the two is rather large. I also implemented an approach using <code>Menu</code> and <code>MenuItem</code>s, which have a very similar behaviour, but it turned out to be very ugly due to some render-related problems with the <code>MenuItem</code>s.
</p>
<h2>Sizing &#038; Positioning</h2>
<p>
The control works in a very visual manner, which requires us to have the root item in close proximity to the object it shall operate on. Let&#8217;s first concentrate on the case where the actual object does not move. Now we are still facing the problem that the control, when collapsing / expanding, changes its size. When the control grows to a certain direction -say, for example, to the top- it also needs to be repositioned, so the center of the main circle is still aligned with our object.</p>
<p>Even worse, since we have a hierarchical data structure, this problem must be solved for all items recursively. This, again, calls for a special panel. In an act of desperation, I called this <code>ReferenceAlignPanel</code>, thus qualifying for the worst-class-names-ever-thought-of-2008-award. While the name of this control is really awkward, it&#8217;s behaviour is at least unusual, too:<br />
Given a set of controls that implement <code>ICustomAlignedControl</code>, it will ask the controls for their <code>AlignReferencePoint</code> and arrange the controls in a way such that all reference points coincide. This, of course, is not possible in every case. I stuck to a very basic implementation of this kind of panel. More on that later.</p>
<p>The standard <code>ContextMenu</code> will be placed in a <code>Popup</code>, and can draw on areas of the screen where the application window is not. That sounds tempting for the MenuKiller, too. However, the <code>ContextMenu</code> can do that only due to the fact that the <code>ContextMenu</code> is a very boring control with a solid background color. The MenuKiller, having a 100% transparent panel, should not cross window borders. The effect might be visually irritating. </p>
<p>Apart from the alignment of circles, it would be nice to see a different expanding behaviour if the control is located at a window border. It is also desireable to make a distinction between left-to-right and right-to-left systems. I call this feature &#8220;adaptive arrange&#8221;, but the current solution does not include it because some problems remain to this day. (The issue here is that we need arrangement information in the measure pass. That is not good, and the current simple MenuKiller already needs remeasures from time to time).
</p>
<p>
Summing up the possibilities on arrangement:</p>
<ul>
<li>We can rearrange the items in the <code>CircularPanel</code> in a smart manner, thus eliminating the need to use alignment hacks. This is tricky and will only work to a certain degree.</li>
<li>We can put the whole MenuKiller or all <code>MenuKillerItem</code>s into a <code>Popup</code>, which might result in more available space at the cost of visual coherence. This doesn&#8217;t eliminate the arrangement problem at screen borders, however. Putting each item into a separate popup is not a good idea from my experience.</li>
</ul>
<p>
For most scenarios, we can make some simplifying assumptions. The most important assumption is that there is enough space in one direction, at least. So we can choose the direction(s) with most space available as initial grow directions. We might also accept the case where the control &#8216;jumps&#8217; because it grew too large in one direction, therefore requiring to be realigned, at least if there is little space available.
</p>
<h3>Custom Alignment: ICustomAlign</h3>
<p>Let&#8217;s talk about the way our custom alignment should look for the MenuKiller: When we talk about the center of a control, we normally mean the point which lies in the middle of the actual control&#8217;s border. However, for the CircularPanel, it is desirable to know the center of the circle segment. We have to provide some public getter:</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="co1">/// &lt;summary&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">/// This name is too generic and imprecise.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">/// &lt;/summary&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">interface</span> ICustomAlignedControl</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; Point AlignReferencePoint <span class="br0">&#123;</span> get; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
Notice that this point may be well outside of the control. The screenshot shows a <code>CircularPanel</code> with its full circle, the circles center and the controls center:
</p>
<p><img src="http://www.emphess.net/wp-content/uploads/2008/05/Alignment1.jpg" alt="Screenshot showing the difference between the center of the CircularPanels' desired size and the center of the corresponding circle segment." /></p>
<p>
Since we don&#8217;t want to mess around with this interface and its alignment-implications everywhere, it&#8217;s time for the first custom panel of the solution which takes care of that:
</p>
<h3>The ReferenceAlignPanel</h3>
<p>
Also known as the panel with the ugly name, the <code>ReferenceAlignPanel</code> constitutes the core concept that addresses the alignment issues we are getting into by arranging all its items such that their <code>AlignReferencePoints</code> or their centers coincide (see above). Let me give a short introduction to panels:
</p>
<p>
When writing a custom panel, one must override the <code>MeasureOverride</code> and <code>ArrangeOverride</code> methods, which constitute the 2-pass layout system of WPF. In the <code>MeasureOverride()</code> method, the control is asked for its <code>DesiredSize</code>. WPF will automatically assign the return value of the measure pass to the <code>DesiredSize</code>-property. Note that even if the amount of <code>availableSize</code> is infinite (as it is for example in a scroll-container), you must not return an infinite size from <code>MeasureOverride</code>. Also, we need to make sure we call <code>Measure()</code> on all children:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">using</span> <span class="kw5">System</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">using</span> <span class="kw5">System</span>.<span class="me1">Windows</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">using</span> <span class="kw5">System</span>.<span class="me1">Windows</span>.<span class="me1">Controls</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">using</span> <span class="kw5">System</span>.<span class="me1">Windows</span>.<span class="me1">Media</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">namespace</span> MenuKiller</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">public</span> <span class="kw4">class</span> ReferenceAlignPanel <span class="sy0">:</span> Panel, ICustomAlignedControl</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">private</span> Point _alignReferencePoint;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">public</span> Point AlignReferencePoint</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> _alignReferencePoint; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; set <span class="br0">&#123;</span> _alignReferencePoint <span class="sy0">=</span> value; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">private</span> Vector GetChildOffset<span class="br0">&#40;</span>UIElement child<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; Vector childDesiredOffset;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>child <span class="kw3">is</span> ICustomAlignedControl<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset <span class="sy0">=</span> AlignReferencePoint <span class="sy0">-</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>ICustomAlignedControl<span class="br0">&#41;</span>child<span class="br0">&#41;</span>.<span class="me1">AlignReferencePoint</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">else</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// TODO: Honor the children&#39;s align properties</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset <span class="sy0">=</span> <span class="kw3">new</span> Vector<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset.<span class="me1">X</span> <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _alignReferencePoint.<span class="me1">X</span> <span class="sy0">-</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Width</span> <span class="sy0">*</span> <span class="nu0">0.5</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset.<span class="me1">Y</span> <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _alignReferencePoint.<span class="me1">Y</span> <span class="sy0">-</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Height</span> <span class="sy0">*</span> <span class="nu0">0.5</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>AllowRealign<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// If this happens, we have to re-measure all items!</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>childDesiredOffset.<span class="me1">X</span> <span class="sy0">&lt;</span> <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _alignReferencePoint.<span class="me1">X</span> <span class="sy0">-=</span> childDesiredOffset.<span class="me1">X</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset.<span class="me1">X</span> <span class="sy0">=</span> <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; realignRequired <span class="sy0">=</span> <span class="kw1">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>childDesiredOffset.<span class="me1">Y</span> <span class="sy0">&lt;</span> <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _alignReferencePoint.<span class="me1">Y</span> <span class="sy0">-=</span> childDesiredOffset.<span class="me1">Y</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset.<span class="me1">Y</span> <span class="sy0">=</span> <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; realignRequired <span class="sy0">=</span> <span class="kw1">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> childDesiredOffset;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw4">bool</span> realignRequired <span class="sy0">=</span> <span class="kw1">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw1">override</span> Size ArrangeOverride<span class="br0">&#40;</span>Size finalSize<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> arrangeCount <span class="sy0">=</span> <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// realign should not be required, but you can&#39;t bet on it. </span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// Protect from infinite iteration.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span>UIElement child <span class="kw1">in</span> Children<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>child.<span class="me1">IsVisible</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vector childOffset <span class="sy0">=</span> GetChildOffset<span class="br0">&#40;</span>child<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; child.<span class="me1">Arrange</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> Rect<span class="br0">&#40;</span>childOffset.<span class="me1">X</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;childOffset.<span class="me1">Y</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;child.<span class="me1">DesiredSize</span>.<span class="me1">Width</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;child.<span class="me1">DesiredSize</span>.<span class="me1">Height</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">++</span>arrangeCount;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">while</span> <span class="br0">&#40;</span>realignRequired <span class="sy0">&amp;&amp;</span> arrangeCount <span class="sy0">&lt;</span> <span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> finalSize;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw1">override</span> Size MeasureOverride<span class="br0">&#40;</span>Size availableSize<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; Size inifiniteSize <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> Size<span class="br0">&#40;</span><span class="kw4">Double</span>.<span class="me1">PositiveInfinity</span>, <span class="kw4">Double</span>.<span class="me1">PositiveInfinity</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; AdjustAlignReferencePoint<span class="br0">&#40;</span>availableSize<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> bMeasureNecessary <span class="sy0">=</span> <span class="kw1">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> iMaxRemeasureCount <span class="sy0">=</span> <span class="nu0">4</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; Size neededSize <span class="sy0">=</span> <span class="kw3">new</span> Size<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// ugly and convoluted</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// A high number of remeasures will not happen - except </span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// for the vs designer, it seems. Removing </span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// this check will crash VS</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// FIXME: Clean this up or use different beh. in design mode</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span>; bMeasureNecessary <span class="sy0">&amp;&amp;</span> i <span class="sy0">&lt;</span> iMaxRemeasureCount; <span class="sy0">++</span>i <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; neededSize.<span class="me1">Width</span> <span class="sy0">=</span> neededSize.<span class="me1">Height</span> <span class="sy0">=</span> <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; bMeasureNecessary <span class="sy0">=</span> <span class="kw1">false</span>; <span class="co1">// Assume remeasure is not needed</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; Vector MinimumChildOffset <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> Vector<span class="br0">&#40;</span><span class="kw4">Double</span>.<span class="me1">MaxValue</span>, <span class="kw4">Double</span>.<span class="me1">MaxValue</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span>UIElement child <span class="kw1">in</span> Children<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; child.<span class="me1">Measure</span><span class="br0">&#40;</span>inifiniteSize<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>child.<span class="me1">IsVisible</span> <span class="sy0">==</span> <span class="kw1">false</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">continue</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vector childDesiredOffset <span class="sy0">=</span> GetChildOffset<span class="br0">&#40;</span>child<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MinimumChildOffset.<span class="me1">X</span> <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Math.<span class="me1">Min</span><span class="br0">&#40;</span>MinimumChildOffset.<span class="me1">X</span>, childDesiredOffset.<span class="me1">X</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MinimumChildOffset.<span class="me1">Y</span> <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Math.<span class="me1">Min</span><span class="br0">&#40;</span>MinimumChildOffset.<span class="me1">Y</span>, childDesiredOffset.<span class="me1">Y</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; neededSize.<span class="me1">Width</span> <span class="sy0">=</span> Math.<span class="me1">Max</span><span class="br0">&#40;</span>neededSize.<span class="me1">Width</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset.<span class="me1">X</span> <span class="sy0">+</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Width</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; neededSize.<span class="me1">Height</span> <span class="sy0">=</span> Math.<span class="me1">Max</span><span class="br0">&#40;</span>neededSize.<span class="me1">Height</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; childDesiredOffset.<span class="me1">Y</span> <span class="sy0">+</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Height</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>bMeasureNecessary<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">continue</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>AllowRealign<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>MinimumChildOffset.<span class="me1">X</span> <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _alignReferencePoint.<span class="me1">X</span> <span class="sy0">-=</span> MinimumChildOffset.<span class="me1">X</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>MinimumChildOffset.<span class="me1">Y</span> <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _alignReferencePoint.<span class="me1">Y</span> <span class="sy0">-=</span> MinimumChildOffset.<span class="me1">Y</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>MinimumChildOffset.<span class="me1">X</span> <span class="sy0">&gt;</span> <span class="nu0">0</span> <span class="sy0">||</span> MinimumChildOffset.<span class="me1">Y</span> <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bMeasureNecessary <span class="sy0">=</span> <span class="kw1">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> neededSize;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#if DEBUG</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw1">override</span> <span class="kw1">void</span> OnRender<span class="br0">&#40;</span>DrawingContext dc<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">base</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>dc<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; Rect r <span class="sy0">=</span> <span class="kw3">new</span> Rect<span class="br0">&#40;</span><span class="kw1">this</span>.<span class="me1">DesiredSize</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; dc.<span class="me1">DrawRectangle</span><span class="br0">&#40;</span><span class="kw1">null</span>, <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Brushes.<span class="me1">Tomato</span>, <span class="nu0">2.0</span><span class="br0">&#41;</span>, r<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// show the visual center</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; dc.<span class="me1">DrawEllipse</span><span class="br0">&#40;</span>Brushes.<span class="me1">SeaGreen</span>, <span class="kw1">null</span>, _alignReferencePoint, <span class="nu0">3</span>, <span class="nu0">3</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endif</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
As you can see, there are some hacks in here: We sometimes need to repeat measurement. We will later dig into that deeper; there are a number of unusual effects here.
</p>
<h3>Implementing a CircularPanel</h3>
<p>
The CircularPanel will arrange all items (more specifically, their centers or their align reference points) on a circle segment. The segments <code>StartAngle</code>, <code>EndAngle</code> and <code>Radius</code> can be customized using <code>DependencyProperties</code>, which automatically enables data binding and animation:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="co2">#region Dependency Properties</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#region StartAngle DP</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Category<span class="br0">&#40;</span><span class="st0">&quot;Arrange&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">@&#8221;Sets the angle in degrees where the first item will </span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp;be placed. 0 degrees points to the top.&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">double</span> StartAngle</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>GetValue<span class="br0">&#40;</span>StartAngleProperty<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; set <span class="br0">&#123;</span> SetValue<span class="br0">&#40;</span>StartAngleProperty, value<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">readonly</span> DependencyProperty StartAngleProperty <span class="sy0">=</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; DependencyProperty.<span class="me1">Register</span><span class="br0">&#40;</span><span class="st0">&quot;StartAngle&quot;</span>, <span class="kw3">typeof</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>, <span class="kw3">typeof</span><span class="br0">&#40;</span>CircularPanel<span class="br0">&#41;</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">new</span> FrameworkPropertyMetadata<span class="br0">&#40;</span>45d, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; FrameworkPropertyMetadataOptions.<span class="me1">AffectsArrange</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endregion</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#region EndAngle DP</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Category<span class="br0">&#40;</span><span class="st0">&quot;Arrange&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">@&#8221;Sets the angle in degrees where the last item will be placed. 0 degrees </span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp;points to the top. Note that this will be ignored if AngleSpacing is specified.&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>TypeConverterAttribute<span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>DoubleAutoConverter<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">double</span> EndAngle</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>GetValue<span class="br0">&#40;</span>EndAngleProperty<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; set <span class="br0">&#123;</span> SetValue<span class="br0">&#40;</span>EndAngleProperty, value<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">readonly</span> DependencyProperty EndAngleProperty <span class="sy0">=</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; DependencyProperty.<span class="me1">Register</span><span class="br0">&#40;</span><span class="st0">&quot;EndAngle&quot;</span>, <span class="kw3">typeof</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>, <span class="kw3">typeof</span><span class="br0">&#40;</span>CircularPanel<span class="br0">&#41;</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">new</span> FrameworkPropertyMetadata<span class="br0">&#40;</span><span class="kw4">Double</span>.<span class="me1">NaN</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; FrameworkPropertyMetadataOptions.<span class="me1">AffectsArrange</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endregion</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#region Radius DP</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Category<span class="br0">&#40;</span><span class="st0">&quot;Arrange&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">@&#8221;Sets the radius of the circle where children will be positioned on. </span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp;Note that the resulting panel might be siginificantly larger.&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">double</span> Radius</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>GetValue<span class="br0">&#40;</span>RadiusProperty<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; set <span class="br0">&#123;</span> SetValue<span class="br0">&#40;</span>RadiusProperty, value<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">readonly</span> DependencyProperty RadiusProperty <span class="sy0">=</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; DependencyProperty.<span class="me1">Register</span><span class="br0">&#40;</span><span class="st0">&quot;Radius&quot;</span>, <span class="kw3">typeof</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>, <span class="kw3">typeof</span><span class="br0">&#40;</span>CircularPanel<span class="br0">&#41;</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> FrameworkPropertyMetadata<span class="br0">&#40;</span>45d,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FrameworkPropertyMetadataOptions.<span class="me1">AffectsMeasure</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endregion</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#region AngleSpacing DP</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Category<span class="br0">&#40;</span><span class="st0">&quot;Arrange&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">@&#8221;Sets the number of degress between two items. When </span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp;set to &#39;auto&#39;, children will be arranged evenly distributed between </span></div>
</li>
<li class="li1">
<div class="de1"><span class="st0"> &nbsp; &nbsp;StartAngle and EndAngle.&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>TypeConverterAttribute<span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>DoubleAutoConverter<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">double</span> AngleSpacing</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; get <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>GetValue<span class="br0">&#40;</span>AngleSpacingProperty<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; set <span class="br0">&#123;</span> SetValue<span class="br0">&#40;</span>AngleSpacingProperty, value<span class="br0">&#41;</span>; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">readonly</span> DependencyProperty AngleSpacingProperty <span class="sy0">=</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; DependencyProperty.<span class="me1">Register</span><span class="br0">&#40;</span><span class="st0">&quot;AngleSpacing&quot;</span>, <span class="kw3">typeof</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">typeof</span><span class="br0">&#40;</span>CircularPanel<span class="br0">&#41;</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> FrameworkPropertyMetadata<span class="br0">&#40;</span>45d, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FrameworkPropertyMetadataOptions.<span class="me1">AffectsArrange</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endregion</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endregion</span></div>
</li>
</ol>
</div>
<p>
For the CircularPanel, the <code>MeasureOverride()</code> method looks like this:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">protected</span> <span class="kw1">override</span> Size MeasureOverride<span class="br0">&#40;</span>Size availableSize<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; Size size <span class="sy0">=</span> <span class="kw3">new</span> Size<span class="br0">&#40;</span><span class="kw4">Double</span>.<span class="me1">PositiveInfinity</span>, <span class="kw4">Double</span>.<span class="me1">PositiveInfinity</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; Size resultSize <span class="sy0">=</span> <span class="kw3">new</span> Size<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">this</span>.<span class="me1">Children</span> <span class="sy0">==</span> <span class="kw1">null</span> <span class="sy0">||</span> <span class="kw1">this</span>.<span class="me1">Children</span>.<span class="me1">Count</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> resultSize;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; RecalcParams<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw4">int</span> iCurrentChildIndex <span class="sy0">=</span> <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; dXMax <span class="sy0">=</span> <span class="kw4">Double</span>.<span class="me1">MinValue</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; dYMax <span class="sy0">=</span> <span class="kw4">Double</span>.<span class="me1">MinValue</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; dXMin <span class="sy0">=</span> <span class="kw4">Double</span>.<span class="me1">MaxValue</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; dYMin <span class="sy0">=</span> <span class="kw4">Double</span>.<span class="me1">MaxValue</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span>UIElement child <span class="kw1">in</span> Children<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw4">double</span> dAngle <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span><span class="br0">&#40;</span>iCurrentChildIndex<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">*</span> dRenderAngleSpacing </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">+</span> StartAngle;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw4">double</span> dX <span class="sy0">=</span> &nbsp;dRenderRadius <span class="sy0">*</span> Math.<span class="me1">Sin</span><span class="br0">&#40;</span>dAngle <span class="sy0">*</span> dDegToRad<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// We invert the Y coordinate, because the origin in controls </span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// is the upper left corner, rather than the lower left</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw4">double</span> dY <span class="sy0">=</span> <span class="sy0">-</span>dRenderRadius <span class="sy0">*</span> Math.<span class="me1">Cos</span><span class="br0">&#40;</span>dAngle <span class="sy0">*</span> dDegToRad<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; child.<span class="me1">Measure</span><span class="br0">&#40;</span>size<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; Point visualCenter <span class="sy0">=</span> <span class="kw3">new</span> Point<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>child <span class="kw3">is</span> ICustomAlignedControl<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; ICustomAlignedControl mkchild <span class="sy0">=</span> <span class="br0">&#40;</span>ICustomAlignedControl<span class="br0">&#41;</span>child;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; visualCenter.<span class="me1">X</span> <span class="sy0">=</span> mkchild.<span class="me1">AlignReferencePoint</span>.<span class="me1">X</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; visualCenter.<span class="me1">Y</span> <span class="sy0">=</span> mkchild.<span class="me1">AlignReferencePoint</span>.<span class="me1">Y</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">else</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; visualCenter.<span class="me1">X</span> <span class="sy0">=</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Width</span> <span class="sy0">*</span> <span class="nu0">0.5</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; visualCenter.<span class="me1">Y</span> <span class="sy0">=</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Height</span> <span class="sy0">*</span> <span class="nu0">0.5</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dXMax <span class="sy0">=</span> Math.<span class="me1">Max</span><span class="br0">&#40;</span>dXMax, dX <span class="sy0">+</span> <span class="br0">&#40;</span>child.<span class="me1">DesiredSize</span>.<span class="me1">Width</span> <span class="sy0">-</span> visualCenter.<span class="me1">X</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dYMax <span class="sy0">=</span> Math.<span class="me1">Max</span><span class="br0">&#40;</span>dYMax, dY <span class="sy0">+</span> <span class="br0">&#40;</span>child.<span class="me1">DesiredSize</span>.<span class="me1">Height</span> <span class="sy0">-</span> visualCenter.<span class="me1">Y</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dXMin <span class="sy0">=</span> Math.<span class="me1">Min</span><span class="br0">&#40;</span>dXMin, dX <span class="sy0">-</span> <span class="br0">&#40;</span>visualCenter.<span class="me1">X</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dYMin <span class="sy0">=</span> Math.<span class="me1">Min</span><span class="br0">&#40;</span>dYMin, dY <span class="sy0">-</span> <span class="br0">&#40;</span>visualCenter.<span class="me1">Y</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; iCurrentChildIndex<span class="sy0">++</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; resultSize.<span class="me1">Width</span> <span class="sy0">=</span> dXMax <span class="sy0">-</span> dXMin;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; resultSize.<span class="me1">Height</span> <span class="sy0">=</span> dYMax <span class="sy0">-</span> dYMin;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">return</span> resultSize;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">private</span> Vector GetChildOffset<span class="br0">&#40;</span>UIElement child, <span class="kw4">double</span> dAngle<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; Vector Offset <span class="sy0">=</span> <span class="kw3">new</span> Vector<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>child <span class="kw3">is</span> ICustomAlignedControl<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; ICustomAlignedControl mkchild <span class="sy0">=</span> <span class="br0">&#40;</span>ICustomAlignedControl<span class="br0">&#41;</span>child;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; Offset.<span class="me1">X</span> <span class="sy0">=</span> &nbsp;dRenderRadius <span class="sy0">*</span> Math.<span class="me1">Sin</span><span class="br0">&#40;</span>dAngle <span class="sy0">*</span> dDegToRad<span class="br0">&#41;</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="sy0">-</span> dXMin <span class="sy0">-</span> mkchild.<span class="me1">AlignReferencePoint</span>.<span class="me1">X</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; Offset.<span class="me1">Y</span> <span class="sy0">=</span> <span class="sy0">-</span>dRenderRadius <span class="sy0">*</span> Math.<span class="me1">Cos</span><span class="br0">&#40;</span>dAngle <span class="sy0">*</span> dDegToRad<span class="br0">&#41;</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="sy0">-</span> dYMin <span class="sy0">-</span> mkchild.<span class="me1">AlignReferencePoint</span>.<span class="me1">Y</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">else</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; Offset.<span class="me1">X</span> <span class="sy0">=</span> &nbsp;dRenderRadius <span class="sy0">*</span> Math.<span class="me1">Sin</span><span class="br0">&#40;</span>dAngle <span class="sy0">*</span> dDegToRad<span class="br0">&#41;</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="sy0">-</span> dXMin <span class="sy0">-</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Width</span> <span class="sy0">*</span> <span class="nu0">0.5</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; Offset.<span class="me1">Y</span> <span class="sy0">=</span> <span class="sy0">-</span>dRenderRadius <span class="sy0">*</span> Math.<span class="me1">Cos</span><span class="br0">&#40;</span>dAngle <span class="sy0">*</span> dDegToRad<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">-</span> dYMin <span class="sy0">-</span> child.<span class="me1">DesiredSize</span>.<span class="me1">Height</span> <span class="sy0">*</span> <span class="nu0">0.5</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">return</span> Offset;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
First of all, note that the maximum and minimum X and Y coordinates will be used to determine the size of the resulting control. The idea here is that the CircularPanel does not need to be large enough for a full circle. You might even choose to use the CircularPanel in a different context with very large radius to achieve a completely different effect:
</p>
<p><img src="http://www.emphess.net/wp-content/uploads/2008/05/CircularPanel1.jpg" alt="CircularPanel Screenshot" /></p>
<p>
Note the border which is, as promised, only as large as necessary to hold the children. The circle segment which is visible is a little debugging helper. Let&#8217;s add these fancy lines and circles to the <code>OnRender()</code> method:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="co2">#if DEBUG</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">protected</span> <span class="kw1">override</span> <span class="kw1">void</span> OnRender<span class="br0">&#40;</span>DrawingContext dc<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">base</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>dc<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw5">System</span>.<span class="me1">Windows</span>.<span class="me1">Media</span>.<span class="me1">Pen</span> p <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> <span class="kw5">System</span>.<span class="me1">Windows</span>.<span class="me1">Media</span>.<span class="me1">Pen</span><span class="br0">&#40;</span><span class="kw5">System</span>.<span class="me1">Windows</span>.<span class="me1">Media</span>.<span class="me1">Brushes</span>.<span class="me1">LightBlue</span>, <span class="nu0">2.0</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dc.<span class="me1">DrawRectangle</span><span class="br0">&#40;</span><span class="kw1">null</span>, p, <span class="kw3">new</span> Rect<span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">0</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; DesiredSize.<span class="me1">Width</span> <span class="sy0">-</span> Margin.<span class="me1">Left</span> <span class="sy0">-</span> Margin.<span class="me1">Right</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; DesiredSize.<span class="me1">Height</span> <span class="sy0">-</span> Margin.<span class="me1">Top</span> <span class="sy0">-</span> Margin.<span class="me1">Bottom</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dc.<span class="me1">DrawEllipse</span><span class="br0">&#40;</span><span class="kw1">null</span>, p, AlignReferencePoint, dRenderRadius, dRenderRadius<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dc.<span class="me1">DrawEllipse</span><span class="br0">&#40;</span><span class="kw1">null</span>, p, AlignReferencePoint, <span class="nu0">1.0</span>, <span class="nu0">1.0</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endif</span></div>
</li>
</ol>
</div>
<p>
A note on this one: Using the <code>DesiredSize</code>, we can determine and debug whether our measure method works as expected. However, when clipped, this value will not decrease, so the border will just be clipped partially just like the rest of the control. Sice <code>DesiredSize</code> includes <code>Margin</code>, we have to subtract the value if we want to see the minimum size in this case. You also may want to draw additional <code>Rect</code>s for debugging purposes, namely:</p>
<ul>
<li><code>Rect r = LayoutInformation.GetLayoutSlot(this);</code> This is all available space (might be larger or smaller than <code>DesiredSize</code>) including <code>Margin</code></li>
<li><code>RenderSize</code> This is all available space (again larger or smaller than <code>DesiredSize</code>), not including margin</li>
</ul>
<p>A simple CircularPanel in debug mode now looks like this:
</p>
<p><img src="http://www.emphess.net/wp-content/uploads/2008/05/CircularPanel2.jpg" alt="Screenshot of a CircularPanel showing a full circle." /></p>
<p>
The CircularPanel provided here is still very simple, because it does not provide support realignment, re-scaling, different positioning modes, etc. However, adding that functionality is straightforward, and the panel is more elaborate than many others I found on the net. Furthermore, our CircularPanel makes some assumptions here, namely that it centers all children unless they implement the <code>ICustomAlignedControl</code> interface.
</p>
<h3>The MenuKillerItem</h3>
<p>
First, we have to decide whether we customize an existing control, create a <code>UserControl</code> or create a custom control. Since we need quite special behaviour and want the control to be re-templateable, we choose a custom control. When creating a custom control, there is no designer support (nonsense in this case, anyway) and the control will be derived from an existing control or a control base class, rather than from <code>UserControl</code>. A custom control will have a default template which is stored in <code>Themes/Generic.xaml</code>.
</p>
<p>
As previously mentioned, the <code>MenuKillerItem</code> will have to be an <code>ItemsControl</code> so it can hold a number of children. We also like it to have an <code>Expanded</code> property and a <code>Header</code>, so we derive this from <code>TreeViewItem</code>, where we get both of the last for free. With the components we have created before, we can start creating the core functionality of the future MenuKiller control within the <code>MenuKillerItem</code>. Since the whole MenuKiller has a recursive structure, most of the work is done in the <code>MenuKillerItems</code>, rather than in the <code>MenuKiller</code> class.
</p>
<p>
Additionally, we want the <code>MenuKillerItem</code> to report where its <code>Header</code> is positioned, so we have to implement <code>ICustomAlignedControl</code>, too.
</p>
<p>
Moreover, sticking to the approach which has a <code>Button</code> in its template, we need to assign a <code>Command</code> to the <code>MenuKillerItem</code>. In doing so, we expect the <code>MenuKillerItem</code> to be able to trigger that associated command. To do so, it needs to implement <code>ICommandSource</code>. Thus, our class defition reads:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">class</span> MenuKillerItem <span class="sy0">:</span> TreeViewItem, ICommandSource, ICustomAlignedControl</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// &#8230;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h4>Putting it together</h4>
<p>
The <code>MenuKillerItem</code> will consist of a <code>Button</code> which can be used to toggle expansion (a node), or to send a specific application command (a leaf), and a <code>CircularPanel</code>, which presents children if they exist and the <code>MenuKillerItem</code> is expanded. Since we want the Button to be in the center of the circle segment, we enclose both in a <code>ReferenceAlignPanel</code>, which does all the hard work for us.
</p>
<p>
Sadly, we need to know these components in the code (Footnote: This is not entirely true, at least the <code>Button</code> can easily be removed. For this article, I chose the simpler option, though). Therefore, we have to introduce some kind of contract between the default template defined in <code>Generic.xaml</code> and the code. We do this by giving those controls a special name, per convention prefixed with <code>PART_</code>. Let&#8217;s have a look at the <code>MenuKillerItem</code>s default template:
</p>
<div class="geshi no xaml">
<ol>
<li class="li1">
<div class="de1">&lt;!&#8211; Some things stripped out &#8211;&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;ControlTemplate x:Key=&quot;MenuKillerItemTemplate&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TargetType=&quot;local:MenuKillerItem&quot;&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;local:ReferenceAlignPanel x:Name=&quot;PART_AlignPanel&quot; &gt; &nbsp; &nbsp; &nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &lt;Button x:Name=&quot;PART_Button&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Style=&quot;{StaticResource MenuKillerBtnStyle}&quot;&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &lt;ContentPresenter ContentSource=&quot;Header&quot; /&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &lt;/Button&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &lt;local:CircularPanel x:Name=&quot;PART_Panel&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IsItemsHost=&quot;True&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Visibility=&quot;&#8230;&quot; /&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;/local:ReferenceAlignPanel&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;/ControlTemplate&gt;</div>
</li>
</ol>
</div>
<p>
Let&#8217;s take a close look at this. The first line is trivial: It creates a <code>ControlTemplate</code> for the <code>MenuKillerItem</code>. (Applying the template, however, can be a little tricky. See <a href="http://www.emphess.net/2008/04/07/applying-itemcontainerstyle-recursively/">my blog post on this</a>).
</p>
<p>
Everything in the control is then placed in a <code>ReferenceAlignPanel</code>, which will arrange the items in the desired fashion. Since we need to know this control in the code, we give it a <code>PART_</code>-prefix and call it <code>PART_AlignPanel</code>.
</p>
<p>
In the <code>ReferenceAlignPanel</code>, we place a <code>Button</code>, which we simply call <code>PART_Button</code> and apply a certain style to it. What the style looks like is not important right now. This merely makes sure the hover behaviour of the buttons is the same. As previously mentioned, the button does not need to be part of the generic template, but it simplifies using the control a little. Since we don&#8217;t want to restrict the contents of the button, we simply put a <code>ContentPresenter</code> in it which will put all content from the <code>TreeViewItem.Header</code> into it.
</p>
<p>
The <code>CircularPanel</code> is now added, again with <code>PART_</code>-prefix. Since we want all <code>TreeViewItem.Items</code> to appear in it, we set <code>IsItemsHost</code> to <code>true</code>. The <code>Visibility</code>, of course, shall depend on the <code>TreeView.IsExpanded</code> state. We&#8217;ll cover that later.
</p>
<p>
We have now created our default control template in <code>generic.xaml</code>, where the control has three <code>PART_</code>s. Here&#8217;s how we access them from code so we can use them later:</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">override</span> <span class="kw1">void</span> OnApplyTemplate<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">base</span>.<span class="me1">OnApplyTemplate</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mCenterButton <span class="sy0">=</span> Template.<span class="me1">FindName</span><span class="br0">&#40;</span><span class="st0">&quot;PART_Button&quot;</span>, <span class="kw1">this</span><span class="br0">&#41;</span> <span class="kw1">as</span> Button;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> mCenterButton<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; mCenterButton.<span class="me1">Click</span> <span class="sy0">+=</span> <span class="kw3">new</span> <span class="kw5">System</span>.<span class="me1">Windows</span>.<span class="me1">RoutedEventHandler</span><span class="br0">&#40;</span>mCenterButton_Click<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; mCenterButton.<span class="me1">MouseEnter</span> <span class="sy0">+=</span> <span class="kw3">new</span> MouseEventHandler<span class="br0">&#40;</span>MenuKillerItem_MouseEnter<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mPanel <span class="sy0">=</span> Template.<span class="me1">FindName</span><span class="br0">&#40;</span><span class="st0">&quot;PART_Panel&quot;</span>, <span class="kw1">this</span><span class="br0">&#41;</span> <span class="kw1">as</span> CircularPanel;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mAlignPanel <span class="sy0">=</span> Template.<span class="me1">FindName</span><span class="br0">&#40;</span><span class="st0">&quot;PART_AlignPanel&quot;</span>, <span class="kw1">this</span><span class="br0">&#41;</span> <span class="kw1">as</span> ReferenceAlignPanel;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> mPanel<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; mPanel.<span class="me1">ChildArranged</span> <span class="sy0">+=</span> <span class="kw3">new</span> CircularPanel.<span class="me1">OnChildArranged</span><span class="br0">&#40;</span>mPanel_ChildArranged<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
An important note: Do not use <code>GetTemplateChild()</code>, because it will only find direct descendants. Also refer to the <a href="http://msdn2.microsoft.com/en-us/library/system.windows.frameworkelement.gettemplatechild.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/msdn2.microsoft.com');">MSDN Comment of <code>GetTemplateChild()</code></a>. IntelliSense should also tell you that its use is deprecated. This is a common mistake and it severly limits the extensibility and customizeability of the control.
</p>
<p>
I introduced this section with &#8220;sadly&#8221;. Why that? Well, the problem with this kind of dependency is that is somewhat error prone and hidden. It also creates a very tight coupling. However, the reasons for this lie largely in the problem domain: We need these controls to exist, otherwise the control cannot implement the behaviour it is expected to. We can at least loosen the coupling a little by providing interfaces here, that is, we don&#8217;t require a <code>CircularPanel</code> for example, but only an <code>ICircularPanel</code> which can then be re-implemented by the control user. This enhances extensibility at little cost, but here, customization is going very far.
</p>
<p>
In order to enhance visibility of this contract, there is the <code>TemplatePart</code> attribute, which should be applied to the class:</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>TemplatePart<span class="br0">&#40;</span>Name <span class="sy0">=</span> <span class="st0">&quot;PART_Button&quot;</span>, Type <span class="sy0">=</span> <span class="kw3">typeof</span><span class="br0">&#40;</span>Button<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>TemplatePart<span class="br0">&#40;</span>Name <span class="sy0">=</span> <span class="st0">&quot;PART_Panel&quot;</span>, Type <span class="sy0">=</span> <span class="kw3">typeof</span><span class="br0">&#40;</span>CircularPanel<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>TemplatePart<span class="br0">&#40;</span>Name <span class="sy0">=</span> <span class="st0">&quot;PART_AlignPanel&quot;</span>, Type <span class="sy0">=</span> <span class="kw3">typeof</span><span class="br0">&#40;</span>ReferenceAlignPanel<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">class</span> MenuKillerItem <span class="sy0">:</span> TreeViewItem, ICommandSource, ICustomAlignedControl</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// &#8230;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
The attribute doesn&#8217;t change anything in terms of behaviour, but it adds meta information which is available to programs such as Expression Blend.
</p>
<p>
The code snippet above also shows the first reasons why we need to identify these controls: We want to be notified of <code>MouseEnter</code> and of <code>Click</code> events on the <code>Button</code>. The latter activates the command that is associated with this <code>MenuKillerItem</code>, or toggles expanson:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">void</span> mCenterButton_Click<span class="br0">&#40;</span><span class="kw4">object</span> sender, <span class="kw5">System</span>.<span class="me1">Windows</span>.<span class="me1">RoutedEventArgs</span> e<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">this</span>.<span class="me1">mPanel</span>.<span class="me1">Children</span>.<span class="me1">Count</span> <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; MenuKillerCommands.<span class="me1">OpenCategory</span>.<span class="me1">Execute</span><span class="br0">&#40;</span><span class="kw1">null</span>, <span class="kw1">this</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">else</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Command <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; RoutedCommand command <span class="sy0">=</span> Command <span class="kw1">as</span> RoutedCommand;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>command <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; command.<span class="me1">Execute</span><span class="br0">&#40;</span>CommandParameter, CommandTarget<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">else</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>ICommand<span class="br0">&#41;</span>Command<span class="br0">&#41;</span>.<span class="me1">Execute</span><span class="br0">&#40;</span>CommandParameter<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
Note that there are esentially two different ways to execute the <code>Command</code>, depending on its type. Also note that we also implement the expansion using a custom routed command. This is convenient, since there is little overhead but it improves extensibility by providing a mechanism to programatically trigger expansion from the outside.
</p>
<h4>Custom Commands</h4>
<p>
Declaring a custom command is very easy:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">class</span> MenuKillerCommands</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">readonly</span> RoutedUICommand ToggleExpansion <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> RoutedUICommand<span class="br0">&#40;</span><span class="st0">&quot;ToggleExpansion&quot;</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;ToggleExpansion&quot;</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">typeof</span><span class="br0">&#40;</span>MenuKillerCommands<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
However, we also need to create a <code>CommandBinding</code> in the static constructor of the <code>MenuKillerItem</code>:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">static</span> MenuKillerItem<span class="br0">&#40;</span><span class="br0">&#41;</span> &nbsp; &nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; DefaultStyleKeyProperty.<span class="me1">OverrideMetadata</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw3">new</span> FrameworkPropertyMetadata<span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; CommandBinding binding <span class="sy0">=</span> <span class="kw3">new</span> CommandBinding<span class="br0">&#40;</span>MenuKillerCommands.<span class="me1">ToggleExpansion</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; binding.<span class="me1">Executed</span> <span class="sy0">+=</span> <span class="kw3">new</span> ExecutedRoutedEventHandler<span class="br0">&#40;</span>ToggleCommandHandler<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; binding.<span class="me1">CanExecute</span> <span class="sy0">+=</span> <span class="kw3">new</span> CanExecuteRoutedEventHandler<span class="br0">&#40;</span>CanToggleHandler<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; CommandManager.<span class="me1">RegisterClassCommandBinding</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span>, binding<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">private</span> <span class="kw1">static</span> <span class="kw1">void</span> ToggleCommandHandler<span class="br0">&#40;</span><span class="kw4">object</span> target, ExecutedRoutedEventArgs e<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> target <span class="sy0">&amp;&amp;</span> target <span class="kw3">is</span> MenuKillerItem<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span>target<span class="br0">&#41;</span>.<span class="me1">ToggleExpand</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">private</span> <span class="kw1">static</span> <span class="kw1">void</span> CanToggleHandler<span class="br0">&#40;</span><span class="kw4">object</span> target, CanExecuteRoutedEventArgs e<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> target <span class="sy0">&amp;&amp;</span> target <span class="kw3">is</span> MenuKillerItem<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; e.<span class="me1">CanExecute</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span>target<span class="br0">&#41;</span>.<span class="me1">CanToggleExpand</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
The command then simply calls <code>ToggleExpand</code> on the target <code>MenuKillerItem</code>.
</p>
<h4>Expanding a Node</h4>
<p>
Now, what happens when we open a node? Essentially, we have to set the <code>TreeViewItem.Expanded</code> property. Databinding will the show the circular panel, and the <code>ReferenceAlignPanel</code> makes sure alignment is OK&#8230; But, wait a second, doesn&#8217;t that imply that the size of this control changes? Yes, but worst of all, this change propagates to the root of the tree:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">void</span> InvalidateTreeMeasure<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; InvalidateMeasure<span class="br0">&#40;</span><span class="br0">&#41;</span>; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; mPanel.<span class="me1">InvalidateMeasure</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mAlignPanel.<span class="me1">InvalidateMeasure</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Parent <span class="kw3">is</span> MenuKillerItem<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span>Parent<span class="br0">&#41;</span>.<span class="me1">InvalidateTreeMeasure</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h4>Measure and Arrange in the MKI</h4>
<p>
Fortunately, since the <code>ReferenceAlignPanel</code> and the <code>CircularPanel</code> do all the gritty work for us, the <code>MeasureOverride</code> of the <code>MenuKillerItem</code> is very simple:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">protected</span> <span class="kw1">override</span> Size MeasureOverride<span class="br0">&#40;</span>Size constraint<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// Beware of all this allocations, they are not necessary</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; Size infSize <span class="sy0">=</span> <span class="kw3">new</span> Size<span class="br0">&#40;</span><span class="kw4">Double</span>.<span class="me1">PositiveInfinity</span>, <span class="kw4">Double</span>.<span class="me1">PositiveInfinity</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mCenterButton.<span class="me1">Measure</span><span class="br0">&#40;</span>infSize<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mAlignPanel.<span class="me1">AlignReferencePoint</span> <span class="sy0">=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw3">new</span> Point<span class="br0">&#40;</span>mCenterButton.<span class="me1">DesiredSize</span>.<span class="me1">Width</span> <span class="sy0">*</span> <span class="nu0">0.5</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; mCenterButton.<span class="me1">DesiredSize</span>.<span class="me1">Height</span> <span class="sy0">*</span> <span class="nu0">0.5</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mPanel.<span class="me1">Measure</span><span class="br0">&#40;</span>infSize<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; mAlignPanel.<span class="me1">Measure</span><span class="br0">&#40;</span>infSize<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">return</span> <span class="kw1">base</span>.<span class="me1">MeasureOverride</span><span class="br0">&#40;</span>constraint<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
There is not even an <code>ArrangeOverride</code>! However, when a new <code>MenuKillerItem</code> is opened, we might want to tell it which direction it should open to. Because we can&#8217;t get that information easily, we simply have the <code>CircularPanel</code> notify us about its arrangements. In <code>OnApplyTemplate</code>, we already registered to the event. Here comes the implementation:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">override</span> <span class="kw1">void</span> OnApplyTemplate<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="co1">// &#8230;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> mPanel<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; mPanel.<span class="me1">ChildArranged</span> <span class="sy0">+=</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">new</span> CircularPanel.<span class="me1">OnChildArranged</span><span class="br0">&#40;</span>mPanel_ChildArranged<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">void</span> mPanel_ChildArranged<span class="br0">&#40;</span><span class="kw4">object</span> sender, UIElement child, <span class="kw4">double</span> angle<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; MenuKillerItem childItem <span class="sy0">=</span> child <span class="kw1">as</span> MenuKillerItem;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; childItem.<span class="me1">mPanel</span>.<span class="me1">AngleSpacing</span> <span class="sy0">=</span> <span class="kw4">Double</span>.<span class="me1">NaN</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// These values should not be hardcoded, of course</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; childItem.<span class="me1">mPanel</span>.<span class="me1">StartAngle</span> <span class="sy0">=</span> angle <span class="sy0">-</span> <span class="nu0">45.0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; childItem.<span class="me1">mPanel</span>.<span class="me1">EndAngle</span> <span class="sy0">=</span> angle <span class="sy0">+</span> <span class="nu0">45.00</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h4>Opacity Issues</h4>
<p>Next, we want to dial down the opacity of the parent control&#8217;s button and all siblings to indicate which &#8216;path&#8217; is active in a visual manner. Unfortunately, there is an &#8216;opacity stack&#8217;, which makes it <a href="http://www.emphess.net/2008/04/10/on-uielementopacity-and-the-removal-of-storyboards/">impossible to create a child element which is less transparent than its parent</a>. So we have to come up with a little helper method:</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">void</span> SetChildrenOpacity<span class="br0">&#40;</span>UIElement exception, <span class="kw4">double</span> dOpacity<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">foreach</span><span class="br0">&#40;</span>UIElement elemRover <span class="kw1">in</span> mPanel.<span class="me1">Children</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>elemRover <span class="sy0">!=</span> exception<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; elemRover.<span class="me1">Opacity</span> <span class="sy0">=</span> dOpacity;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">void</span> SetOpacityRecursively<span class="br0">&#40;</span><span class="kw4">int</span> iLevel<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// 2.0 seemed a little too much. One might want this to be configureable</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw4">double</span> dTargetOp <span class="sy0">=</span> <span class="nu0">1.0</span> <span class="sy0">/</span> Math.<span class="me1">Pow</span><span class="br0">&#40;</span><span class="nu0">1.4</span>, iLevel<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Parent <span class="kw3">is</span> MenuKillerItem<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span>Parent<span class="br0">&#41;</span>.<span class="me1">SetChildrenOpacity</span><span class="br0">&#40;</span><span class="kw1">this</span>, dTargetOp<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span>Parent<span class="br0">&#41;</span>.<span class="me1">SetOpacityRecursively</span><span class="br0">&#40;</span><span class="sy0">++</span>iLevel<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; mCenterButton.<span class="me1">Opacity</span> <span class="sy0">=</span> dTargetOp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<h3>The Tool Tip</h3>
<p>
We&#8217;re almost done!
</p>
<p>
There&#8217;s one thing left, however: The &#8216;tool tip&#8217; which is presented on the center button. This is meant to provide information about the button the mouse is currently over. So there are esentially two small problems to solve here: </p>
<ol>
<li>Identify the button that is under the mouse currently and retrieve its tooltip</li>
<li>Present the tool tip</li>
</ol>
<p>To find the item that is currently under the mouse, we have to get back to our template <code>PART_</code>s. We already registered a <code>MouseEnter</code> handler in the <code>MenuKillerItem</code> </p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">void</span> MenuKillerItem_MouseEnter<span class="br0">&#40;</span><span class="kw4">object</span> o, MouseEventArgs e<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; Button sender <span class="sy0">=</span> o <span class="kw1">as</span> Button;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> sender<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; sender.<span class="me1">RaiseEvent</span><span class="br0">&#40;</span><span class="kw3">new</span> RoutedEventArgs<span class="br0">&#40;</span>MenuKillerItem.<span class="me1">MouseHoverEvent</span>, <span class="kw1">this</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
The event raised in here is a custom one with a very bad (i.e. misleading, already existing) name:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="co2">#region Attached Event MouseHover</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">readonly</span> RoutedEvent MouseHoverEvent <span class="sy0">=</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; EventManager.<span class="me1">RegisterRoutedEvent</span><span class="br0">&#40;</span><span class="st0">&quot;MouseHover&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RoutingStrategy.<span class="me1">Bubble</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">typeof</span><span class="br0">&#40;</span>RoutedEventHandler<span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">typeof</span><span class="br0">&#40;</span>MenuKillerItem<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">void</span> AddMouseHoverHandler<span class="br0">&#40;</span>DependencyObject o, RoutedEventHandler handler<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>UIElement<span class="br0">&#41;</span>o<span class="br0">&#41;</span>.<span class="me1">AddHandler</span><span class="br0">&#40;</span>MenuKillerItem.<span class="me1">MouseHoverEvent</span>, handler<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">void</span> RemoveMouseHoverHandler<span class="br0">&#40;</span>DependencyObject o, RoutedEventHandler handler<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>UIElement<span class="br0">&#41;</span>o<span class="br0">&#41;</span>.<span class="me1">RemoveHandler</span><span class="br0">&#40;</span>MenuKillerItem.<span class="me1">MouseHoverEvent</span>, handler<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endregion</span></div>
</li>
</ol>
</div>
<p>
In order to make this available to the root <code>MenuKiller</code>, we have to have the <code>MenuKiller</code> catch the event as soon as it bubbles up and implement a <code>DependencyProperty</code> which makes the current &#8216;tool tip&#8217; available to the outside:
</p>
<div class="geshi no csharp">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">void</span> HandleMouseHover<span class="br0">&#40;</span><span class="kw4">object</span> sender, RoutedEventArgs rea<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> rea<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; MenuKillerItem mki <span class="sy0">=</span> rea.<span class="me1">OriginalSource</span> <span class="kw1">as</span> MenuKillerItem;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">null</span> <span class="sy0">!=</span> mki<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; HoverToolTip <span class="sy0">=</span> mki.<span class="me1">RootToolTip</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">readonly</span> DependencyProperty HoverToolTipProperty <span class="sy0">=</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; DependencyProperty.<span class="me1">Register</span><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;HoverToolTip&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">typeof</span><span class="br0">&#40;</span><span class="kw4">object</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">typeof</span><span class="br0">&#40;</span>MenuKiller<span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> PropertyMetadata<span class="br0">&#40;</span><span class="kw1">null</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw4">object</span> HoverToolTip</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; get</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw4">object</span><span class="br0">&#41;</span>GetValue<span class="br0">&#40;</span>HoverToolTipProperty<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; set</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; SetValue<span class="br0">&#40;</span>HoverToolTipProperty, value<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">public</span> <span class="kw1">override</span> <span class="kw1">void</span> OnApplyTemplate<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">base</span>.<span class="me1">OnApplyTemplate</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; AddHandler<span class="br0">&#40;</span>MenuKillerItem.<span class="me1">MouseHoverEvent</span>, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw3">new</span> RoutedEventHandler<span class="br0">&#40;</span>HandleMouseHover<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>
As you can see, there is no template <code>PART_</code> that actually displays the tool tip. This is simply because I wanted to allow rich content within the tool tip (thus it is of type <code>object</code>) and I believe this to be a common modification. Requiring the control user to re-template the control just to change the appearance (or worse, the position) of the tool tip seems annoying.
</p>
<p>
Finally adding the tool tip in the actual &#8216;users&#8217; window markup is straightforward:
</p>
<div class="geshi no xaml">
<ol>
<li class="li1">
<div class="de1">&lt;mk:ReferenceAlignPanel&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;mk:MenuKiller &nbsp;Margin=&quot;2,2,2,2&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x:Name=&quot;MKRoot&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HoverToolTip=&quot;Default Value&quot;&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &lt;!&#8211; &#8230;. &#8211;&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;/mk:MenuKiller&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;TextBox &nbsp;Text=&quot;{Binding Path=HoverToolTip, ElementName=MKRoot, Mode=OneWay}&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width=&quot;128&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HorizontalAlignment=&quot;Left&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TextAlignment=&quot;Center&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; VerticalAlignment=&quot;Top&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Height=&quot;20px&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BorderThickness=&quot;0px&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsHitTestVisible=&quot;False&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Background=&quot;Transparent&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Margin=&quot;0, 192, 0,0&quot;/&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;/mk:ReferenceAlignPanel&gt;</div>
</li>
</ol>
</div>
<p>
As you can see, I chose a simple <code>TextBox</code>, although the system allows me to use images, too. The <code>Binding</code> to the <code>MenuKiller</code>&#8217;s <code>DependencyProperty HoverToolTip</code> does the job, the rest is merely a description of the desired appearance. The <code>Margin</code> makes the <code>TextBox</code> appear beneath the center.
</p>
<h2>Conclusion</h2>
<p>The MenuKiller Control offers a very different way of user interaction. With the introduction of WPF, the creation of this control has been simplified while keeping it customizeable at the same time. The use of databinding even allows to decouple parts of the control completely (e.g. tool tip box), thereby overcoming the issue of retemplating which usually requires to replace the whole template instead of replacing only specific parts.</p>
<p>The development of this control has taken a lof of iterations. For me, this was highly educating and a lot of fun. I hope to have contributed a little to a new discussion and new thinking in user interface design, while also providing a resource on how to develop custom WPF controls.</p>
<h2>Open Questions, Todos</h2>
<p>This control can certainly be optimized in various ways. There is still a lot of work to do to make this control really nice. For example, &#8216;adaptive arrange&#8217; is certainly necessary in some cases, furthermore, every modification to the arrangement could be animated for some eye candy. There is a lot to do terms of features and integration with <code>Popup</code>s, for example.</p>
<p>What matter most, though, is experience in using this control in a real world application. Customer and end-user feedback are required to help making this control what it is supposed to be one day: A fast, flexible, intuitive and context sensitive control with a small amount of text and happy end-user.</p>
<h2>Resources</h2>
<p>In the making&#8230;</p>
<h2>History</h2>
<ul>
<li>2008-05-04 v. 1.0 Initial release on emphess.net</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.emphess.net/2008/05/04/a-menukiller-control-draft/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Prism 10933</title>
		<link>http://www.emphess.net/2008/04/30/prism-10933/</link>
		<comments>http://www.emphess.net/2008/04/30/prism-10933/#comments</comments>
		<pubDate>Wed, 30 Apr 2008 19:35:16 +0000</pubDate>
		<dc:creator>Christoph Menge</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Prism]]></category>

		<guid isPermaLink="false">http://www.emphess.net/?p=35</guid>
		<description><![CDATA[A new Prism drop has just been released:
http://www.codeplex.com/prism/SourceControl/DownloadSourceCode.aspx?changeSetId=10933
The current prism drop comes with a neat documentation. Unfortunately, I won&#8217;t be able to check it out for the next few days&#8230;
The StockTraderRI now looks like this: .
]]></description>
			<content:encoded><![CDATA[<p>A new Prism drop has just been released:</p>
<p><a href="http://www.codeplex.com/prism/SourceControl/DownloadSourceCode.aspx?changeSetId=10933" onclick="javascript:pageTracker._trackPageview ('/outbound/www.codeplex.com');">http://www.codeplex.com/prism/SourceControl/DownloadSourceCode.aspx?changeSetId=10933</a></p>
<p>The current prism drop comes with a neat documentation. Unfortunately, I won&#8217;t be able to check it out for the next few days&#8230;</p>
<p>The StockTraderRI now looks like this: <a href="http://www.emphess.net/wp-content/uploads/2008/04/prismri.jpg" target="_blank"><img width="600" src="http://www.emphess.net/wp-content/uploads/2008/04/prismri.jpg" alt="Prism Reference Implementation Screenshot"/></a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.emphess.net/2008/04/30/prism-10933/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Protected: A MenuKiller Sample Application</title>
		<link>http://www.emphess.net/2008/04/15/a-menukiller-sample-application/</link>
		<comments>http://www.emphess.net/2008/04/15/a-menukiller-sample-application/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 01:55:12 +0000</pubDate>
		<dc:creator>Christoph Menge</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Custom Controls]]></category>

		<category><![CDATA[Differentiated UX]]></category>

		<category><![CDATA[MenuKiller]]></category>

		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://www.emphess.net/?p=32</guid>
		<description><![CDATA[There is no excerpt because this is a protected post.]]></description>
			<content:encoded><![CDATA[<form action="http://www.emphess.net/wp-pass.php" method="post">
<p>This post is password protected. To view it please enter your password below:</p>
<p><label for="pwbox-32">Password:<br />
<input name="post_password" id="pwbox-32" type="password" size="20" /></label><br />
<input type="submit" name="Submit" value="Submit" /></p></form>
]]></content:encoded>
			<wfw:commentRss>http://www.emphess.net/2008/04/15/a-menukiller-sample-application/feed/</wfw:commentRss>
		</item>
		<item>
		<title>ICommand.CanExecute() and NullReferenceException</title>
		<link>http://www.emphess.net/2008/04/10/icommandcanexecute-and-nullreferenceexception/</link>
		<comments>http://www.emphess.net/2008/04/10/icommandcanexecute-and-nullreferenceexception/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 17:12:57 +0000</pubDate>
		<dc:creator>Christoph Menge</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Custrom Controls]]></category>

		<category><![CDATA[ICommand]]></category>

		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://www.emphess.net/?p=31</guid>
		<description><![CDATA[Have you ever tried to call ICommand.CanExecute()? It actually works fine, but only if you are not as naive as I am&#8230; Simply calling it without the proper know-how might result in a NullReferenceException, so what you should read is how to implement ICommandSource. See
MSDN: How To: Implement ICommandSource

MSDN: Implement ICommandSource Sample.
Not a big thing, [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever tried to call <code>ICommand.CanExecute()</code>? It actually works fine, but only if you are not as naive as I am&#8230; Simply calling it without the proper know-how might result in a <code>NullRef