Home > Blockchain >  Creating a Custom Slider
Creating a Custom Slider

Time:05-23

I have created a custom slider, but the ValueChanged event is not triggered when changing the value of the slide, anyone can point out the reason why.

using Mobile.Resources;
using System;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Mobile.Controls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class SliderControl : Grid
    {
        #region Bindable Property

        public event EventHandler<TextChangedEventArgs> SliderValueChanged;
        public event EventHandler<ValueChangedEventArgs> ValueChanged;

        public static readonly BindableProperty MinimumValueProperty =
            BindableProperty.Create("MinimumValue", typeof(double), typeof(SliderControl), defaultValue: 0.00);

        public static readonly BindableProperty MiddleValueProperty =
            BindableProperty.Create("MiddleValue", typeof(double), typeof(SliderControl), defaultValue: 50.00);

        public static readonly BindableProperty MaximumValueProperty =
            BindableProperty.Create("MaximumValue", typeof(double), typeof(SliderControl), defaultValue: 100.00);

        public static readonly BindableProperty SliderValueProperty =
            BindableProperty.Create(nameof(SliderValue), typeof(double), typeof(SliderControl), defaultValue: 0.00);

        public static readonly BindableProperty ValidationExceedMessageProperty =
            BindableProperty.Create("ValidationExceedMessage", typeof(string), typeof(SliderControl), defaultValue: "Limits exceeded");

        public static readonly BindableProperty IsValidationExceedProperty =
            BindableProperty.Create("IsValidationExceed", typeof(bool), typeof(SliderControl), defaultValue: false);

        #endregion

        #region Properties

        public double MinimumValue
        {
            get { return (double)GetValue(MinimumValueProperty); }
            set { SetValue(MinimumValueProperty, value); }
        }

        public double MiddleValue
        {
            get { return (double)GetValue(MiddleValueProperty); }
            set { SetValue(MiddleValueProperty, value); }
        }

        public double MaximumValue
        {
            get { return (double)GetValue(MaximumValueProperty); }
            set { SetValue(MaximumValueProperty, value); }
        }

        public double SliderValue
        {
            set => SetValue(SliderValueProperty, value);
            get => (double)GetValue(SliderValueProperty);
        }

        public bool IsValidationExceed
        {
            get { return (bool)GetValue(IsValidationExceedProperty); }
            set { SetValue(IsValidationExceedProperty, value); }
        }

        public string ValidationExceedMessage
        {
            get { return (string)GetValue(ValidationExceedMessageProperty); }
            set { SetValue(ValidationExceedMessageProperty, value); }
        }

        #endregion

        #region Constructor

        public SliderControl()
        {
            InitializeComponent();
        }

        #endregion

        #region Method

    private void Entry_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (!string.IsNullOrEmpty(e.NewTextValue))
        {
            try
            {
                int.Parse(e.NewTextValue);
                this.SliderValue = double.Parse(e.NewTextValue);
            }
            catch (Exception)
            {
                this.SliderValue = 0;
            }
        }
        else
        {
            this.SliderValue = 0;
        }

        ValidateNumericValue();
        SliderValueChanged?.Invoke(sender, e);
    }

    private void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        SliderValue = args.NewValue;

        ValidateNumericValue();
        ValueChanged?.Invoke(sender, args);
    }

This is the XAML.cs of SliderControl.cs, I'm also missing the event where if I change the slider value it should be reflected in the Entry component.

<?xml version="1.0" encoding="UTF-8" ?>
<Grid
    x:Class="Mobile.Controls.SliderControl"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:common="clr-namespace:Mobile.Common"
    xmlns:control="clr-namespace:Mobile.Controls"
    x:Name="component"
    RowDefinitions="Auto,Auto"
    VerticalOptions="Center">

<Grid RowDefinitions="Auto, *">
    <StackLayout Orientation="Horizontal">
        <Slider Maximum="{x:Binding MaximumValue, Source={x:Reference component}}"
                Minimum="0"
                WidthRequest="300"
                VerticalOptions="FillAndExpand"
                Value="{x:Binding SliderValue, Source={x:Reference component}}"
                ValueChanged="OnSliderValueChanged"/>
        <Entry x:Name="SliderText"
               Placeholder="0"
               WidthRequest="50"
               VerticalOptions="CenterAndExpand"
               TextChanged="Entry_TextChanged"/>
    </StackLayout>
    <StackLayout Orientation="Horizontal" Grid.Row="1">
        <Label Text="0"
               HorizontalOptions="Start"
               MinimumWidthRequest="100"/>
        <Label Text="{x:Binding MiddleValue, Source={x:Reference component}}"
               HorizontalOptions="Center"
               Margin="120,0,0,0"
               MinimumWidthRequest="100"/>
        <Label Text="{x:Binding MaximumValue, Source={x:Reference component}}"
               HorizontalOptions="End"
               Margin="120,0,0,0"
               MinimumWidthRequest="100"/>
    </StackLayout>
</Grid>

This is a new instance for creating a dynamic slider control.

private void GenerateSliderContent(SQViewModel question)
{
    if (question.Entity.QuestionAnswer != null)
    {
        var slider = new SliderControl();

        var maxValue = question.Entity.MaxPrice ?? 100;
        var minValue = question.Entity.MinPrice ?? 0;

        slider.MaximumValue = Math.Max(minValue, maxValue);
        slider.MinimumValue = Math.Min(minValue, maxValue);
        slider.MiddleValue = slider.MaximumValue / 2;
        slider.WidthRequest = 100;
        slider.IsEnabled = !this.IsReadOnly;

        slider.SliderValue = question.Answer == null ? 0 : question.Answer.Entity.ValueNumeric.Value;

        slider.ValueChanged  = (sender, e) => Slider_ValueChanged(question, e.NewValue);

        this.Children.Add(slider);
    }
}

private void Slider_ValueChanged(SQViewModel question, double value)
{
    if (question.Answer != null)
    {
        question.Answer.Entity.ValueNumeric = value;
    }
    else
    {
        SAnswer answer = new SAnswer
        {
            SurveyId = Guid.NewGuid(),
            AccountId = AccountId,
            STId = question.Entity.STId,
            STQAnswerId = Guid.NewGuid(),
            STQId = question.Entity.Id,
            ValueNumeric = value,
        };

        question.Answer = new SAnswerViewModel(answer);
    }
}

CodePudding user response:

You can customize color, thumb image, and track color easily. Basic customization can be done in two ways:

  • From the Attributes Inspector
  • Programmatically in the viewDidLoad()

this is link

CodePudding user response:

You could refer to the code below.

  1. Add the ValueChanged in your SliderControl Xaml:

    <Slider Maximum="100"
                 Minimum="0"
                 WidthRequest="300"
                 VerticalOptions="FillAndExpand"                    
                 ValueChanged="Slider_ValueChanged"
                 Value="{x:Binding SliderValue, Source={x:Reference component}}"/>
    
  2. Register the event in SliderControl code behind:

     public event EventHandler<ValueChangedEventArgs> ValueChanged;
     private void Slider_ValueChanged(object sender, ValueChangedEventArgs e)
     {
         ValueChanged?.Invoke(this, e);
     }
    
  3. Usage: I provide a simple code about how to do this in Xaml, you could do this in c# code as well.

    <local:SliderControl ValueChanged="SliderControl_ValueChanged"></local:SliderControl>
    
  • Related