views:

203

answers:

1

The following xaml code works:

<Window x:Class="DerivedTemplateBug.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:local="clr-namespace:DerivedTemplateBug"
 Title="Window1" Height="300" Width="300">
 <Button>
  <Button.Template>
   <ControlTemplate>
    <Border BorderBrush="Black" BorderThickness="2">
     <TextBlock>Testing!</TextBlock>
    </Border>
   </ControlTemplate>
  </Button.Template>
 </Button>
</Window>

Now, if you define the following data template:

using System.Windows.Controls;

namespace DerivedTemplateBug
{
 public class DerivedTemplate : ControlTemplate
 {
 }
}

And then swap the ControlTemplate for the derived class:

<Window x:Class="DerivedTemplateBug.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:local="clr-namespace:DerivedTemplateBug"
 Title="Window1" Height="300" Width="300">
 <Button>
  <Button.Template>
   <local:DerivedTemplate>
    <Border BorderBrush="Black" BorderThickness="2">
     <TextBlock>Testing!</TextBlock>
    </Border>
   </local:DerivedTemplate>
  </Button.Template>
 </Button>
</Window>

You get the following error:

Invalid ContentPropertyAttribute on type 'DerivedTemplateBug.DerivedTemplate', property 'Content' not found.

Can anyone tell me why this is the case?

A: 

I get a different error when I try this:

'Border' object cannot be added to 'DerivedTemplate'. 
Object of type 'System.Windows.Controls.Border' cannot be converted 
to type 'System.Windows.FrameworkElementFactory'.

Looking up FrameworkElementFactory, it appears this was an old way of creating templates in code:

This class is a deprecated way to programmatically create templates, which are subclasses of FrameworkTemplate such as ControlTemplate or DataTemplate; not all of the template functionality is available when you create a template using this class.

My question is, why are you inheriting from ControlTemplate? I can't think of a use case for doing this. If you are simply trying to create your own templates in code-behind, MSDN recommends the following approach:

The recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class.

Charlie
Our project is loading xaml files at run time to create dynamic user editable UIs. We need additional data on the template to know what it should be used for, as well as other things.The error you get is actually the error I was trying to debug when I got this error in my test project.I think the error that you got is a bug in the xaml compiler. The 'ContentProperty' of the ControlTemplate is the VisualTree property which is of type FrameworkElementFactory. When you use a DataTemplate or ControlTemplate it automatically converts the xaml to elements, but when you subclass it doesn't.
Farnk
Could you try working around this using composition? In other words, rather than inherit from ControlTemplate, create a separate class that contains a ControlTemplate, as well as all the rest of the data you need. Then pass that class around rather than the ControlTemplate. This solution seems like a better approach, in my opinion.
Charlie
I think composition might be the answer, we're going to try that. Thanks!
Farnk