I have a strange problem with bindings on a custom control. I created a custom toolbar:
public partial class TopToolbar { public static readonly BindableProperty BackCommandProperty = BindableProperty.Create(nameof(BackCommand), typeof(ICommand), typeof(TopToolbar), propertyChanged: BackCommandChanged); public ICommand BackCommand { get => (ICommand) GetValue(BackCommandProperty); set => SetValue(BackCommandProperty, value); } public TopToolbar() { InitializeComponent(); } // for debug purposes only protected override void OnBindingContextChanged() { base.OnBindingContextChanged(); Debug.WriteLine(BindingContext); } // for debug purposes only private static void BackCommandChanged(BindableObject bindable, object oldvalue, object newvalue) { Debug.WriteLine($"old: {oldvalue}, new: {newvalue}"); } } <?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="Core.Controls.TopToolbar" x:Name="TopToolbarView" BindingContext="{x:Reference TopToolbarView}" Orientation="Vertical"> <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" <Image Source="{StaticResource Image.Toolbar.LeftArrow}"> <Image.GestureRecognizers> <TapGestureRecognizer Command="{Binding BackCommand}" /> </Image.GestureRecognizers> </Image> </StackLayout> </StackLayout> I use it on a page in this way:
<pages:ContentPage.Content> <StackLayout BackgroundColor="{StaticResource LightGrayColor}" Spacing="0" Padding="0"> <controls:TopToolbar Title="Master Data" BackCommand="{Binding MyBackCommand}" /> BindingContext of the page is a view model:
public class MyCustomersPageModel { public RelayCommand MyBackCommand { get; set; } public MyCustomersPageModel() { MyBackCommand = // command creation; } } From the debugging I know that BindingContext of a control is set (OnBindingContextChanged called) properly to itself (TopToolbar object) twice - first time when there's no child views and second time after they are added. I've checked that BindingContext is correctly propagated in all child controls.
Unfortunately the BackCommand is not bind at all. The setter of the TopToolbar.BackCommand is not called even once.
Interestingly when I replace setting the BindingContext on a control to setting the Souce directly in bindings everything works fine:
<?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="Core.Controls.TopToolbar" x:Name="TopToolbarView" Orientation="Vertical"> <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" <Image Source="{StaticResource Image.Toolbar.LeftArrow}"> <Image.GestureRecognizers> <TapGestureRecognizer Command="{Binding Source={x:Reference TopToolbarView}, Path=BackCommand}" /> </Image.GestureRecognizers> </Image> </StackLayout> </StackLayout> Any clue what I do wrong?