Milèstre BV
May 31, 2019

Xamarin Forms: Custom Setter control


For our Vraag Eva app, we needed a stepper control that has a different design than the normal stepper control of Xamarin.
The normal stepper looks like this:

stepper

but we needed something like this.

custom_stepper

To make this possible a custom stepper is developed. For easiness we used the Telerik button control for showing a background image. But this is also possible we the normal button control of Xamarin

using System;
using Telerik.XamarinForms.Input;
using Xamarin.Forms;
using Xamarin_Support.Behaviors;
using Xamarin_Support.Controls;
 
namespace VraagEva.Controls
{
    public class CustomStepper : StackLayout
    {
        private RadButton PlusBtn;
        private RadButton MinusBtn;
        private CustomEntry Entry;
        private Frame Frame;
 
        public static readonly BindableProperty TextProperty = 
            BindableProperty.Create(propertyName: "Text",returnType: typeof(int),declaringType: typeof(CustomStepper),defaultValue: 1,defaultBindingMode: BindingMode.TwoWay);
 
        public static readonly BindableProperty PlusButtonImageProperty =
            BindableProperty.Create("PlusButtonImage", typeof(ImageSource), typeof(CustomStepper));
 
        public static readonly BindableProperty MinusButtonImageProperty =
            BindableProperty.Create("MinusButtonImage", typeof(ImageSource), typeof(CustomStepper));
 
        public static readonly BindableProperty MinimumValueProperty =
            BindableProperty.Create("MinimumValue", typeof(int), typeof(CustomStepper), defaultValue: 1);
 
        public static readonly BindableProperty MaximumValueProperty =
            BindableProperty.Create("MaximumValue", typeof(int), typeof(CustomStepper), defaultValue: 10);
 
        public int Text
        {
            get { return (int)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
 
        public ImageSource PlusButtonImage
        {
            get { return (ImageSource)GetValue(PlusButtonImageProperty); }
            set { SetValue(PlusButtonImageProperty, value); }
        }
 
        public ImageSource MinusButtonImage
        {
            get { return (ImageSource)GetValue(MinusButtonImageProperty); }
            set { SetValue(MinusButtonImageProperty, value); }
        }
 
        public int MinimumValue
        {
            get { return (int)GetValue(MinimumValueProperty); }
            set { SetValue(MinimumValueProperty, value); }
        }
 
        public int MaximumValue
        {
            get { return (int)GetValue(MaximumValueProperty); }
            set { SetValue(MaximumValueProperty, value); }
        }
 
        public CustomStepper()
        {
            HorizontalOptions = LayoutOptions.Center;
            Orientation = StackOrientation.Horizontal;
            WidthRequest = 170;
            PlusBtn = new RadButton { BackgroundImage = PlusButtonImage, WidthRequest = 45, HeightRequest = 40};
            MinusBtn = new RadButton { BackgroundImage = MinusButtonImage, WidthRequest = 45, HeightRequest = 40 };
            PlusBtn.Clicked += PlusBtn_Clicked;
            MinusBtn.Clicked += MinusBtn_Clicked;
            Frame = new Frame{ CornerRadius = 20, BackgroundColor = (Color)Application.Current.Resources["LightGreyColor"], Margin = 0, Padding = 0};
            Entry = new CustomEntry
            { PlaceholderColor = Color.Gray, Keyboard = Keyboard.Numeric, WidthRequest = 70,
                BackgroundColor = (Color)Application.Current.Resources["LightGreyColor"], HorizontalTextAlignment = TextAlignment.Center};
            Entry.Behaviors.Add(new NumericValidationBehavior());
            Entry.SetBinding(Xamarin.Forms.Entry.TextProperty, new Binding(nameof(Text), BindingMode.TwoWay, source: this));
            Entry.TextChanged += Entry_TextChanged;
            Frame.Content = Entry;
            Children.Add(MinusBtn);
            Children.Add(Frame);
            Children.Add(PlusBtn);
        }
 
        protected override void OnParentSet()
        {
            base.OnParentSet();
            PlusBtn.BackgroundImage = PlusButtonImage;
            MinusBtn.BackgroundImage = MinusButtonImage;
        }
 
 
        private void Entry_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.NewTextValue))
                this.Text = int.Parse(e.NewTextValue);
        }
 
        private void MinusBtn_Clicked(object sender, EventArgs e)
        {
            if (Text > MinimumValue)
                Text--;
        }
 
        private void PlusBtn_Clicked(object sender, EventArgs e)
        {
            if (Text < MaximumValue)
                Text++;
        }
    }
}
 
In the Xaml page, you can use it like this:

<localctrl:CustomStepper PlusButtonImage="plus.png" MinusButtonImage="minus.png" HorizontalOptions="Center" MinimumValue="0" MaximumValue="9" Text="{Binding NumDaysStopWeek}" />
 
About us

Milèstre is a digital development agency based in Maastricht and operating all over the world. Since 2003 we build software solutions together with established companies and great startups. During the years we have developed a process that enables us to transform ideas into meaningful, intelligent and designfull experiences for mobile and web. A process where strategy, design, development and user experience are playing an important rol.

 

Contact us

Milestre BV
Ambyerstraat Zuid 82
6225 AJ Maastricht
Netherlands

Tel: +31(0)43 - 4070780
Email: info@milestre.nl
Recent Posts

© Copyright 2022 - Milestre BV
Top