I have a custom control as follows:
public partial class MyControl : ContentView
{
public event EventHandler? MyClicked;
public MyControl()
{
InitializeComponent();
InternalCommand = new Command(
execute: () =>
{
MyClicked?.Invoke(this, EventArgs.Empty);// breakpoint is added here.
},
canExecute: () => true
);
}
public ICommand InternalCommand { get; set; }
}
<ContentView
...
x:Name="This">
<Button
Command="{Binding InternalCommand,Source={Reference This}}"
Text="Click Me" />
</ContentView>
A page subscribe to the control's clicked event as follows:
public partial class MyPage : ContentPage
{
public MyPage()
{
InitializeComponent();
}
private void MyControl_MyClicked(object sender, EventArgs e)
{
DisplayAlert("MyControl_MyClicked", "Clicked", "Ok");
}
}
<ContentPage
...
xmlns:loc="clr-namespace:MyProject"
>
<loc:MyControl
MyClicked="MyControl_MyClicked" />
</ContentPage>
In debug mode the breakpoint never gets reached when I click the button. What is the culprit?
Even though I use BindingContext
as follows, it still does not work.
<ContentView
...
x:Name="This">
<Button
BindingContext="{Reference This}"
Command="{Binding InternalCommand}"
Text="Click Me" />
</ContentView>
However it WORKS if I use ControlTemplate
.
<ContentPage
...
xmlns:loc="clr-namespace:MyProject">
<ContentPage.Resources>
<ControlTemplate
x:Key="MyTemplate">
<Button
Text="Click Me (templated)"
Command="{TemplateBinding InternalCommand, x:DataType='loc:MyControl'}" />
</ControlTemplate>
</ContentPage.Resources>
<loc:MyControl
MyClicked="MyControl_MyClicked" ControlTemplate="{StaticResource MyTemplate}" />
</ContentPage>
Because of the InitializeComponent();
that happens earlier your InternalCommand
will appear uninitialize and even though you updated after, it still will not be seen. To correct this, you need to either:
InitializeComponent();
, -- OR --OnPropertyChanged(nameof(InitialCommand));
at the end