UserControl within a ControlTemplate

时光总嘲笑我的痴心妄想 提交于 2020-01-02 06:46:29

问题


I have a ControlTemplate for a Telerik Tile and I am overriding like below:

<ControlTemplate TargetType="{x:Type ctrl:Tile}">
    <Border>  

        <local:UserControl>
            <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
        </local:UserControl>
    </Border>
</ControlTemplate>

My user control looks like:

    <DockPanel>
        <!-- some content -->

        <ContentPresenter/>

    </DockPanel>

The ControlTemplate does not display the content of the UserControl.

If I change my control template to:

<ControlTemplate TargetType="{x:Type ctrl:Tile}">
    <Border>  
        <StackPanel>
            <local:UserControl/>

            <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
       </StackPanel>
    </Border>
</ControlTemplate>

It will find the content and place it appropriately. It seems like the ControlTemplate cannot find the content once it's nested inside my UserControl. Is there anything I could be doing wrong?

Note that these ControlTemplate Items are appearing in an ItemsPresenter.


回答1:


You're treating the UserControl as if it is a basic ContentControl (like a Button) which is a little different than what it actually is. Using Button as an example, when you add a child (i.e. a TextBlock) into a Button element that's actually setting that TextBlock as the Button's Content property. The way it gets rendered is through the Button's ControlTemplate, which includes a ContentPresenter to inject Content into. The Visual Tree ends up like this:

<Button>
  -start Template
  <Border>
    <ContentPresenter>
      -start Content
      <TextBlock>

So far that's basically the model your code is following. The problem is that you're using a (still ContentControl derived) UserControl instead, which rather than using a ControlTemplate is most often defined with a XAML+code-behind model, where the XAML defines the Content of the UserControl. (It is possible to switch these models and template a UserControl or make a Button derived class with XAML+code-behind but not common)

If you want to both define the look of your UserControl in XAML as normal and still be able to inject other content you can add another DependencyProperty that mirrors the setup of the Content property and set your content to that. This approach is used with HeaderedContentControl derivatives (i.e. Expander) which essentially has 2 content properties, Content and Header. Using the new property would look like this:

<Border>  
    <local:UserControl>
      <local:UserControl.OtherContent>
          <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
      </local:UserControl.OtherContent>
    </local:UserControl>
</Border>

And then inside the UserControl's XAML you need to explicitly set up the ContentPresenter Bindings (you only get them for free inside templates of ContentControls):

<DockPanel>
    <!-- some content -->

    <ContentPresenter Content="{Binding Path=OtherContent, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"/>
</DockPanel>

If you want a ContentTemplate, ContentTemplateSelector, or ContentStringFormat you'll also need to add properties and bindings for those.



来源:https://stackoverflow.com/questions/17221763/usercontrol-within-a-controltemplate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!