<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7414806507349335375</id><updated>2011-04-21T19:55:21.152-04:00</updated><category term='WPF'/><title type='text'>A Troll's musings</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://denis-troller.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7414806507349335375/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://denis-troller.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Denis Troller</name><uri>http://www.blogger.com/profile/07741569707639135339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>1</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7414806507349335375.post-6766969871133485730</id><published>2009-03-17T08:17:00.001-04:00</published><updated>2009-03-17T08:21:21.217-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><title type='text'>Reusable Templates with WPF Attached properties</title><content type='html'>&lt;p&gt;WPF &lt;a href="http://msdn.microsoft.com/en-us/library/ms749011.aspx"&gt;attached properties&lt;/a&gt; are probably a very underused feature of WPF for beginners.&lt;/p&gt;  &lt;p&gt;Most people come into contact with them only through Grid.Column or Canvas.X, and see them as related to layout. But there is so much more to them!&lt;/p&gt;  &lt;p&gt;Attached properties become really powerful indeed when mixed with styles and templates or as “declarative behavior anchors”. This post is about the first case.&lt;/p&gt;  &lt;p&gt;Today on &lt;a href="http://stackoverflow.com/questions/643689/attach-icommand-in-wpf-usercontrol/650620#650620"&gt;Stack Overflow&lt;/a&gt;, someone asked how to make his UserControl work. His goal was to make a reusable “image button”, with an Image and a Caption. His problem was to still be able to bind an ICommand.&lt;/p&gt;  &lt;p&gt;This is a very common reaction for anybody who has been brought up in the Windows Forms toolkit. When you want reusable, you create a UserControl. I’d argue that this is probably wrong most of the time in WPF. Second answer is usually “create a class that inherits from Button!”. No need for that.&lt;/p&gt;  &lt;p&gt;The goal was just to change the appearance of a Button, which is a textbook case for styling and templating. But his goal was to make it &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;reusable across the application &lt;/li&gt;    &lt;li&gt;as concise as possible to create a new “ImageButton” in his layout &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Well, this is where Attached Properties, with some support from styles and templates, come into play.  &lt;/p&gt;  &lt;p&gt;The attached properties give you the power of extending the information attached to an element. In our case, we can use them to store Caption as a string and Image as an ImageSource.&lt;/p&gt;  &lt;p&gt;we can then use a style and some templating to use these properties and display what we want. The end result? We still have a button, that works like it should, but with a specific look that is easy to reuse across the board.&lt;/p&gt;  &lt;p&gt;lets look at the properties first:&lt;/p&gt;           &lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;public class ImageButton               &lt;br /&gt;{ &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;          &lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    public static ImageSource GetImage(DependencyObject obj)               &lt;br /&gt;    {                &lt;br /&gt;        return (ImageSource)obj.GetValue(ImageProperty);                &lt;br /&gt;    } &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;          &lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    public static void SetImage(DependencyObject obj, ImageSource value)               &lt;br /&gt;    {                &lt;br /&gt;        obj.SetValue(ImageProperty, value);                &lt;br /&gt;    } &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;          &lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    public static readonly DependencyProperty ImageProperty =               &lt;br /&gt;        DependencyProperty.RegisterAttached("Image", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null)); &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;          &lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    public static String GetCaption(DependencyObject obj)               &lt;br /&gt;    {                &lt;br /&gt;        return (String)obj.GetValue(CaptionProperty);                &lt;br /&gt;    } &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;          &lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    public static void SetCaption(DependencyObject obj, String value)               &lt;br /&gt;    {                &lt;br /&gt;        obj.SetValue(CaptionProperty, value);                &lt;br /&gt;    } &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;          &lt;p&gt;&lt;span&gt;&lt;strong&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    public static readonly DependencyProperty CaptionProperty =               &lt;br /&gt;        DependencyProperty.RegisterAttached("Caption", typeof(String), typeof(ImageButton), new UIPropertyMetadata(null));                &lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;     &lt;br /&gt;&lt;p&gt;That’s all the code you need.&lt;/p&gt;  &lt;p&gt;Now for the templating, trusty old xaml is here:&lt;/p&gt;  &lt;br /&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;lt;Style TargetType="{x:Type Button}"           &lt;br /&gt;   x:Key="ImageButton"&amp;gt;            &lt;br /&gt;    &amp;lt;Setter Property="ContentTemplate"&amp;gt;            &lt;br /&gt;        &amp;lt;Setter.Value&amp;gt;            &lt;br /&gt;            &amp;lt;DataTemplate&amp;gt;            &lt;br /&gt;                &amp;lt;Grid&amp;gt;            &lt;br /&gt;                    &amp;lt;Grid.RowDefinitions&amp;gt;            &lt;br /&gt;                        &amp;lt;RowDefinition Height="*" /&amp;gt;            &lt;br /&gt;                        &amp;lt;RowDefinition Height="Auto" /&amp;gt;            &lt;br /&gt;                    &amp;lt;/Grid.RowDefinitions&amp;gt;            &lt;br /&gt;                    &amp;lt;Image Source="{Binding Path=(local:ImageButton.Image),            &lt;br /&gt;                           RelativeSource={RelativeSource AncestorType={x:Type Button}}}" /&amp;gt;            &lt;br /&gt;                    &amp;lt;TextBlock Text="{Binding Path=(local:ImageButton.Caption),            &lt;br /&gt;                           RelativeSource={RelativeSource AncestorType={x:Type Button}}}"            &lt;br /&gt;                           Margin="2,0,0,0" /&amp;gt;            &lt;br /&gt;                &amp;lt;/Grid&amp;gt;            &lt;br /&gt;            &amp;lt;/DataTemplate&amp;gt;            &lt;br /&gt;        &amp;lt;/Setter.Value&amp;gt;            &lt;br /&gt;    &amp;lt;/Setter&amp;gt;  &lt;br /&gt;&amp;lt;/Style&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt; With this, it becomes fairly easy to reuse your button anywhere you need it:&lt;/p&gt;  &lt;p&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;lt;Button Style="{DynamicResource ImageButton}"   &lt;br /&gt;                    local:ImageButton.Caption="Foo"  local:ImageButton.Image=”{StaticResource FooImage}” /&amp;gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;That’s it. No subclassing, almost no code, and you have a perfectly functioning button that reacts like any other button.&lt;/p&gt;  &lt;p&gt;The Style used here assumes you want to keep the standard chrome (borders, mouseover states etc) of a button. If you want to completely replace the representation of the button, you can work on the Button.Template property instead, and use {TemplateBinding} to get the properties you need.&lt;/p&gt;  &lt;p&gt;This is deceptively simple, but yet impressively powerful. And there is much more to Dependency Properties once you decide to use them to their full extent and encapsulate behavior in a declarative way, but that’s a story for another post.&lt;/p&gt;  &lt;p&gt;As &lt;a href="http://www.dotnetrocks.com/"&gt;Carl Franklin&lt;/a&gt; would say: Attached Properties, Know ‘em, Learn ‘em, Love ‘em!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7414806507349335375-6766969871133485730?l=denis-troller.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denis-troller.blogspot.com/feeds/6766969871133485730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7414806507349335375&amp;postID=6766969871133485730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7414806507349335375/posts/default/6766969871133485730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7414806507349335375/posts/default/6766969871133485730'/><link rel='alternate' type='text/html' href='http://denis-troller.blogspot.com/2009/03/reusable-templates-with-wpf-attached.html' title='Reusable Templates with WPF Attached properties'/><author><name>Denis Troller</name><uri>http://www.blogger.com/profile/07741569707639135339</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
