9

I downloaded the Visual Studio Image Library and I see that the included icons are available in vector format in the form of .XAML files. Here is an example:

Add_16x.xaml

<!-- This file was generated by the AiToXaml tool.-->
<!-- Tool Version: 14.0.22307.0 -->
<Viewbox Width="16" Height="16" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Rectangle Width="16" Height="16">
    <Rectangle.Fill>
      <DrawingBrush>
        <DrawingBrush.Drawing>
          <DrawingGroup>
            <DrawingGroup.Children>
              <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
              <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M5.0004,-0.000199999999999534L5.0004,4.9998 0.000399999999999956,4.9998 0.000399999999999956,10.9998 5.0004,10.9998 5.0004,15.9998 10.9994,15.9998 10.9994,10.9998 16.0004,10.9998 16.0004,4.9998 10.9994,4.9998 10.9994,-0.000199999999999534z" />
              <GeometryDrawing Brush="#FF388A34" Geometry="F1M10,6L15,6 15,10 10,10 10,15 6,15 6,10 1,10 1,6 6,6 6,1 10,1z" />
            </DrawingGroup.Children>
          </DrawingGroup>
        </DrawingBrush.Drawing>
      </DrawingBrush>
    </Rectangle.Fill>
  </Rectangle>
</Viewbox>

I want to put all the icon xaml files I want to use in my application source in a folder called "Icons" and then be able to have a file called IconDictionary.xaml somewhere else that defines a ResourceDictionary holding a MergedDictionaries and inside this MergedDictionaries I want to be able to include the icon.xaml files somehow and assign them an x:Key property so I can refer to them throughout my application as static resources.

Is it possible to use this icon.xaml file without modifying the .xaml file itself?

I would like to be able to just leave them as they are but unfortunately it seems like I have no choice but to either copy their contents into my IconDictionary.xaml or edit the individual .xaml files and surround them in a ResourceDictionary with a x:Key that I could add to my MergedDictionaries.


UPDATE

Here is what I would like my IconDictionary.xaml to look like for clarity:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <DataTemplate x:Key="Add_16x">
        <!-- Import Viewbox from Add_16x.xaml here... -->
    </DataTemplate>

</ResourceDictionary>
Kyle V.
  • 4,752
  • 9
  • 47
  • 81

1 Answers1

6

Is it possible to use this icon.xaml file without modifying the .xaml file itself?

I don't believe so. While XAML looks a lot like XML, and follows a lot of XML rules, the XAML compiler doesn't seem to allow the DOCTYPE and ENTITY markup that would normally be used to import XML from one file into another. When used, the first error reported reads "DTD is prohibited in this XML document". Without the ability to provide a DTD, you can't declare entities, and thus won't be able to import the standalone XAML.


If you want to use the generated XAML file directly, you can add the file to your project as a Resource. The resource data can then be loaded using XamlReader.Load() in code-behind, added at the appropriate time where you want it.

For example, assuming you have copied the XAML file to a folder named "Resources" in your project, and set the "Build Action" for the file to "Resource", you can write code like this to retrieve the object:

using (Stream stream = App.GetResourceStream(
    new Uri("pack://application:,,,/Resources/Add_16x.xaml")).Stream)
{
    object o = XamlReader.Load(stream);
}

That will get a Stream object representing the XAML file data that has been embedded in your application and then load the WPF object the XAML represents, using the XamlReader.Load() method.


Personally, when I am using these files, I just copy/paste the DrawingGroup element from the XAML file, into my own resource XAML file. The wrapper (Viewbox, Rectangle, and DrawingBrush) are all redundant anyway. What I really need is the DrawingGroup object.

When I do this, I also remove the explicit <DrawingGroup.Drawing> syntax, and just include the children of the DrawingGroup directly, making the XAML a bit more concise. E.g.:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <DrawingGroup x:Key="Add_16x">
    <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
    <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M5.0004,-0.000199999999999534L5.0004,4.9998 0.000399999999999956,4.9998 0.000399999999999956,10.9998 5.0004,10.9998 5.0004,15.9998 10.9994,15.9998 10.9994,10.9998 16.0004,10.9998 16.0004,4.9998 10.9994,4.9998 10.9994,-0.000199999999999534z" />
    <GeometryDrawing Brush="#FF388A34" Geometry="F1M10,6L15,6 15,10 10,10 10,15 6,15 6,10 1,10 1,6 6,6 6,1 10,1z" />
  </DrawingGroup>
</ResourceDictionary>

You can then use the above resource however you like. For example, an idiomatic approach in WPF would be to declare a DataTemplate configured to display a Drawing the way you want, and then bind a given Drawing resource as the content for a content control. E.g.:

<DataTemplate DataType="{x:Type Drawing}">
  <Rectangle>
    <Rectangle.Fill>
      <DrawingBrush Drawing="{Binding}" Stretch="Uniform"/>
    </Rectangle.Fill>
  </Rectangle>
</DataTemplate>

Then elsewhere:

<Button Content="{StaticResource Add_16x}"/>

(Making sure the style for the content control, e.g. your Button, is otherwise compatible with your Drawing resource, i.e. correct size, etc.)

Community
  • 1
  • 1
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • I like this solution the most after seeing the alternatives aren't that friendly. Can I add an `x:Key` to the `DrawingGroup` directly or do I need to wrap it in something if I want to put it in my `ResourceDictionary`? – Kyle V. Mar 18 '16 at 20:24
  • Not only can you add the `x:Key` attribute to the `DrawingGroup`, you'll be required to if you want the `DrawingGroup` object to be directly contained by the dictionary. More generally: you can declare an object of _any_ type in a `ResourceDictionary` collection, provided that object has a parameterless constructor, and every element of a `ResourceDictionary` will be required to have an `x:Key` attribute. – Peter Duniho Mar 18 '16 at 20:51
  • Will this also work for XAML icons that consist only of a `Path` object? – Kyle V. Mar 18 '16 at 20:52
  • Like I said in my previous comment: _"you can declare an object of any type"_. Copying and pasting XAML from one file to another will always work, as long as all of the relevant XAML is copied (you might e.g. run into XAML that references other declared resources, in which case those resources need to be converted as well). If you have a `Path` object, you can copy the `Path` object and use it as a resource element, just like the `DrawingGroup` example above. – Peter Duniho Mar 18 '16 at 20:57
  • Sorry, last question: If I declared a `DrawingGroup` like in your example above, how do I then display it somewhere in my view? – Kyle V. Mar 18 '16 at 21:20