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

<channel>
	<title>Dr. WPF &#187; Focus</title>
	<atom:link href="http://drwpf.com/blog/category/focus/feed/" rel="self" type="application/rss+xml" />
	<link>http://drwpf.com/blog</link>
	<description>Drinking (and serving) the WPF Kool-Aid since 2002</description>
	<lastBuildDate>Sun, 09 May 2010 06:59:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Render Transforms and Focus Visuals</title>
		<link>http://drwpf.com/blog/2010/01/29/render-transforms-and-focus-visuals/</link>
		<comments>http://drwpf.com/blog/2010/01/29/render-transforms-and-focus-visuals/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 01:22:17 +0000</pubDate>
		<dc:creator>Dr. WPF</dc:creator>
				<category><![CDATA[Focus]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://drwpf.com/blog/?p=75</guid>
		<description><![CDATA[While cleaning out my inbox, I came across a few old emails that I missed during a recent crunchtime. I think one question merits a public (albeit rather late) reply, as I&#8217;ve seen it crop up in other scenarios in the past:

Hi Dr WPF
When an element receives keyboard focus, it seems to get a dashed [...]]]></description>
			<content:encoded><![CDATA[<p>While cleaning out my inbox, I came across a few old emails that I missed during a recent crunchtime. I think one question merits a public (albeit rather late) reply, as I&#8217;ve seen it crop up in other scenarios in the past:</p>
<hr /><em><br />
Hi Dr WPF</em></p>
<p><em>When an element receives keyboard focus, it seems to get a dashed border indicating the focus by default. However, if I subsequently adjust the RenderTransform of the container, this keyboard-focus rectangle doesn’t move accordingly.</em></p>
<p><em>Can you explain what’s happening, and possibly suggest solutions?</em></p>
<p><em>Thanks<br />
David</em></p>
<hr /> <br />
Hi David,</p>
<p>The dotted line that you are seeing is called the &#8220;focus visual&#8221; for the control. If the keyboard is used to focus an element, then its focus visual will be rendered <em>within the nearest parent adorner layer</em>. More on that in a moment.</p>
<p><strong>Focus Visual Styles</strong></p>
<p>Most controls simply use the default focus visual style which you&#8217;ve described in your email. All themes (Aero, Classic, Luna Homestead, Luna Metallic, Luna NormalColor) define the exact same default focus visual style:</p>
<pre><span style="color: #0000ff;"><span style="color: #0000ff;"><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span></span></span><span style="color: #a31515;"><span style="color: #a31515;">Style</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> x</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">:</span></span><span style="color: #ff0000;"><span style="color: #ff0000;">Key</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="{</span></span><span style="color: #a31515;"><span style="color: #a31515;">x</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">:</span></span><span style="color: #a31515;"><span style="color: #a31515;">Static</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> SystemParameters</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">.</span></span><span style="color: #ff0000;"><span style="color: #ff0000;">FocusVisualStyleKey</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">}"&gt;
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Setter</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> Property</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="Control.Template"&gt;
    </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Setter.Value</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
      </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">ControlTemplate</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">        &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Rectangle</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> StrokeThickness</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="1" </span></span><span style="color: #ff0000;"><span style="color: #ff0000;">Stroke</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="Black"
            </span></span><span style="color: #ff0000;"><span style="color: #ff0000;">StrokeDashArray</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="1 2" </span></span><span style="color: #ff0000;"><span style="color: #ff0000;">SnapsToDevicePixels</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="true" /&gt;
      </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">ControlTemplate</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
    </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">Setter.Value</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
  </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">Setter</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span><span style="color: #a31515;"><span style="color: #a31515;"><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span>Style</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span></pre>
<p>This provides a dotted line around the control that has keyboard focus. If you want something more elaborate, you can give an element a custom focus visual by setting its FocusVisualStyle property.</p>
<p><strong>Focus Visuals are Rendered within an Adorner</strong></p>
<p>The important thing to note is that a focus visual is not part of the target control&#8217;s subelement tree. Rather, it is the child of a special adorner (FocusVisualAdorner) that is dynamically created by the keyboard navigation manager. This adorner is added to the adorner layer of the nearest parent AdornerDecorator element. As such, the focus visual is rendered over the top of the target control, but in a separate subtree of a larger visual tree.</p>
<p>Most of the time, the nearest parent AdornerDecorator will be the one declared as part of the parent Window control&#8217;s template. This is nearly at the top of the visual tree. This can lead to the problem you&#8217;ve described. Namely, if the focus visual is rendered and then you subsequently adjust the RenderTransform on the focused control, the focus visual will not automatically be rerendered in the correct location.</p>
<p>Consider the following simple scene:</p>
<pre><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Canvas</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;"> </span></span>
<span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Canvas.RenderTransform</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
   </span></span><span style="color: #a31515;"><span style="color: #a31515;"> </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">TransformGroup</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">      &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">TranslateTransform</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> x</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">:</span></span><span style="color: #ff0000;"><span style="color: #ff0000;">Name</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="translateTransform" /&gt;
      </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">ScaleTransform</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> ScaleX</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="2"</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> ScaleY</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="2" /&gt;
    </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">TransformGroup</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">Canvas.RenderTransform</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Button</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> x</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">:</span></span><span style="color: #ff0000;"><span style="color: #ff0000;">Name</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="button"&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Click Me</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">Button</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">Canvas</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span></pre>
<p>Suppose we focus the button and then subsequently change the translate transform, as follows:</p>
<pre><span>    translateTransform.X += 25;
</span></pre>
<p>This can lead to a broken visual appearance:</p>
<p><img class="alignnone size-full wp-image-83" src="http://drwpf.com/blog/wp-content/uploads/2010/01/ButtonAndOffsetFocusVisual.jpg" alt="" width="154" height="47" /></p>
<p>In this case, we have translated the canvas that contains our button <em>after </em>the focus visual has already been rendered at the button&#8217;s original location.</p>
<p>The following diagram depicts the problem showing the relevant elements of the visual tree:</p>
<p><img class="aligncenter size-full wp-image-86" src="http://drwpf.com/blog/wp-content/uploads/2010/01/RenderTransformOnCanvas.jpg" alt="" width="421" height="403" /></p>
<p><strong>A Simple Workaround</strong></p>
<p>In the above scenario, if we were to cause a layout pass, perhaps by adding a call to button.InvalidateArrange(), the focus visual would suddenly pop into the correct position. This is because the framework uses the layout pass to update adorner positions to match their target elements.</p>
<p>So here is one way to work around the issue:</p>
<pre><span>    translateTransform.X += 25;
    button.InvalidateArrange();
</span></pre>
<p><strong>Shouldn&#8217;t changing the RenderTransform automatically affect focus visuals?</strong></p>
<p>Arguably, it would have been nice of the framework developers to solve this problem for us. But that would have had an associated performance cost.</p>
<p>The great benefit of using a RenderTransform is that it does not incur a layout pass. The element only needs to measure, arrange, and render itself once. At that point, it has handed its render data to the MIL (Media Integration Layer) so that it can be quickly drawn to the screen. Any changes to the render transform from that point forward will cause a very performant redraw of the subtree using the existing render data with the appropriate matrix math applied.</p>
<p>To make things even more complex, the render transform that is affecting the focused element may appear anywhere in the parent tree. The framework could certainly track all this (and maybe it should), but it would add overhead so its easy to see why it does not.</p>
<p><strong>An Alternative Workaround that Doesn&#8217;t Require Code</strong></p>
<p>The real problem in this scenario is that the subtree containing the focused <em>control</em> is being affected by the render transfom while the the adorner layer containing the <em>focus visual</em> is not. As such, another solution is to simply add a closer adorner layer directly within the transformed subtree.</p>
<p>In the previous example, we were applying a render transform to the canvas that contained the button. We can give this canvas its own adorner layer by simply wrapping it with an AdornerDecorator element. Then we can apply our render transform directly to that new AdornerDecorator, as follows:</p>
<pre><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">AdornerDecorator</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;"> </span></span>
<span style="color: #0000ff;"><span style="color: #0000ff;"><span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">AdornerDecorator.RenderTransform</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
   </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">TransformGroup</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">      &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">TranslateTransform</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> x</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">:</span></span><span style="color: #ff0000;"><span style="color: #ff0000;">Name</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="translateTransform" /&gt;
      </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">ScaleTransform</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> ScaleX</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="2"</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> ScaleY</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="2" /&gt;
    </span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">TransformGroup</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">AdornerDecorator.RenderTransform</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span></span></span><span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Canvas</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">    &lt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Button</span></span><span style="color: #ff0000;"><span style="color: #ff0000;"> x</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">:</span></span><span style="color: #ff0000;"><span style="color: #ff0000;">Name</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">="button"&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">Click Me</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">Button</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span><span style="color: #a31515;"><span style="color: #a31515;">
</span></span><span style="color: #0000ff;"><span style="color: #0000ff;"><span style="color: #0000ff;"><span style="color: #0000ff;">  &lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">Canvas</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;
</span></span>&lt;/</span></span><span style="color: #a31515;"><span style="color: #a31515;">AdornerDecorator</span></span><span style="color: #0000ff;"><span style="color: #0000ff;">&gt;</span></span></pre>
<p>The visual tree for this scene now looks like this:</p>
<p><img class="aligncenter size-full wp-image-87" src="http://drwpf.com/blog/wp-content/uploads/2010/01/RenderTransformOnDecorator.jpg" alt="" width="551" height="321" /></p>
<p>Since the render transform is now on the AdornerDecorator, it affects this entire tree (the AdornerDecorator and all of its descendants) so dynamically updating it causes all render data, including the data for the focus visual, to be updated.</p>
<p><em>Tip of the Day:  </em>If you are going to apply a render transform to a tree that contains focusable controls, you might consider wrapping that tree in an AdornerDecorator and applying the render transform to the decorator instead.  Voîla!  Problem solved. <img src='http://drwpf.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Hope this helps!</p>
<p>Cheers,<br />
Dr. WPF</p>
]]></content:encoded>
			<wfw:commentRss>http://drwpf.com/blog/2010/01/29/render-transforms-and-focus-visuals/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

