创建自定义滑块
Creating a Custom Slider
我创建了一个自定义滑块,但是更改滑块的值时没有触发 ValueChanged 事件,任何人都可以指出原因。
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);
}
这是 SliderControl.cs 的 XAML.cs,我也错过了如果我更改滑块值,它应该反映在 Entry 组件中的事件。
<?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>
这是一个用于创建动态滑块控件的新实例。
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);
}
}
您可以轻松自定义颜色、缩略图和轨道颜色。基本定制可以通过两种方式完成:
- 来自属性检查器
- 在 viewDidLoad() 中以编程方式
这是link
您可以参考下面的代码。
在您的 SliderControl Xaml 中添加 ValueChanged
:
<Slider Maximum="100"
Minimum="0"
WidthRequest="300"
VerticalOptions="FillAndExpand"
ValueChanged="Slider_ValueChanged"
Value="{x:Binding SliderValue, Source={x:Reference component}}"/>
在后面的SliderControl代码中注册事件:
public event EventHandler<ValueChangedEventArgs> ValueChanged;
private void Slider_ValueChanged(object sender, ValueChangedEventArgs e)
{
ValueChanged?.Invoke(this, e);
}
用法:我在 Xaml 中提供了有关如何执行此操作的简单代码,您也可以在 C# 代码中执行此操作。
<local:SliderControl ValueChanged="SliderControl_ValueChanged"></local:SliderControl>
我创建了一个自定义滑块,但是更改滑块的值时没有触发 ValueChanged 事件,任何人都可以指出原因。
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);
}
这是 SliderControl.cs 的 XAML.cs,我也错过了如果我更改滑块值,它应该反映在 Entry 组件中的事件。
<?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>
这是一个用于创建动态滑块控件的新实例。
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);
}
}
您可以轻松自定义颜色、缩略图和轨道颜色。基本定制可以通过两种方式完成:
- 来自属性检查器
- 在 viewDidLoad() 中以编程方式
这是link
您可以参考下面的代码。
在您的 SliderControl Xaml 中添加
ValueChanged
:<Slider Maximum="100" Minimum="0" WidthRequest="300" VerticalOptions="FillAndExpand" ValueChanged="Slider_ValueChanged" Value="{x:Binding SliderValue, Source={x:Reference component}}"/>
在后面的SliderControl代码中注册事件:
public event EventHandler<ValueChangedEventArgs> ValueChanged; private void Slider_ValueChanged(object sender, ValueChangedEventArgs e) { ValueChanged?.Invoke(this, e); }
用法:我在 Xaml 中提供了有关如何执行此操作的简单代码,您也可以在 C# 代码中执行此操作。
<local:SliderControl ValueChanged="SliderControl_ValueChanged"></local:SliderControl>