Xamarin.Forms Stepper
Use un Stepper para seleccionar un valor numérico de un intervalo de valores.
Xamarin.FormsStepper
consta de dos botones etiquetados con signos menos y más. El usuario puede manipular estos botones para seleccionar incrementalmente un valor double
de un rango de valores.
Stepper
define dos propiedades de tipo double
:
Increment
es la cantidad por la que se cambia el valor seleccionado, con un valor predeterminado de 1.Minimum
es el valor mínimo del rango, con un valor predeterminado de 0.Maximum
es el valor máximo del rango, con un valor predeterminado de 100.Value
es el valor del control de incremento, que puede oscilar entreMinimum
yMaximum
, y tiene un valor predeterminado de 0.
Todos estos objetos están respaldados por objetos BindableProperty
. La propiedad Value
tiene un modo de enlace predeterminado de BindingMode.TwoWay
, lo que significa que es adecuado como origen de enlace en una aplicación que usa la arquitectura Model-View-ViewModel (MVVM).
Advertencia
Internamente, Stepper
garantiza que Maximum
sea menor que Minimum
. Si Minimum
o Maximum
se establecen alguna vez para que Maximum
no sea menor que Minimum
, se genera una excepción. Para obtener más información sobre cómo establecer las propiedades Minimum
y Maximum
, consulte la sección Precauciones.
El Stepper
reprime la propiedad Value
para que esté entre Minimum
y Maximum
, ambos inclusive. Si la propiedad Minimum
se establece en un valor mayor que la propiedad Value
, Stepper
establece la propiedad Value
en Minimum
. Del mismo modo, si Maximum
se establece en un valor menor que Value
, Stepper
establece la propiedad Value
en Maximum
.
Stepper
define un evento ValueChanged
que se desencadena cuando cambia Value
, ya sea mediante la manipulación del usuario Stepper
o cuando la aplicación establece la propiedad Value
directamente. También se desencadena un evento ValueChanged
cuando la propiedad Value
se coacciona como se describe en el párrafo anterior.
El objeto ValueChangedEventArgs
que acompaña al evento ValueChanged
tiene dos propiedades, de tipo double
: OldValue
y NewValue
. En el momento en que se desencadena el evento, el valor NewValue
es el mismo que la propiedad Value
del objetoStepper
.
Código y marcado básicos de Stepper
El ejemplo contiene tres páginas que son funcionalmente idénticas, pero se implementan de maneras diferentes. La primera página usa solo código de C#, el segundo usa XAML con un controlador de eventos en el código y, en tercer lugar, puede evitar el controlador de eventos mediante el enlace de datos en el archivo XAML.
Creación de un Stepper en el código
En la página Código de Stepper básico en el ejemplo se muestra cómo crear un objeto Stepper
y dos objetos en el código 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
se inicializa para tener una propiedad Maximum
de 360, y una propiedad Increment
de 30. Si se manipula Stepper
, el valor seleccionado cambia incrementalmente entre Minimum
y Maximum
en función del valor de la propiedad Increment
. El controlador ValueChanged
del Stepper
usa la propiedad Value
del objeto stepper
para establecer la propiedad Rotation
del primero Label
y usa el método string.Format
con la propiedad NewValue
de los argumentos del evento para establecer la propiedad Text
del segundo Label
. Estos dos enfoques para obtener el valor actual de Stepper
son intercambiables.
En las capturas de pantalla siguientes se muestra la página Código de Stepper básico:
El segundo Label
muestra el texto "(sin inicializar)" hasta que Stepper
se manipula, lo que hace que se desencadene el primer evento ValueChanged
.
Creación de un Stepper en XAML
La página Basic Stepper XAML es funcionalmente la misma que Basic Stepper Code pero implementada principalmente en 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>
El archivo de código subyacente contiene el controlador para el evento 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);
}
}
También es posible que el controlador de eventos obtenga el Stepper
que desencadena el evento a través del argumento sender
. La propiedad Value
contiene el valor actual:
double value = ((Stepper)sender).Value;
Si el objeto Stepper
recibiera un nombre en el archivo XAML con un atributo x:Name
(por ejemplo, "stepper"), el controlador de eventos podría hacer referencia directamente a ese objeto:
double value = stepper.Value;
Enlace de datos del Stepper
En la página Enlaces de paso básico se muestra cómo escribir una aplicación casi equivalente que elimina el controlador de eventos Value
mediante el Enlace de datos:
<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>
La propiedad Rotation
del primer Label
está enlazada a la propiedad Value
de Stepper
, tal como es la propiedad Text
del segundo Label
con una especificación StringFormat
. La página Basic Stepper Bindings funciona de manera un poco diferente a las dos páginas anteriores: cuando aparece la página por primera vez, la segunda Label
muestra la cadena de texto con el valor. Esta es una ventaja de usar el enlace de datos. Para mostrar texto sin enlace de datos, tendrías que inicializar específicamente la propiedad Text
de Label
o simular una activación del evento ValueChanged
mediante una llamada al controlador de eventos desde el constructor de clase.
Precauciones
El valor de la propiedad Minimum
debe ser siempre inferior que el valor de la propiedad Maximum
. El siguiente fragmento de código hace que Stepper
genere una excepción:
// Throws an exception!
Stepper stepper = new Stepper
{
Minimum = 180,
Maximum = 360
};
El compilador de C# genera código que establece estas dos propiedades en secuencia y, cuando la propiedad Minimum
se establece en 180, es mayor que el valor Maximum
predeterminado de 100. Puedes evitar la excepción en este caso estableciendo primero la propiedad Maximum
:
Stepper stepper = new Stepper
{
Maximum = 360,
Minimum = 180
};
Establecer Maximum
en 360 no es un problema porque es mayor que el valor predeterminado Minimum
de 0. Cuando Minimum
está establecido, el valor es menor que el valor Maximum
de 360.
El mismo problema existe en XAML. Establece las propiedades en un orden que garantice que Maximum
siempre sea mayor que Minimum
:
<Stepper Maximum="360"
Minimum="180" ... />
Luego, puedes establecer los valores Minimum
y Maximum
en números negativos, pero solo en un orden donde Minimum
siempre sea menor que Maximum
:
<Stepper Minimum="-360"
Maximum="-180" ... />
La propiedad Value
siempre es mayor o igual que el valor Minimum
y menor o igual que Maximum
. Si Value
se establece en un valor fuera de ese intervalo, el valor se reprimirá para que se encuentre dentro del intervalo, pero no se genera ninguna excepción. Por ejemplo, este código no generará una excepción:
Stepper stepper = new Stepper
{
Value = 180
};
En su lugar, la propiedad Value
se convierte al valor Maximum
de 100.
Este es un fragmento de código que se muestra anteriormente:
Stepper stepper = new Stepper
{
Maximum = 360,
Minimum = 180
};
Cuando Minimum
se establece en 180, Value
también se establece en 180.
Si un controlador de eventos ValueChanged
se ha adjuntado en el momento en que la propiedadValue
está coaccionada a algo distinto de su valor predeterminado de 0, se desencadena un evento ValueChanged
. Este es un fragmento de código XAML:
<Stepper ValueChanged="OnStepperValueChanged"
Maximum="360"
Minimum="180" />
Cuando Minimum
se establece en 180, Value
también se establece en 180 y el evento ValueChanged
se desencadena. Esto puede ocurrir antes de que se haya construido el resto de la página y el controlador podría intentar hacer referencia a otros elementos de la página que aún no se han creado. Es posible que desees agregar código al controlador ValueChanged
que comprueba si hay valores null
de otros elementos en la página. O bien, puedes establecer el controlador de eventos ValueChanged
después de inicializar los valores Stepper
.