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.
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}}"/>
Register the event in SliderControl code behind:
public event EventHandler<ValueChangedEventArgs> ValueChanged; private void Slider_ValueChanged(object sender, ValueChangedEventArgs e) { ValueChanged?.Invoke(this, e); }
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>