tags:

views:

252

answers:

1

Is it possible and a good idea to have user control (public MyControl: UserControl) which supports both ControlTemplates and existing content? I have understood that ControlTemplates should only be used when you inherit from Control (public MyControl: Control), but I found out that you can use them with UserControl too if your UserControl.xaml is empty.

Imagine I have control which has two rectangles side by side like the following.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt; 
    <Grid ShowGridLines="true" Height="100" Width="100"> 
        <Grid.ColumnDefinitions> 
            <ColumnDefinition/> 
            <ColumnDefinition/> 
        </Grid.ColumnDefinitions> 
        <Rectangle Name="left" Grid.Column="0" Height="90" Fill="LightBlue"/> 
        <Rectangle Name="right" Grid.Column="1" Height="100" Fill="LightGreen"/> 
    </Grid> 
</Page>

I would like the user of the control be able to replace those rectangles with whatever FrameworkElements he wants to use. So I need a ControlTemplate.

But in 99% of the cases user of the control is happy with the existing functionality so I would like him to be able to say:

Code behind:

mycontrol.Left.Fill = ....

XAML:

<mycontrol>
<mycontrol.Left.Fill = "Red"/>
</mycontrol>

That doesn't seem to be possible since if I support control templates I really don't have any UI elements or xaml. I only have the code behind file. I guess I could have a DependencyProperty "Left" but as long as I don't have some kind of container which would hold the content that would't do much good. I would have to create the grid in code behind file. Doesn't seem like a good idea.

And finally I would like to be able to use generics so the user can specify the type of the parts:

MyControl mycontrol = new MyControl();

This would help in code behind because of the type safety (no need to cast FrameworkElement into correct type). Unfortunately I don't think generics are really supported on the XAML side.

Is there any solution to this problem or is it really "Inherit from Control in order to support ControlTemplates but loose the easy usability of the control. Inherit from UserControl in order to support easy usability but loose the ControlTemplate support"?

+1  A: 

Add a dependency property to the control:

public static DependencyProperty LeftFillProperty = DependencyProperty.
   Register("LeftFill", typeof(Brush), typeof(MyControl));

public Brush LeftFill
{
   get { return (Brush)GetValue(LeftFillProperty); }
   set { SetValue(LeftFillProperty,value); }
}

Then in the default control template use:

<Rectangle Name="left" Grid.Column="0" Height="90" Fill="{TemplateBinding LeftFill}"/>

This will left you use (C#)

ctrl.LeftFill = Brushes.Red;

or (XAML)

<c:MyControl LeftFill="Red"/>

when you use the default template and when someone writes a new control template it's their responsibility to decide what to do with the LeftFill property (or to ignore it completely).

BTW, you should consider changing the names from "left" and "right" to something else ("MasterPanel" and "DetailPanel", "FoldersArea" and "FilesArea", whatever the logical usage in your control is), this will solve the issue of someone replacing the default template with a template that displays the same data in a different layout (top and bottom instead of left and right for example).

Nir