David
David

Reputation: 115

Trying to create custom bindable template view in Xamarin.Forms

I'm trying to create a XAML template in Xamarin Forms that I can reference from multiple screens. The template has a header, a summary, and can receive touch input. In the attached wireframe, there would be a model backing the three blocks of data. I've read through the docs at https://developer.xamarin.com/guides/xamarin-forms/templates/control-templates/template-binding/, but at this point I feel like I'm missing an important concept. I thought I would just need to create a ContentView template and somehow make the Labels inside bindable to an object at runtime via .BindingContext. What am I missing?

Content 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"
             x:Class="Namespace.SettingsPage"
             Title ="Settings">
  <ContentPage.Resources>
    <ResourceDictionary>
        <ControlTemplate x:Key="SettingTemplate">
            <StackLayout>
                <Label
                    x:Name="Header"
                    Text="{TemplateBinding Parent.Header}" />
                <Label 
                    x:Name="Summary"
                    Text="{TemplateBinding Parent.Summary}"/>
                </StackLayout>                    
        </ControlTemplate>
    </ResourceDictionary>
  </ContentPage.Resources>
  <ContentPage.Content>      
    <StackLayout>      
        <StackLayout>
            <ContentView x:Name="alerts" ControlTemplate="{StaticResource SettingTemplate}"></ContentView>
            <ContentView x:Name="recipients" ControlTemplate="{StaticResource SettingTemplate}"></ContentView>
            <ContentView x:Name="log" ControlTemplate="{StaticResource SettingTemplate}"></ContentView>
        </StackLayout>
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

Code Behind

using Xamarin.Forms;

namespace Namespace.Settings
{
    public partial class SettingsPage : ContentPage
    {
        protected SettingsViewModel viewModel;

        public SettingsPage(AlertInfo info)
        { 
            InitializeComponent();
            BindingContext = viewModel = new SettingsViewModel(info, this);

            // Bind individual models here. AlertSummary VM has logic to pull out
            // header and summary fiels.
            this.alerts.BindingContext = new AlertSummaryViewModel(info, Summary.ALERTS, this);
            this.recipients.BindingContext = new AlertSummaryViewModel(info, Summary.RECIPIENTS, this);
        }       
    }
}

Wireframe

Upvotes: 0

Views: 2104

Answers (1)

Yuri S
Yuri S

Reputation: 5370

Here is the starting point.

    public partial class ControlTemplateTest : ContentPage
    {
        public static readonly BindableProperty HeaderTextProperty =
            BindableProperty.Create("HeaderText", typeof(string), typeof(ControlTemplateTest), "Alerts");
        public static readonly BindableProperty SummaryTextProperty =
          BindableProperty.Create("SummaryText", typeof(string), typeof(ControlTemplateTest), "Three alerts set");

        public string HeaderText
        {
            get { return (string)GetValue(HeaderTextProperty); }
        }

        public string SummaryText
        {
            get { return (string)GetValue(SummaryTextProperty); }
        }

        public ControlTemplateTest()
        {
            InitializeComponent();
        }
    }
}

Xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonRendererDemo.ControlTemplateTest">
  <ContentPage.Resources>
    <ResourceDictionary>
      <ControlTemplate x:Key="SettingTemplate">
        <StackLayout BackgroundColor="#DCF394" >
          <Label FontSize="48" TextColor="Black" Text="{TemplateBinding Parent.Parent.HeaderText}" />
          <Label Text="{TemplateBinding Parent.Parent.SummaryText}"/>
        </StackLayout>
      </ControlTemplate>
    </ResourceDictionary>
  </ContentPage.Resources>

  <ContentPage.Content>
    <StackLayout BackgroundColor="White" VerticalOptions="FillAndExpand" Spacing="0,40" Padding="0,40">
      <ContentView  x:Name="alerts" VerticalOptions="FillAndExpand" ControlTemplate="{StaticResource SettingTemplate}"></ContentView>
      <ContentView x:Name="recipients" VerticalOptions="FillAndExpand" ControlTemplate="{StaticResource SettingTemplate}"></ContentView>
      <ContentView x:Name="log" VerticalOptions="FillAndExpand" ControlTemplate="{StaticResource SettingTemplate}"></ContentView>
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

enter image description here

Upvotes: 1

Related Questions