views:

569

answers:

1

I have a Canvas in a ResourceDictionary xaml file like so:

<Canvas x:Key="Icon">
     <Path ... />
     <Path ... />
</Canvas>

In my code-behind I load this icon using

LayoutGrid.Children.Add(FindResource("Icon") as Canvas);

And this works fine. Now I want to create a button that uses the same icon as a template. So I create a control template:

<ControlTemplate x:Key="IconTemplate">
    ...
</ControlTemplate>

Now here's the problem: How would I put the "Icon" resource canvas into the control template? As far as I know, Canvas does not have a Style or Template property. It has a Children property, but it's not accessible via XAML. How would I go about using my canvas in a template?

+1  A: 

When you create a type such as canvas as a resource, then you are creating ONE instance of the type. This means that you cannot place that resource in more than one location in your application (an element can only be in one place at a time). You should look at using control templates, I think.

You don't need any code behind for this.

Something like this:

<ControlTemplate x:Key="Icon">
  <Canvas>
   <Path ... />
   <Path ... />
  </Canvas>
</ControlTemplate>

Then elsewhere you do something like this:

<Button>
  <Control Template="{StaticResource Icon}" />
</Button>

This constructs a regular looking button with your icon as it's content. The content of that button is your icon.

If, however, you want to completely redefine the template of your button, then you would do so

<ControlTemplate x:Key="Icon" TargetType="Button">
  <Canvas>
   <Path ... />
   <Path ... />
  </Canvas>
</ControlTemplate>

Then elsewhere you do something like this:

<Button Template="{StaticResource Icon}" />

Note that this isn't a great style for a button. Look at this example from Microsoft for an example of a more fully featured button template.

EDIT

Unless you have a ContentPresenter in your ControlTemplate, then there's no need to assign the template to a content control. Note that any class derived from Control can be templated, including Control itself. So in order to place an item into your view, then you can just use:

<Control Template="{StaticResource Icon}" />

This uses the widest applicable type in the hierarchy, which is also the lightest.

Drew Noakes
The problem with this is that I want to be able to use my icon as a canvas elsewhere in my app rather than as a template. I know that the way I defined the canvas in the dictionary only creates one instance, which is why i created a function to clone the canvas so creating multiple instances isn't a problem, it's just using that icon in a button that's giving me troubles.
Willson Haw
Hmm... I'm still not 100% clear on what you're trying to do. If you posted some XAML that reproduces the error you're seeing, it would be helpful.
Drew Noakes
I figured it out. I just went with your suggestion and I turned everything into a Control Template. Then in my Canvases I just added a <ContentControl Template="{StaticResource icon}"/> to show the icon as a canvas, and <Button Template="{StaticResource icon}"/> to show the icon as a button.Thanks for pointing me in the right direction!
Willson Haw