10

I created some assets in inkscape and would like to use them as icons in a windows 8 application. I have done some reading and it seams that while .Net 4.5 supports SVG, the modern ui profile does not. I converted the svg to xaml using this tool.

I get the following xaml.

<Canvas xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="svg2997" Width="744.09448" Height="1052.3622" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Canvas x:Name="layer1">
    <Path Fill="#FFCCCCCC" Stroke="#FF000000" StrokeThickness="1.34377062" StrokeMiterLimit="4" x:Name="path3007" Data="M372.58272,134.72445C167.96301,134.72445 2.06820310000001,300.58818 2.06820310000001,505.20789 2.06820310000001,709.8276 167.96301,875.72241 372.58272,875.72241 577.20243,875.72241 743.06616,709.8276 743.06616,505.20789 743.06616,300.58818 577.20243,134.72445 372.58272,134.72445z M280.73888,251.77484L455.94149,251.77484 455.94149,413.70594 628.16035,413.70594 628.16035,588.97071 455.94149,588.97071 455.94149,773.71514 280.73888,773.71514 280.73888,588.97071 106.22005,588.97071 106.22005,413.70594 280.73888,413.70594 280.73888,251.77484z" />
  </Canvas>
</Canvas>

If I add this directly to my apps xaml it will render however the scale is way off.

I would like to use this as an image source for an image object if possible.

<Image HorizontalAlignment="Left" Height="100" Margin="127,37,0,0" VerticalAlignment="Top" Width="100" Source="Assets/plus_circle.xaml"/>

Can this be done?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Chris Gonzales
  • 1,180
  • 1
  • 13
  • 31
  • What is the xaml element that contains the image element? What happens to aspect ratio if you remove width, height, and / or margin attributes from the image element? – Nathan Feb 10 '13 at 04:16
  • The hierarchy is . Not sure what you mean by 'aspect ratio'? Using the above code I cannot get the image to display at all. – Chris Gonzales Feb 10 '13 at 04:53
  • "If I add this directly to my apps xaml it will render however the scale is way off." - I was keying off of that phrase regarding aspect ratio. It wasn't clear to me when I read your question the first time that you weren't getting it to display at all when using image source - though it is pretty clear in the title... – Nathan Feb 10 '13 at 05:41
  • Did you see http://stackoverflow.com/questions/1107334/using-a-xaml-file-as-a-vector-image-source ? – Nathan Feb 10 '13 at 05:52
  • I saw it but I guess it didn't click. Thanks for the help Nathan. – Chris Gonzales Feb 12 '13 at 00:14

2 Answers2

4

Most AppBar buttons are based on a style included in StandardStyles called AppBarButtonStyle.

To customize the text of the button you set the AutomationProperties.Name attached property, to customize the icon in the button you set the Content property, and it's also a good idea to set the AutomationProperties.AutomationId attached property for accessibility reasons.

Here's an example of a button customized using this approach:

<Style x:Key="FolderButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="FolderAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Folder"/>
    <Setter Property="Content" Value="&#xE188;"/>
</Style>

As mentioned above, to customize the icon you set the Content property. The challenge is how you set the content so it displays your custom vector art.

It turns out you can place any path Xaml, even yours, into a Viewbox to change its scale. That was my first approach, but it doesn't work. In fact, it seems any time you use Xaml expanded notation to set the Content property for a button it doesn't work.

<Style x:Key="SquareButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SquareAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Square"/>
<Setter Property="Content">
    <Setter.Value>
        <!-- This square will never show -->
        <Rectangle Fill="Blue" Width="20" Height="20" />
    </Setter.Value>
</Setter>

I actually think this is a bug, but luckily there is a workaround.

Tim Heuer wrote an excellent article on the simplest way to use a Xaml Path as the artwork for a button. That article is here:

http://timheuer.com/blog/archive/2012/09/03/using-vectors-as-appbar-button-icons.aspx

In short, you need to define a style that sets up all the bindings correctly:

<Style x:Key="PathAppBarButtonStyle" BasedOn="{StaticResource AppBarButtonStyle}" TargetType="ButtonBase">
<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>

Then you create a style that inherits from that style and you paste in your path. Here is the style for your artwork you listed above:

<Style x:Key="CrossButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource PathAppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="CrossAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Cross"/>
    <Setter Property="Content" Value="M372.58272,134.72445C167.96301,134.72445 2.06820310000001,300.58818 2.06820310000001,505.20789 2.06820310000001,709.8276 167.96301,875.72241 372.58272,875.72241 577.20243,875.72241 743.06616,709.8276 743.06616,505.20789 743.06616,300.58818 577.20243,134.72445 372.58272,134.72445z M280.73888,251.77484L455.94149,251.77484 455.94149,413.70594 628.16035,413.70594 628.16035,588.97071 455.94149,588.97071 455.94149,773.71514 280.73888,773.71514 280.73888,588.97071 106.22005,588.97071 106.22005,413.70594 280.73888,413.70594 280.73888,251.77484z"/>
</Style>

And finally, you use it in your AppBar like this:

<Button Style="{StaticResource CrossButtonStyle}" />

Dev support, design support and more awesome goodness on the way: http://bit.ly/winappsupport

Jared Bienz - MSFT
  • 3,550
  • 17
  • 21
  • Thanks once again Jared. You are always there to remind me how awesome XAML can be. Also, how little I understand. I need to spend less time in JVS and more time with XAML. – Chris Gonzales Feb 12 '13 at 00:12
  • Wow, from the OP question I never knew it had anything to do with buttons in the first place haha – Chris W. Feb 12 '13 at 00:25
  • lol, Good point Chris W! I guess I made an assumption because he said "Icons" and icons are usually used in buttons (especially AppBar buttons). But the same DataTemplate trick could be applied anywhere. Usually you see people using a Viewbox to scale paths, but my gut tells me that Viewbox is expensive. The trick Tim Heuer shows looks to be much lighter weight. Thanks for being on SO and helping answer questions Chris W., I appreciate it. And Chris G., definitely apply some of those mad skills you have to Win 8. :) People I know are already making good money! – Jared Bienz - MSFT Feb 12 '13 at 13:26
3

I'm pretty positive you can't just inject Path Data into an Image Source and expect it to magically work unless it's through a Drawing Object as Source. What you can however do is adopt your Path into a ContentControl for re-use in the same way without having to go through the trouble of Drawing objects for every instance.

So instead of;

<Image Source="..."/>

Just do something like this and plop it in your Object.Resources or ResourceDictionary;

 <Style x:Key="YourThingy" TargetType="ContentControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ContentControl">
                   <Path Fill="#FFCCCCCC" Stroke="#FF000000" StrokeThickness="1.34377062" StrokeMiterLimit="4" x:Name="path3007" Data="M372.58272,134.72445C167.96301,134.72445 2.06820310000001,300.58818 2.06820310000001,505.20789 2.06820310000001,709.8276 167.96301,875.72241 372.58272,875.72241 577.20243,875.72241 743.06616,709.8276 743.06616,505.20789 743.06616,300.58818 577.20243,134.72445 372.58272,134.72445z M280.73888,251.77484L455.94149,251.77484 455.94149,413.70594 628.16035,413.70594 628.16035,588.97071 455.94149,588.97071 455.94149,773.71514 280.73888,773.71514 280.73888,588.97071 106.22005,588.97071 106.22005,413.70594 280.73888,413.70594 280.73888,251.77484z" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Then just plop it on your view wherever and as many times as you like;

  <ContentControl Style="{StaticResource YourThingy}"/>

You will however want to play with that Path of yours. It seems set a large size, but hopefully this provides a good alternative for your circumstance. Cheers!

Chris W.
  • 22,835
  • 3
  • 60
  • 94