I'm trying to add a custom content to a button in Xamarin Forms.
By default Button is created like this:
<Button d:DataContext="{d:DesignInstance viewModel:AssessmentItemCategory}"
Clicked="Button_OnClicked"
Style="{StaticResource CategoryButtonStyle}"
Text={Binding Text} />
But I would like to create custom content of this button. Normally with WPF I would do it like this:
<Button d:DataContext="{d:DesignInstance viewModel:AssessmentItemCategory}"
Clicked="Button_OnClicked"
Style="{StaticResource CategoryButtonStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Text}" Grid.Column="0" TextColor="Black"/>
<Label Text="-" Grid.Column="1" TextColor="Black"/>
</Grid>
</Button>
But this isn't working.
I was also looking for a DataTemplate property, but haven't found this.
How to do it in Xamarin.Forms?
Thanks Paul,
I have created my own UserControl which handles that
Here it is:
public partial class ContentButton : ContentView
{
public ContentButton()
{
InitializeComponent();
}
public event EventHandler Tapped;
public static readonly BindableProperty CommandProperty = BindableProperty.Create<ContentButton, ICommand>(c => c.Command, null);
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
private void TapGestureRecognizer_OnTapped(object sender, EventArgs e)
{
if(Tapped != null)
Tapped(this,new EventArgs());
}
}
And view code:
<?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="RFA.Wireframes.Controls.ContentButton"
x:Name="ContentButtonView">
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" Command="{Binding Source={x:Reference ContentButtonView}, Path=Command}"></TapGestureRecognizer>
</ContentView.GestureRecognizers>
</ContentView>
Unfortunately, at the moment Xamarin.Forms does not support a Content property for the Button.
You would have to create your own User Control with a combination of other controls to try and recreate a Button control. You could then make part of your User Control a ContentView, create a BindableProperty to bind your Grid to, then use the a BindingPropertyChangedDelegate to assign the Content property of your ContentView.
Thanks Tomasz, good inspiration. However for me, your control didn´t pick up the tap-event on all platforms and used obsolete Xamarin.Forms methods "BindableProperty.Create<" and . So I came up with this one.
Here it is:
public class ContentButton:ContentView
{
private readonly TapGestureRecognizer _tapGestureRecognizer;
public ContentButton()
{
_tapGestureRecognizer = new TapGestureRecognizer();
GestureRecognizers.Add(_tapGestureRecognizer);
}
protected override void OnChildAdded(Element child)
{
base.OnChildAdded(child);
if (child is View childview)
{
childview.GestureRecognizers.Add(_tapGestureRecognizer);
}
}
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand),
typeof(ContentButton), null, BindingMode.Default, null, CommandPropertyChanged);
private static void CommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if (newValue is ICommand command && bindable is ContentButton contentButton)
{
contentButton._tapGestureRecognizer.Command = command;
}
}
public ICommand Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With