"値の範囲から数値を選ぶには、ステッパーを使います。"
Xamarin.FormsStepper は、マイナス記号とプラス記号の付いた 2 つのボタンで構成されます。 ユーザーはこれらのボタンを操作して、値の範囲から double 値を段階的に選択できます。
Stepper では、double 型の 4 つのプロパティが定義されています。
Incrementは選択した値を変更する量で、既定値は 1 です。Minimumは範囲の最小値で、既定値は 0 です。Maximumは範囲の最大値で、既定値は 100 です。Valueはステッパーの値です。この値はMinimumからMaximumまでの範囲で指定でき、既定値は 0 です。
これらのプロパティはすべて、BindableProperty オブジェクトによってサポートされます。 Value プロパティの既定のバインド モードは BindingMode.TwoWay で、Model-View-ViewModel (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 は、Stepper がユーザーによって操作されるか、アプリケーションで Value プロパティが直接設定されることで、Value が変化したときに発生する ValueChanged イベントを定義します。 前の段落で説明したように、Value プロパティが強制された場合にも ValueChanged イベントが発生します。
ValueChanged イベントに付随する ValueChangedEventArgs オブジェクトには、double 型の 2 つのプロパティ (OldValue と NewValue) があります。 イベントが発生した時点では、NewValue の値は Stepper オブジェクトの Value プロパティと同じです。
基本的なステッパー コードとマークアップ
サンプルは、機能的には同じですが、異なる方法で実装された 3 つのページが含まれます。 最初のページでは C# コードのみを使い、2 番目のページではコード内のイベント ハンドラーで XAML を使い、3 番目のページでは XAML ファイル内のデータ バインディングを使ってイベント ハンドラーを回避できます。
コードでのステッパーの作成
サンプルの [基本的なステッパー コード] ページには、コード内に Stepper と 2 つの 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 になるように初期化されます。 Stepper を操作すると、Increment プロパティの値に基づいて、選択した値が Minimum から Maximum まで段階的に変更されます。 Stepper の ValueChanged ハンドラーは、stepper オブジェクトの Value プロパティを使って最初の Label の Rotation プロパティを設定し、string.Format メソッドをイベント引数の NewValue プロパティと共に使って 2 番目の Label の Text プロパティを設定します。 Stepper の現在の値を取得するこれらの 2 つの方法は、相互に置き換え可能です。
次のスクリーンショットは、[基本的なステッパー コード] ページを示しています。
2 番目の 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;
XAML ファイル内で Stepper オブジェクトに 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 プロパティにバインドされ、2 番目の Label の Text プロパティは StringFormat の仕様でバインドされています。 [基本的なステッパー バインディング] ページは、前の 2 つのページとは少し異なる形で機能します。ページが最初に表示されると、2 番目の Label に値を含むテキスト文字列が表示されます。 これは、データ バインディングを使う利点です。 データ バインディングなしでテキストを表示するには、Label の Text プロパティを具体的に初期化するか、クラス コンストラクターからイベント ハンドラーを呼び出して ValueChanged イベントの発生をシミュレートする必要があります。
注意事項
Minimum プロパティの値は常に、Maximum プロパティの値より小さくする必要があります。 次のコード スニペットを使うと、Stepper で例外が発生します。
// Throws an exception!
Stepper stepper = new Stepper
{
Minimum = 180,
Maximum = 360
};
C# コンパイラは、これら 2 つのプロパティを順番に設定するコードを生成します。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 プロパティは Maximum の値が 100 に強制的に設定されます。
上記のコード スニペットを次に示します。
Stepper stepper = new Stepper
{
Maximum = 360,
Minimum = 180
};
Minimum を 180 に設定すると、Value も 180 に設定されます。
ValueChanged イベント ハンドラーが、Value プロパティが既定値 0 以外の値に強制された時点ですでにアタッチされていた場合、ValueChanged イベントが発生します。 XAML のスニペットを次に示します。
<Stepper ValueChanged="OnStepperValueChanged"
Maximum="360"
Minimum="180" />
Minimum を 180 に設定すると、Value も 180 に設定され、ValueChanged イベントが発生します。 これは、ページの残りの部分が作成される前に発生する可能性があり、ハンドラーは、まだ作成されていないページ上の他の要素を参照しようとする可能性があります。 ページ上の他の要素の null 値をチェックするコードを、ValueChanged ハンドラーに追加できます。 または、Stepper の値が初期化された後に ValueChanged イベント ハンドラーを設定することもできます。
