1

If I have an object derived from System.Windows.DispatcherObject but defines a ControlTemplate.

public class A : System.Windows.DependencyObject
{
   public ControlTemplate ControlTemplate {get; set;}
}

which is a member of

public class B 
{
   public A NonUIElement {get; set;}
}

Is it possible to render this object via a Binding such as

<Border Name="Border">
<ContentPresenter Margin="5,0" Content="{Binding NonUIElement }"/>
</Border>

assuming the DataContext of border is set to an instance of B?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Klaus Nji
  • 18,107
  • 29
  • 105
  • 185

2 Answers2

3

The object will render, but not in the way I think you're hoping for. The Content of the ContentPresenter is set to the instance of A. WPF then tries to figure out how to render this instance of A. It first asks, is this object a UIElement? In this case, the answer is no. So it next looks for a DataTemplate for the type. In this case, there's no DataTemplate for the A class. So it falls back on calling ToString(). So your ContentPresenter will display a TextBlock containing the text "YourNamespace.A".

The fact that A happens to have a member of type ControlTemplate does not affect this logic. To WPF, that's just a chunk of data that A happens to be carrying around. WPF only uses ControlTemplate when there is a Control involved and the ControlTemplate is assigned to the Template property.

So you need either to supply a DataTemplate for A (which of course can access the ControlTemplate and use it to render the instance), or create a named DataTemplate and apply that via ContentPresenter.ContentTemplate, or derive from UIElement instead.

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
itowlson
  • 73,686
  • 17
  • 161
  • 157
  • Excellent explanation, thank you. However, when you say I need to supply a DataTemplate for A where do I assign this within my HierarchicalDataTemplate, which is what I am working with? – Klaus Nji Dec 18 '09 at 21:59
  • Probably the easiest way to do this initially is to assign it on the ContentPresenter.ContentTemplate property: ``. – itowlson Dec 18 '09 at 22:36
  • If WPF uses will look for the ControlTemplate for NonUIElement before it tries to render it within the ContentPresenter specified in your suggestion, why do I still have to supply a DataTemplate? Should this not implicitley mean "Use ControlTemplate of NonUIElement to to render content?" – Klaus Nji Dec 19 '09 at 13:20
  • Also, what would the composition of MyNonUIElementTemplate look like? Something like this simply throws a StackOverflow exception. I cannot seem to wrap my head around this. – Klaus Nji Dec 19 '09 at 14:03
  • WPF will *NOT* "look for the ControlTemplate for NonUIElement before it tries to render it." As far as the content model is concerned, NonUIElement is just a chunk of data. It does not know that you want the ControlTemplate property to have significance for rendering. Per my answer, "WPF only uses ControlTemplate when there is a Control involved and the ControlTemplate is assigned to the Template property." That is, the significance of ControlTemplate is implemented by the Control class, not by DependencyObject or the WPF rendering infrastructure. – itowlson Dec 19 '09 at 18:05
  • 1
    I think that throws a StackOverflowException because you're essentially telling it to repeat the same rendering within a Border. So it keeps trying to instantiating the template within the template within the template... until the stack overflows. You need to do something like (using whatever control has appropriate behaviour for what you want to render). But looking at your answer, what you want is a DataTemplate, not a ControlTemplate. I'll post a comment to that answer. – itowlson Dec 19 '09 at 18:09
0

I finally got it with this;

<HierarchicalDataTemplate DataType="{x:Type vm:MapLayerModel}" ItemsSource="{Binding Path=Children, Mode=OneTime}">   
**<ContentControl Margin="5" Content="{Binding LayerRepresentation}" Template="{Binding LayerRepresentation.ControlTemplate}" Mode=OneTime/>**
</HierarchicalDataTemplate>

This has been a great personal lesson on WPF templating and its content control model. Thanks again itowlson.

Klaus Nji
  • 18,107
  • 29
  • 105
  • 185