×

First time here?

You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting!

I was helping a friend today doing some over-the-shoulder code review and suggestions for his Windows app he’s writing for the store.  In doing this I asked a question about how to perform a certain action.  He indicated that he put those functions in the AppBar and was it not obvious I was supposed to use them.  I looked at the AppBar again and found out why I wasn’t drawn to them.  First, the labels he used weren’t descriptive to me and relied too much on me looking at the actual icon.  Second, however, is that when I hovered over them I received no visual feedback I was expecting and immediately thought they were just disabled (the color was slightly gray as well which probably didn’t help this).

I mentioned these to him and noted he should use the AppBarButtonStyle base definition that comes in the Visual Studio templates as a guide and just set the appropriate content.  He proceeded to let me know that he received the vector data from Syncfusion’s Metro Studio product.  We then began to examine the vector data.  Metro Studio is doing probably too much than it needs to for AppBar button definitions.  To be fair, it serves a goal to get Windows UI style icons for the developers in XAML form.  This is great!  However, if my intention is to use them for AppBar buttons, then it is doing too much.  It led me down a path to see how easy it was to use vector data with the default AppBarButtonStyle definition.  Turns out it wasn’t as simple as I thought.  Let me first explain the core issue then walk through a step on how to do this with vector data.

Fill versus Foreground

The main culprit is Fill vs. Foreground.  The default AppBarButtonStyle has the different visual states for setting the correct default/inverted colors for your icon within the ellipse.  These visual states however set these colors based on changing the Foreground property of the ContentPresenter.  When your content is text – as is the case with the default styles that are commented out – this works fine.  However the Path element in XAML understands Fill and Foreground doesn’t really apply.  So while the vector data could be represented in the icon location, it wasn’t working on the different states because the Foreground value changing had no effect!

Let’s see how we can accomplish this…

Step 1: Get your vector data

I mentioned that we discovered this using Syncfusion’s Metro Studio, but this is one way where you can get vector-based artwork for XAML.  Another is http://xamlproject.com which is similar in how it does things.  Both will give you vector data based on a selected icon.

NOTE: The one thing I don’t like about The XAML Project site is the sizer doesn’t tell me what size I’m using.  Metro Studio gave me the option to set a specific size.

When we launch Metro Studio we can search for different items based on keywords.  Since the Segoe UI Symbol font includes a ton of these for us (all of which are represented in a commented-out style definition in StandardStyles.xaml you can just uncomment and use) I will pick an obscure one called “wash” from Metro Studio.  When I select to edit it I’m presented with a default UI to modify the data:

Metro Studio user interface

Now notice how it gives me options for background shapes, etc.?  For an AppBar button you do not these shapes so you can uncheck that option.  Secondarily the ideal size is 20px with no padding.  The colors (background color and icon color) don’t really matter here as we aren’t going to use them to get the default AppBar button style.  My final options look like this:

Metro Studio user interface

Notice I unchecked the Background Shapes option, chose Custom Size and entered 20 with 0 padding.

Now what I do is click the XAML button and am presented with the full definition.  You don’t need it all.  Just copy only the path Data to your clipboard or wherever you can get it later.

Metro Studio path data export

Now that we have our vector data we need to put it in our button.

Step 2: Creating the path button definition

Because of the Fill versus Foreground issue we can’t just simply use the AppBarButtonStyle as the button style and just set our vector data.  We will not receive the correct state visuals when it is used.  So we first need to re-define a base that we can use.  Since I may use other vector data in the future, I’ll encapsulate this in a new base style I’ll call PathBasedAppBarButtonStyle.  This will allow me to remap Foreground to my Fill property to achieve the desired outcome.  The resulting style is this:

   1: <Style x:Key="PathBasedAppBarButtonStyle" BasedOn="{StaticResource AppBarButtonStyle}" TargetType="ButtonBase">
   2:     <Setter Property="ContentTemplate">
   3:         <Setter.Value>
   4:             <DataTemplate>
   5:                 <Path Width="20" Height="20" 
   6:             Stretch="Uniform" 
   7:             Fill="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}" 
   8:             Data="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
   9:             </DataTemplate>
  10:         </Setter.Value>
  11:     </Setter>
  12: </Style>

Notice that for Fill and Data I’m using Binding with the RelativeSource being the TemplatedParent…the actual Button.  This allows me to essentially get at those properties that will be set and put them in my Path element that makes up the container for the vector data.

Step 3: Setting our custom vector data

Using the exported definition from my “wash” icon above, I can now use the style in my AppBar resulting in something like this:

   1: <Page.BottomAppBar>
   2:     <AppBar IsOpen="True">
   3:         <Button Style="{StaticResource PathBasedAppBarButtonStyle}" 
   4:                 AutomationProperties.Name="Wash" AutomationProperties.AutomationId="WashAppBarButton"
   5:                 Content="M9.6803506,4.8474294C10.209365 ... 3.5652149,0z" />
   6:     </AppBar>
   7: </Page.BottomAppBar>

Please note that I trimmed the Path data so as not to take up so much space for your reading.  I set my Button to use the base style, then set my label (via AutomationProperties.Name) and the Content is the exported vector data from the tool.

NOTE: AutomationProperties.Name is used here in the base AppBarButtonStyle to enable us to expose the Content property as the icon and still have a label.  By using this property you also get accessibility for free in using these styles for this particular instance.  Screen readers will read out the name you set when using this.

The resulting visual is correct in the AppBar UI guidelines:

Wash AppBar Icon displayed

Now when my users mouse-hover or press this button the correct visuals and state changes will happen.

Summary

The default AppBarButtonStyle base definition provided from the Visual Studio templates is optimized for the 150+ styles provided in StandardStyles.xaml and font-based vector data.  For most, this is likely more than enough to use the same icons that are used throughout the operating system to give a consistent feel.  If you find one in the 150+ styles provided you should use that.  However if there is something entirely custom or not available in those, you can use your own vector data to provide your AppBar icon.  Using fonts and vectors make it easy to scale up to the different resources without having to provide different images if you used that method.  Defining a new base for vector data isn’t difficult and provides us the flexibility when we need it!

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.


9/3/2012 4:42 PM | # re: Using vector data for AppBar icons in XAML
Syncfusion is wonderful. I've been copying exactly the same data and making great looking icons too.
9/3/2012 5:37 PM | # re: Using vector data for AppBar icons in XAML
I may be wrong here, please correct me. I'm using the same tool, but rather than copying vector data, I'm exporting it as PNG file and using that file as a content for App Bar button. I'm creating my own styles for these buttons inherited/based on AppBarButtonStyle. Is this approach good or bad?
9/3/2012 5:45 PM | # re: Using vector data for AppBar icons in XAML
@Mayur - the PNGs are a decent approach, but vector will make it easier on you. You don't have to supply different images for each of the states as the styles just apply to the Fill. Additionally if you take scale factors into account you'll need 6 images for each icon (normal/pressed and then for each scale)
9/3/2012 11:38 PM | # re: Using vector data for AppBar icons in XAML
brillant for trimming down the size of any silverlight app!
9/4/2012 4:30 AM | # re: Using vector data for AppBar icons in XAML
@timheuer - Why would you need to set a specified size if you're working with XAML vector artwork? Regardless, I hear http://XamlProject.com is building a Windows 8 app :)
9/4/2012 8:16 AM | # re: Using vector data for AppBar icons in XAML
Excellent post. Getting people to stop thinking in terms of static images is difficult. Demonstrating how to use paths and show that paths will stay razor sharp no matter the screen size/resolution is the best way to do this.
9/4/2012 8:25 AM | # re: Using vector data for AppBar icons in XAML
Just on time as I was going to need a new template for my vector-based appbar buttons :)

Can you quickly explain what AutomationProperties are doing?

Thanks,
Laurent
9/4/2012 8:53 AM | # re: Using vector data for AppBar icons in XAML
@Laith - the size you want (20x20) is only to constrain the vector into the space appropriate to match the UI guidelines for an appbar button.

@Laurent - the default template needed two things: one to host the glyph and another for the label. We used Content for one and needed another property for the other without re-creating a new control. By using AutomationProperties.Name we're able to use that property as well as automatically provide accessibility for the button. Setting that value means you are setting the label, but also in the automation engine various accessibility tools will read out that value to the user. This is a two-birds-with-one-stone win/win for using this method.
9/5/2012 4:10 AM | # re: Using vector data for AppBar icons in XAML
Really nice post and great tool but in the style if I set TargetType="ButtonBase" there is an exception occur but if TargetType="Button" it works fine. so what do you think tim ?? Thanks :)
9/5/2012 8:13 AM | # re: Using vector data for AppBar icons in XAML
@Ibraheem - the exception you are seeing is likely because you aren't on RTM using the latest AppBarButtonStyle base style (which is targeting ButtonBase). It is probably just a TargetType mismatch on the base.
9/11/2012 4:38 PM | # re: Using vector data for AppBar icons in XAML
Thanks Tim, and so if users also want to know, the Content can be in the Style too. Then the button can be used in other AppBars:

<Style x:Key="PrintSelectionAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.Name" Value="Print Selection"/>
<Setter Property="Content" Value="M13.338,28.512001L50.661999,28.512001 50.661999,52.741999 13.338,52.741999z M0,6.9750004L9.1771202,6.9750004 9.1771202,13.338428 54.944,13.338428 54.944,6.9750004 64,6.9750004 64,35.609999 54.944,35.609999 54.944,24.107311 9.1771202,24.107311 9.1771202,35.609999 0,35.609999z M13.277,0L50.723,0 50.723,9.4230003 13.277,9.4230003z" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Path Width="20" Height="20" Stretch="Uniform" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}" Data="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
1/8/2013 12:49 PM | # re: Using vector data for AppBar icons in XAML
I think it is worth pointing out here that vector graphics versus exporting a PNG is superior also because disabled buttons are correctly "dimmed". Using an exported PNG will result in a disabled button's icon still showing as bright white. To that end, the developer would need to sub-template the button for to supply the alternating icon path. So, this technique is awesome. And so is "Windows Store Studio" :)

Were I to add anything, it would be Expression Design's ability to trace an image and create the resulting XAML that a developer could use if they don't have the original vector source for their images. Since Design is now a free DL, every developer should have it installed.

// J
1/22/2013 12:45 PM | # re: Using vector data for AppBar icons in XAML
There may be times when you want a round Appbar-style button, but not in the Appbar, instead on a page. If you look to the back-arrow example in the title-bar for guidance, it's both very complicated XAML-wise and (I'm assuming) makes use of multiple special Segoe UI Symbol code points, which makes it untenable for anything other than back- (and evidently forward-) arrow.

Here's a quick & dirty approach. XAML for Win 8 (unlike for other platforms) doesn't support a {RoundButton} attribute. Instead, use a square button. If it's to be small, use an image-design tool to create an image (bitmap, or vector as discussed above) with the inner design and outer circle. If it's to be large, use a Canvas object and overlaying a round image and square button, e.g.:
<Canvas Name="SendControl" Height="100" Width="100" ...>
<Button Canvas.Top="15" Content="&#E122" Click="Send_Click" FontFamily="Segoe UI Symbol" FontSize="45" BorderThickness="0"/>
<Ellipse Stroke="White" StrokeThickness="6" Height="100" Width="100"
</Canvas>

The Canvas element will have additional attributes to position it on the page, e.g., for Grid.Row, HorizontalAlignment, VerticalAlignment, and Margin.

Either method will be "dirty" in that it will flash its square when touched, not a circle. This will be less obvious with the 2nd method, where the square is smaller and mostly inside the circle. You must of course fine-tune the overlap to suit your needs.
4/19/2013 2:09 PM | # re: Using vector data for AppBar icons in XAML
EXACTLY what I was trying to figure out. Works perfect! You saved me a lot of time, thanks!
2/16/2014 11:34 PM | # re: Using vector data for AppBar icons in XAML
It is great idea to use vector data in app bar icons. But my problem is that client provided me a .svg formatted image for using it in app bar icon. And it contains more than one path data. In that case how we can set it ? For one path it is ok because we can directly bind the path Data to your PathBasedAppBarButtonStyle Data property. But how can we use multiple paths? Please provide me any information.
Thanks Tim!
9/3/2014 5:17 AM | # re: Using vector data for AppBar icons in XAML
You can join data from more than one path. It works.

 
Please add 3 and 2 and type the answer here:

DISCLAIMER:

The opinions/content expressed on this blog are provided "ASIS" with no warranties and are my own personal opinions/content (unless otherwise noted) and do not represent my employer's view in any way.