简体   繁体   中英

How to modify ControlTemplate to add items directly to my custom control

I have defined following control template for my custom control.

<ControlTemplate TargetType="{x:Type local:CustomControl}">
    <Grid x:Name="MainGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <local:CustomPanel x:Name="MyCustomPanel" Grid.Column="0" />
        <ScrollBar Grid.Column="1" Width="20" />
    </Grid>
</ControlTemplate>

Here the CustomPanel derives form Panel class. Now I cannot add the items to my CustomControl directly like this

<local:CustomControl x:Name="CControl" Grid.Row="1">
    <Button/>
    <Button/>
    <Button/>
</local:CustomControl>

What can I do for adding the items to my custom control directly from XAML?

Use [ContentProperty( PropertyName )] on your CustomControl.

And: make sure that the content property initialized to an empty list (must not be null ).

Eg:

[ContentProperty("Items")]
public class CustomControl : UserControl
{

    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register("Items", typeof(UIElementCollection), typeof(CustomControl), new UIPropertyMetadata(null)));

    public UIElementCollection Items     
    {     
        get { return (UIElementCollection) GetValue(ItemsProperty); }     
        set { SetValue(ItemsProperty, value); }     
    }   

    public CustomControl()
    {
        Items = new UIElementCollection();
    }

}

IMPORTANT: Do not create the empty collection inside the dependency property registration, ie do not use this:

... new UIPropertyMetadata(new UIElementCollection())

This is considered bad practice, because you then would unintentionally create a singleton collection. Please see Collection-Type Dependency Properties for more details.

Here is a sample control that allows you to directly add content in the way that you're after.

The lines of interest here are the attribute on top of the MyCustomControl class, this tells the XAML editor which property any directly added content should be placed in.

In the XAML code the important line is the ItemsControl that's bound to the Items property, this actually displays each item.

C#

[ContentProperty("Items")]
public class MyCustomControl : Control
{
    public ObservableCollection<Object> Items
    {
        get { return (ObservableCollection<Object>)GetValue(ItemsProperty); }
        set { SetValue(ItemsProperty, value); }
    }

    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register("Items", typeof(ObservableCollection<Object>), typeof(MyCustomControl), new UIPropertyMetadata(new ObservableCollection<object>()));        
}

XAML

<Style TargetType="{x:Type local:MyCustomControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyCustomControl}">
                <ItemsControl ItemsSource="{TemplateBinding Items}"  />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<local:MyCustomControl>
    <Button />
    <Button />
</local:MyCustomControl>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM