1
votes

I'm trying to create a Xamarin Forms user control containing a label and a placeholder where I can "nest" a child control.

I want the label on the left and the nested control on the right. They need to take a percentage of the available space i.e. the label should take one third and the nested control 2 thirds.

I'm trying to use a content presenter as a placeholder so I can use the user control like this

<userControls:PanelControl HeadingText="FIRST HEADING">
    <DatePicker />
</userControls:PanelControl>

If I base the user control on a Stack Layout, the two controls appear in the correct position. The issue with using a Stack Layout is I can't implement percentage widths.

If I base the user control on a Grid, the nested control appears in the first column ovewriting the label. It looks like the Content Presenter does not work properly in a Grid.

Here is the Stack Layout based user control

<?xml version="1.0" encoding="UTF-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BasicAppTemplate.UserControls.PanelControl"
             Orientation="Horizontal">

    <Label x:Name="HeadingLabel" VerticalOptions="Center"/>

    <ContentPresenter/>

</StackLayout>

Here is the Grid based user control

<?xml version="1.0" encoding="UTF-8"?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BasicAppTemplate.UserControls.PanelGridControl">

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="2*"/>
    </Grid.ColumnDefinitions>

    <Label x:Name="HeadingLabel" VerticalOptions="Center" Grid.Column="0"/>

    <StackLayout Grid.Column="1">
        <ContentPresenter/>
    </StackLayout>

</Grid>

Here is the page

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:userControls="clr-namespace:BasicAppTemplate.UserControls;assembly=BasicAppTemplate"
             x:Class="BasicAppTemplate.Pages.MainPage">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <userControls:PanelControl HeadingText="FIRST HEADING">
            <DatePicker />
        </userControls:PanelControl>

        <userControls:PanelGridControl HeadingText="SECOND HEADING" Grid.Row="1">
            <DatePicker />
        </userControls:PanelGridControl>
    </Grid>

</ContentPage>

This what they both look like

enter image description here

Any ideas how to implement this? Is there another way I can create my nested user control?

1
Based on this stackoverflow.com/questions/44948004/… it looks like ContentPresenter is meant to be used inside a ControlTemplate.DavidS
Hmmm interesting. Will give that a go thanks.Steve Chadbourne

1 Answers

1
votes

Thanks to the pointer from DavidS the solution is to embed a ControlTemplate within the User Control

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BasicAppTemplate.UserControls.PanelGridControl">

    <ContentView.ControlTemplate>

        <ControlTemplate>

            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="2*" />
                </Grid.ColumnDefinitions>

                <Label VerticalOptions="Center" Grid.Column="0" Text="{TemplateBinding HeadingText}" />

                <ContentPresenter Grid.Column="1" />

            </Grid>

        </ControlTemplate>

    </ContentView.ControlTemplate>

</ContentView>