Question

I'm wanting to create either a custom ContentControl in WPF that can contain one element. This is easy enough, I've done it plenty of times. But here I want the content control to have rulers on the bottom and left edges. I want these controls to be accessible from the code behind. I'm at a loss with how to move forward. I've considered a template but then the ruler controls would not be readily accessible. I also thought about creating a UserControl with a content like dependency property, but then the XAML would not be as simple for the user of this control as just using a content control.

Thanks.

Was it helpful?

Solution

You can use template parts. You can have a look at a complete example on this page :

http://msdn.microsoft.com/en-us/library/ee330302(v=vs.110).aspx

From the example, here is how the CustomControl declares template parts :

[TemplatePart(Name = "UpButtonElement", Type = typeof(RepeatButton))] [...] public class NumericUpDown : Control [...]

And how you can access them :

  public override void OnApplyTemplate()
    {
        UpButtonElement = GetTemplateChild("UpButton") as RepeatButton;
        [...]
    }

OTHER TIPS

What you're asking for is to be able to use content in the two different ways it is commonly used, but at the same time with one control. You can do this, but just need 2 different content properties. You could define your own secondary content property set but it's much easier to just derive from HeaderContentControl, which already does exactly that for you with its Header properties.

To allow users of the control to treat it like a normal ContentControl and just enclose content in the tags you can use the Header content as the part that you define UserControl style and can access from code-behind. Inside that content you can just put a ContentPresenter wherever you want to receive the external Content. You then also need to adjust the ControlTemplate to only show the Header content (Content will be inside the Header part remember).

<HeaderedContentControl x:Class="WpfApp.MyRulerControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp">
    <HeaderedContentControl.Template>
        <ControlTemplate TargetType="{x:Type local:MyRulerControl}">
            <Border Background="{TemplateBinding Background}">
                <ContentPresenter ContentSource="Header"/>
            </Border>
        </ControlTemplate>
    </HeaderedContentControl.Template>

    <HeaderedContentControl.Header>
        <StackPanel>
            <Border x:Name="Ruler1" Height="20"/>

            <ContentPresenter
                Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MyRulerControl}}, Path=Content}"
                ContentTemplate="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MyRulerControl}}, Path=ContentTemplate}"/>

            <Border x:Name="Ruler2" Height="20"/>
        </StackPanel>
    </HeaderedContentControl.Header>
</HeaderedContentControl>

Now you can use the control like normal:

<local:MyRulerControl>
    <TextBlock Text="External content here"/>
</local:MyRulerControl>

You can also get to anything inside that Header section from code-behind:

    public MyRulerControl()
    {
        InitializeComponent();

        Ruler1.Background = Brushes.Red;
        Ruler2.Background = Brushes.Blue;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top