使用步进器从一系列值中选择一个数值。
Xamarin.FormsStepper 由两个分别标有减号和加号的按钮组成。 用户可以操作这些按钮,以增量方式从一系列值中选择一个 double 值。
Stepper 定义了类型为 double 的四个属性:
Increment是所选值的变化量,默认值为 1。Minimum是最小范围,默认值为 0。Maximum是最大范围,默认值为 100。Value是步进器的值,其范围介于Minimum和Maximum之间,默认值为 0。
所有这些属性都由 BindableProperty 对象提供支持。 Value 属性的默认绑定模式为 BindingMode.TwoWay,这意味着它适合在使用模型-视图-视图模型 (MVVM) 体系结构的应用程序中用作绑定源。
警告
在内部,Stepper 确保 Minimum 小于 Maximum。 如果曾经设置过 Minimum 或 Maximum,使其 Minimum 不小于 Maximum,则会引发异常。 若要详细了解如何设置 Minimum 和 Maximum 属性,请参阅预防措施部分。
Stepper 强制 Value 属性,使其介于 Minimum 和 Maximum(包含端点值)之间。 如果 Minimum 属性设置为大于 Value 属性的值,Stepper 会将 Value 属性设置为 Minimum。 同样,如果 Maximum 设置为小于 Value 的值,Stepper 会将 Value 属性设置为 Maximum。
Stepper 定义一个 ValueChanged 事件;当 Value 因用户操作 Stepper 或应用程序直接设置 Value 属性而发生变化时,会触发此事件。 如前一段所述,当 Value 属性被强制执行时,也会触发 ValueChanged 事件。
ValueChanged 事件随附的 ValueChangedEventArgs 对象有两个类型为 double 的属性:OldValue 和 NewValue。 在事件被触发时,NewValue 的值与 Stepper 对象的 Value 属性相同。
基本步进器代码和标记
该示例包含三个页面,这些页面在功能上相同,但以不同的方式实现。 第一个页面仅使用 C# 代码,第二个页面在代码中将 XAML 和事件处理程序结合使用,第三个页面能够在 XAML 文件中使用数据绑定来避免事件处理程序。
在代码中创建步进器
示例中的“基本步进器代码”页面演示如何在代码中创建 Stepper 和两个 Label 对象:
public class BasicStepperCodePage : ContentPage
{
public BasicStepperCodePage()
{
Label rotationLabel = new Label
{
Text = "ROTATING TEXT",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
Label displayLabel = new Label
{
Text = "(uninitialized)",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
Stepper stepper = new Stepper
{
Maximum = 360,
Increment = 30,
HorizontalOptions = LayoutOptions.Center
};
stepper.ValueChanged += (sender, e) =>
{
rotationLabel.Rotation = stepper.Value;
displayLabel.Text = string.Format("The Stepper value is {0}", e.NewValue);
};
Title = "Basic Stepper Code";
Content = new StackLayout
{
Margin = new Thickness(20),
Children = { rotationLabel, stepper, displayLabel }
};
}
}
会初始化 Stepper,使其 Maximum 属性为 360,Increment 属性为 30。 根据 Increment 属性的值,对 Stepper 进行操作会以增量方式在 Minimum 和 Maximum 之间更改所选值。 Stepper 的 ValueChanged 处理程序使用 stepper 对象的 Value 属性来设置第一个 Label 的 Rotation 属性,将 string.Format 方法与事件参数的 NewValue 属性结合使用来设置第二个 Label 的 Text 属性。 这两种获取 Stepper 的当前值的方法是可互换的。
以下屏幕截图显示了“基本步进器代码”页面:
第二个 Label 显示“(未初始化)”文本,直到 Stepper 被操作,这会导致触发第一个 ValueChanged 事件。
在 XAML 中创建步进器
“基本步进器 XAML”页面在功能上与“基本滑步进器代码”相同,但主要在 XAML 中实现:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StepperDemo.BasicStepperXAMLPage"
Title="Basic Stepper XAML">
<StackLayout Margin="20">
<Label x:Name="_rotatingLabel"
Text="ROTATING TEXT"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Stepper Maximum="360"
Increment="30"
HorizontalOptions="Center"
ValueChanged="OnStepperValueChanged" />
<Label x:Name="_displayLabel"
Text="(uninitialized)"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
代码隐藏文件包含 ValueChanged 事件的处理程序:
public partial class BasicStepperXAMLPage : ContentPage
{
public BasicStepperXAMLPage()
{
InitializeComponent();
}
void OnStepperValueChanged(object sender, ValueChangedEventArgs e)
{
double value = e.NewValue;
_rotatingLabel.Rotation = value;
_displayLabel.Text = string.Format("The Stepper value is {0}", value);
}
}
事件处理程序还可以通过 sender 参数获取触发事件的 Stepper。 Value 属性包含当前值:
double value = ((Stepper)sender).Value;
如果 Stepper 对象在 XAML 文件中指定了具有 x:Name 属性的名称(例如“stepper”),则事件处理程序可能直接引用该对象:
double value = stepper.Value;
数据绑定步进器
“基本步进器绑定”页面演示了如何编写一个几乎等效的应用程序,该程序通过使用数据绑定来消除 Value 事件处理程序:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StepperDemo.BasicStepperBindingsPage"
Title="Basic Stepper Bindings">
<StackLayout Margin="20">
<Label Text="ROTATING TEXT"
Rotation="{Binding Source={x:Reference _stepper}, Path=Value}"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Stepper x:Name="_stepper"
Maximum="360"
Increment="30"
HorizontalOptions="Center" />
<Label Text="{Binding Source={x:Reference _stepper}, Path=Value, StringFormat='The Stepper value is {0:F0}'}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
第一个 Label 的 Rotation 属性绑定到 Stepper 的 Value 属性,第二个 Label 的 Text 属性具有 StringFormat 规范。 “基本步进器绑定”页面在功能上与前面两个页面略有不同:第一个页面出现时,第二个 Label 显示具有值的文本字符串。 这是使用数据绑定的好处。 若要显示没有数据绑定的文本,需要通过从类构造函数调用事件处理程序来专门初始化 Label 的 Text 属性或模拟 ValueChanged 事件的触发。
预防措施
Minimum 属性的值必须始终小于 Maximum 属性的值。 以下代码片段导致 Stepper 引发异常:
// Throws an exception!
Stepper stepper = new Stepper
{
Minimum = 180,
Maximum = 360
};
C# 编译器生成按顺序设置这两个属性的代码,当 Minimum 属性设置为 180 时,它大于默认 Maximum 值 100。 在这种情况下,可以通过先设置 Maximum 属性来避免异常:
Stepper stepper = new Stepper
{
Maximum = 360,
Minimum = 180
};
将 Maximum 设置为 360 没有问题,因为它大于默认的 Minimum 值 0。 设置 Minimum 时,该值小于 Maximum 值 360。
XAML 中存在相同的问题。 设置属性是为了确保 Maximum 始终大于 Minimum:
<Stepper Maximum="360"
Minimum="180" ... />
可以将 Minimum 和 Maximum 值设置为负数,但只能按照 Minimum 始终小于 Maximum 的顺序设置:
<Stepper Minimum="-360"
Maximum="-180" ... />
Value 属性应始终大于或等于 Minimum 值,且小于或等于 Maximum。 如果将 Value 设置为该范围之外的值,则会强制使此值位于该范围内,但不会引发异常。 例如,以下代码不会引发异常:
Stepper stepper = new Stepper
{
Value = 180
};
相反,Value 属性被强制设置为 100 的 Maximum 值。
下面是上述代码片段:
Stepper stepper = new Stepper
{
Maximum = 360,
Minimum = 180
};
当 Minimum 设置为 180 时,Value 也设置为 180。
如果在 Value 属性强制转换为默认值 0 以外的其他值时附加了 ValueChanged 事件处理程序,则会触发 ValueChanged 事件。 下面是 XAML 代码片段:
<Stepper ValueChanged="OnStepperValueChanged"
Maximum="360"
Minimum="180" />
当 Minimum 设置为 180 时,Value 也设置为 180,并会触发 ValueChanged 事件。 在构造页面的其余部分之前,可能会发生这种情况,处理程序可能会尝试引用尚未创建的页面上的其他元素。 你需要向 ValueChanged 处理程序添加一些代码,以检查页面上其他元素的 null 值。 或者,可以在初始化 Stepper 值后设置 ValueChanged 事件处理程序。
