views:

23

answers:

3

I am aware I can reference styles & templates from a resource dictionary and I make significant use of them. But what about complete controls?

I can declare a fully defined WPF control, like a button, within the app.xaml as a resource. For example, the app.xaml file defining a button would contain this:

<Button x:Key="HelpButton" Content="?" />

But how can reference it within the xaml markup of a user control so that the button is rendered?

EDIT:
In response to the question of "Why would you want to?" I agree that a button isn't an excellent example (it's just an easy one to describe).

What about a polygon (not a control, I know) that you declare in app.xaml and want to use in multiple xaml files?

+1  A: 

You can't, and to be honest, I'm not sure why you'd want to. That button is one button, meaning that it can only be in one place (at one time); given that, it makes sense to define a new button in every place you need it. As you've already discovered, that's what template resources are for.

(When I say that you can't, I mean that it's not supported in plain XAML; it's conceivable you could implement IValueConverter in a class that returns the button, and bind it in XAML to the content of a content control. And of course, you could use code to add and remove the button programatically from different containers as necessary. Neither seems like a great option.)

Ben M
just to clarify - a visual element can only have one parent. A run-time exception is thrown if it was referenced twice (had it been possible).
Goblin
A: 

As a side-note to Ben M.'s answer:

Some visuals can be used in this way - things inheriting from ToolTip for instance - but it works only when used in the ToolTip-property:

<UserControl.Resources>
    <local:MyToolTip x:Key="ToolTip"/>
<UserControl.Resources>
<Button ToolTip="{StaticResource ToolTip}"/>

This sorta works, but you really should use styling to do these kinds of things.

Goblin
A: 

The only possibility that makes sense is incorporating some controls in a DataTemplate and using that. The DataTemplate 'dresses up' any object and can include full controls; it's actually quite common to design user controls and compose them using DataTemplates; for example, you could define a DataTemplate like this:

<DataTemplate TargetType="{x:Type viewmodels:MyViewModel}">
  <Button Command={Binding MyCommand} Content={Binding MyCaption} />
</DataTemplate>

Assuming the MyViewModel option contains a string property called MyCaption and an ICommand property called MyCommand, the DataTemplate will be automatically used, if defined within scope, to display visually an instance of the MyViewModel class if:

  • the instance is set as the Content property of a ContentControl or derived control, or
  • the instance is one of many items in a collection displayed using an ItemsControl.

When I say 'in scope', what I actually mean is the DataTemplate is defined in a ResourceDictionary somewhere in the accessible hierarchy of controls; i.e. Application.Resources, Window.Resources etc., down to the level of Grid.Resources if the target control (ContentControl or ItemsControl) is hosted in it.

Of course, you can also specify the DataTemplate without a TargetType, but with an x:Key instead, and use it by manually referencing that Key; for example myListBox.ItemTemplate={StaticResource myKey}.

Alex Paven