xamarin.formscontroltemplatecommandbinding

ControlTemlate Command Binding


Microsoft documentation shows how to inherit from a ControlTemplate and use a ContentPresenter.

It shows how to use string properties to populate string bound items in the template. (e.g. HeaderText)

It doesn't show how to do the same with commands. I want to drive the command behavior of a button in the template via the implementing contentpage/viewmodel.

Following the property example, I tried the same with an ICommand but it gets ignored. Meaning, the button isn't executing the provided command. Is commanding not supported?

Example This is in my ControlTemplate, called ApplicationChrome.xaml

                <Label Grid.Row="0"
                   Margin="20,0,0,0"
                   Text="{TemplateBinding HeaderText}"
                   TextColor="White"
                   FontSize="Title"
                   VerticalOptions="Center"/>

                  <Button Grid.Column="0"
                        x:Name="LeftButton"
                        Margin="20,0,0,0"
                        Text="Change Label"
                        TextColor="White"
                        HorizontalOptions="Start"
                        VerticalOptions="Center"
                        Command="{TemplateBinding LeftButtonTemplateCommand}"

The code-behind defines both Bindable Properties

    public static readonly BindableProperty HeaderTextProperty = BindableProperty.Create("HeaderText", typeof(string), typeof(ContentPage), null, BindingMode.TwoWay);
    public string HeaderText
    {
        get => (string)GetValue(HeaderTextProperty);
        set => SetValue(HeaderTextProperty, value);
    }


    public static readonly BindableProperty LeftButtonTemplateCommandProperty = BindableProperty.Create("LeftButtonCommand", typeof(ICommand), typeof(ApplicationChrome), null);

    public ICommand LeftButtonTemplateCommand
    {
        get => (ICommand) GetValue(LeftButtonTemplateCommandProperty);
        set => SetValue(LeftButtonTemplateCommandProperty, value);
    }

My implementing view sets both Bindables

<core:ApplicationChrome xmlns="http://xamarin.com/schemas/2014/forms" 
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:core="clr-namespace:FEOD.Core;assembly=FEOD"
         mc:Ignorable="d"
         HeaderText="FE | Home"
         LeftButtonTemplateCommand="{Binding LeftButtonCommand}"
         x:Class="FEOD.Views.HomeView">

The implementing view's BindingContext is set to it's viewmodel which defines the LeftButtonCommand

    public ICommand LeftButtonCommand { get; private set; }

    private static void OnLeftButtonClicked(object obj)
    {
        var a = 1;
    }

    public HomeViewModel()
    {
        LeftButtonCommand = new Command(OnLeftButtonClicked);
    }

The bound HeaderText displays "FE | Home" just fine. But the bound command never fires OnLeftButtonClicked.


Solution

  • The first parameter of BindableProperty.Create() method has to be "LeftButtonTemplateCommand" not "LeftButtonCommand". The Property name has to exactly match for Binding to work.