Xamarin.Forms 步进器
使用步进器从一系列值中选择一个数值。
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
事件处理程序。