Having experience developing iOS applications, I know that there is no "check box" per say. When I searched for a Xamarin Forms built in check box and was left with only an native implementation, this would have been acceptable, except that they were causing some significant performance issues/lag when a view containing the controls would be added to the navigation stack.
In my last couple posts, I dove into creating non-native controls in Xamarin Forms. I can build on that knowledge to build a Xamarin Forms checkbox hopefully improve performance. This definitely renders a lot faster.
<localcontrol:CheckBoxView Checked="{Binding SomeBooleanProperty}" DefaultText="Check Box Text" ReadOnly="true" HorizontalOptions="FillAndExpand" TextColor="#000000" FontSize="12" />
The source 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="IntPonApp.Controls.CheckBoxView">
<StackLayout x:Name="CheckBoxStack" Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding CheckCommand}"
CommandParameter="#" />
</StackLayout.GestureRecognizers>
<Image x:Name="boxImage"
Source="{Binding BoxImageSource}" />
<Label x:Name="textLabel"
Text="{Binding Text}"
LineBreakMode="WordWrap"
XAlign="Center"
HorizontalOptions="StartAndExpand"
VerticalOptions="Center"
TextColor="{Binding TextColor}"
Font="{Binding Font}" />
</StackLayout>
</ContentView>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Labs;
using CustomControls;
using System.Diagnostics;
using System.Windows.Input;
namespace Check123Mobile.Controls
{
public partial class CheckBoxView
{
#region Properties
/// <summary>
/// The width request in inches property.
/// </summary>
public static readonly BindableProperty CheckedProperty =
BindableProperty.Create<CheckBoxView, bool>(
p => p.Checked, false
, propertyChanged: new BindableProperty.BindingPropertyChangedDelegate<bool>(
(BindableObject obj, bool oldPlaceHolderValue, bool newPlaceHolderValue) =>
{
var cbv = (CheckBoxView)obj;
cbv.BoxImageSource = cbv.GetCheckBoxImageSource();
})
);
protected static readonly BindableProperty BoxImageSourceProperty =
BindableProperty.Create<CheckBoxView, ImageSource>(
p => p.BoxImageSource, null);
/// <summary>
/// The read only property.
/// </summary>
public static readonly BindableProperty ReadOnlyProperty =
BindableProperty.Create<CheckBoxView, bool>(
p => p.ReadOnly, false);
/// <summary>
/// The checked text property.
/// </summary>
public static readonly BindableProperty CheckedTextProperty =
BindableProperty.Create<CheckBoxView, string>(
p => p.CheckedText, string.Empty);
/// <summary>
/// The unchecked text property.
/// </summary>
public static readonly BindableProperty UncheckedTextProperty =
BindableProperty.Create<CheckBoxView, string>(
p => p.UncheckedText, string.Empty);
/// <summary>
/// The checked image property.
/// </summary>
public static readonly BindableProperty CheckedImageProperty =
BindableProperty.Create<CheckBoxView, string>(
p => p.CheckedImage, string.Empty);
/// <summary>
/// The unchecked image property.
/// </summary>
public static readonly BindableProperty UncheckedImageProperty =
BindableProperty.Create<CheckBoxView, string>(
p => p.UncheckedImage, string.Empty);
/// <summary>
/// The default text property.
/// </summary>
public static readonly BindableProperty DefaultTextProperty =
BindableProperty.Create<CheckBoxView, string>(
p => p.Text, string.Empty);
/// <summary>
/// Identifies the TextColor bindable property.
/// </summary>
///
/// <remarks/>
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create<CheckBoxView, Color>(
p => p.TextColor, Color.Black);
/// <summary>
/// The font size property
/// </summary>
public static readonly BindableProperty FontSizeProperty =
BindableProperty.Create<CheckBoxView, double>(
p => p.FontSize, -1);
/// <summary>
/// The font name property.
/// </summary>
public static readonly BindableProperty FontNameProperty =
BindableProperty.Create<CheckBoxView, string>(
p => p.FontName, string.Empty);
public static ImageSource CheckedImageSource { get; protected set; }
public static ImageSource UncheckedImageSource { get; protected set; }
/// <summary>
/// The checked changed event.
/// </summary>
public EventHandler<EventArgs<bool>> CheckedChanged;
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
public bool Checked
{
get
{
return this.GetValue<bool>(CheckedProperty);
}
set
{
this.SetValue(CheckedProperty, value);
var eventHandler = this.CheckedChanged;
if (eventHandler != null)
{
eventHandler.Invoke(this, value);
}
}
}
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
public bool ReadOnly
{
get
{
return this.GetValue<bool>(ReadOnlyProperty);
}
set
{
this.SetValue(ReadOnlyProperty, value);
}
}
/// <summary>
/// Gets or sets a value indicating the checked text.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string CheckedText
{
get
{
return this.GetValue<string>(CheckedTextProperty);
}
set
{
this.SetValue(CheckedTextProperty, value);
}
}
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string UncheckedText
{
get
{
return this.GetValue<string>(UncheckedTextProperty);
}
set
{
this.SetValue(UncheckedTextProperty, value);
}
}
public ImageSource BoxImageSource
{
get
{
return this.GetValue<ImageSource>(BoxImageSourceProperty) ?? GetCheckBoxImageSource();
}
set
{
this.SetValue(BoxImageSourceProperty, value);
}
}
/// <summary>
/// Gets or sets a value indicating the checked text.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string CheckedImage
{
get
{
return this.GetValue<string>(CheckedImageProperty);
}
set
{
this.SetValue(CheckedImageProperty, value);
}
}
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string UncheckedImage
{
get
{
return this.GetValue<string>(UncheckedImageProperty);
}
set
{
this.SetValue(UncheckedImageProperty, value);
}
}
/// <summary>
/// Gets or sets the text.
/// </summary>
public string DefaultText
{
get
{
return this.GetValue<string>(DefaultTextProperty);
}
set
{
this.SetValue(DefaultTextProperty, value);
}
}
public Color TextColor
{
get
{
return this.GetValue<Color>(TextColorProperty);
}
set
{
this.SetValue(TextColorProperty, value);
}
}
/// <summary>
/// Gets or sets the size of the font.
/// </summary>
/// <value>The size of the font.</value>
public double FontSize
{
get
{
return (double)GetValue(FontSizeProperty);
}
set
{
SetValue(FontSizeProperty, value);
}
}
/// <summary>
/// Gets or sets the name of the font.
/// </summary>
/// <value>The name of the font.</value>
public string FontName
{
get
{
return (string)GetValue(FontNameProperty);
}
set
{
SetValue(FontNameProperty, value);
}
}
public Font Font
{
get
{
return Font.SystemFontOfSize(FontSize);
}
}
public string Text
{
get
{
return this.Checked
? (string.IsNullOrEmpty(this.CheckedText) ? this.DefaultText : this.CheckedText)
: (string.IsNullOrEmpty(this.UncheckedText) ? this.DefaultText : this.UncheckedText);
}
}
public ICommand CheckCommand { get; protected set; }
#endregion Properties
#region Constructor
public CheckBoxView()
{
CheckCommand = new Command((object s) =>
{
if (!ReadOnly)
{
Checked = !Checked;
}
});
InitializeComponent();
LoadImages();
CheckBoxStack.BindingContext = this;
boxImage.BindingContext = this;
textLabel.BindingContext = this;
}
#endregion Constructor
#region Image Functions
protected void LoadImages()
{
if (CheckedImageSource == null)
{
CheckedImageSource = ImageSource.FromResource(GetCheckedImage());
}
if (UncheckedImageSource == null)
{
UncheckedImageSource = ImageSource.FromResource(GetUncheckedImage());
}
}
private ImageSource GetCheckBoxImageSource()
{
return this.Checked ? CheckedImageSource : UncheckedImageSource;
}
private string GetCheckBoxImage()
{
return this.Checked
? GetCheckedImage()
: GetUncheckedImage();
}
private string GetCheckedImage()
{
return (string.IsNullOrEmpty(this.CheckedImage) ?
"Check123Mobile.Resources.checked_checkbox.png" :
this.CheckedImage);
}
private string GetUncheckedImage()
{
return (string.IsNullOrEmpty(this.UncheckedImage) ?
"Check123Mobile.Resources.unchecked_checkbox.png" :
this.UncheckedImage);
}
#endregion Image Functions
}
}