滑块

.NET Multi-platform App UI (.NET MAUI) Slider 是一个水平条,用户可以操作该条从连续范围中选择一个 double 值。

Slider 定义以下属性:

  • Minimum,类型为 double,是范围的最小值,默认值为 0。
  • Maximum,类型为 double,是范围的最大值,默认值为 1。
  • Value,类型为 double,是滑块的值,其范围介于 MinimumMaximum 之间,默认值为 0。
  • MinimumTrackColor,类型为 Color,是拇指左侧的条块颜色。
  • MaximumTrackColor,类型为 Color,是拇指右侧的条块颜色。
  • ThumbColor,类型为 Color,是拇指颜色。
  • ThumbImageSource,类型为 ImageSource,是用于 ImageSource 类型的拇指图像。
  • DragStartedCommand,类型为 ICommand,在拖动操作开始时执行。
  • DragCompletedCommand,类型为 ICommand,在拖动操作结束时执行。

这些属性由 BindableProperty 对象提供支持。 Value 属性具有 BindingMode.TwoWay 的默认绑定模式,这意味着它适合用作使用模型-视图-视图模型 (MVVM) 模式的应用程序中的绑定源。

注意

ThumbColorThumbImageSource 属性相互排斥。 在这两个属性均已设置的情况下,ThumbImageSource 属性优先。

Slider 强制 Value 属性,使其介于 MinimumMaximum 之间(包含端点值)。 如果 Minimum 属性设置为大于 Value 属性的值,Slider 会将 Value 属性将设置为 Minimum。 同样,如果 Maximum 设置为小于 Value 的值,Slider 会将 Value 属性设置为 Maximum。 在内部,Slider 确保 Minimum 小于 Maximum。 如果曾经设置过 MinimumMaximum,则 Minimum 不小于 Maximum,将会引发异常。 有关设置 MinimumMaximum 属性的详细信息,请参阅预防措施

Slider 定义了一个 ValueChanged 事件,当 Value 更改时(通过用户操作 Slider 或当程序直接设置 Value 属性),会引发该事件。 如前文所述,当 Value 属性被强制时,也会引发 ValueChanged 事件。 ValueChanged 事件所随附的 ValueChangedEventArgs 对象具有 OldValueNewValue 属性,类型均为 double。 在引发事件时,NewValue 的值与 Slider 对象的 Value 属性相同。

Slider 还定义 DragStartedDragCompleted 事件,在拖动操作开始和结束时会引发这些事件。 与 ValueChanged 事件不同,DragStartedDragCompleted 事件仅通过用户操作 Slider 引发。 触发 DragStarted 事件时,会执行类型为 ICommandDragStartedCommand。 同样,当触发 DragCompleted 事件时,会执行类型为 ICommandDragCompletedCommand

警告

请勿使用 CenterStart 或具有 SliderEnd 的无约束水平布局选项。 保留 Fill 的默认设置 HorizontalOptions,在 Grid 布局中放置 Slider 时不要使用 Auto 的宽度。

创建滑块

以下示例演示如何创建具有两个 Label 对象的 Slider

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SliderDemos.BasicSliderXamlPage"
             Title="Basic Slider XAML"
             Padding="10, 0">
    <StackLayout>
        <Label x:Name="rotatingLabel"
               Text="ROTATING TEXT"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <Slider Maximum="360"
                ValueChanged="OnSliderValueChanged" />
        <Label x:Name="displayLabel"
               Text="(uninitialized)"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
    </StackLayout>
</ContentPage>

在此示例中,Slider 被初始化,以使 Maximum 属性为 360。 第二个 Label 显示文本“(未初始化)”,直到操作 Slider,这将导致引发第一个 ValueChanged 事件。

代码隐藏文件包含 ValueChanged 事件的处理程序:

public partial class BasicSliderXamlPage : ContentPage
{
    public BasicSliderXamlPage()
    {
        InitializeComponent();
    }

    void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        double value = args.NewValue;
        rotatingLabel.Rotation = value;
        displayLabel.Text = String.Format("The Slider value is {0}", value);
    }
}

SliderValueChanged 处理程序使用 slider 对象的 Value 属性来设置第一个 LabelRotation 属性,并将 String.Format 方法与事件参数的 NewValue 属性一起使用来设置第二个 LabelText 属性:

.NET MAUI Slider screenshot.

事件处理程序还可以通过 sender 参数获取触发事件的 SliderValue 属性包含当前值:

double value = ((Slider)sender).Value;

如果 Slider 对象在 XAML 文件中指定了具有 x:Name 特性的名称(例如“slider”),则事件处理程序可能直接引用该对象:

double value = slider.Value;

用于创建 Slider 的等效 C# 代码为:

Slider slider = new Slider
{
    Maximum = 360
};
slider.ValueChanged += (sender, args) =>
{
    rotationLabel.Rotation = slider.Value;
    displayLabel.Text = String.Format("The Slider value is {0}", args.NewValue);
};

数据绑定滑块

可以通过使用数据绑定来响应 Slider 值更改,来消除 ValueChanged 事件处理程序:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SliderDemos.BasicSliderBindingsPage"
             Title="Basic Slider Bindings"
             Padding="10, 0">
    <StackLayout>
        <Label Text="ROTATING TEXT"
               Rotation="{Binding Source={x:Reference slider},
                                  Path=Value}"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <Slider x:Name="slider"
                Maximum="360" />
        <Label x:Name="displayLabel"
               Text="{Binding Source={x:Reference slider},
                              Path=Value,
                              StringFormat='The Slider value is {0:F0}'}"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
    </StackLayout>
</ContentPage>

在此示例中, 第一个 LabelRotation 属性绑定到 SliderValue 属性,第二个 LabelText 属性会指定 StringFormat。 第一页出现时,第二个 Label 将显示具有该值的文本字符串。 若要显示没有数据绑定的文本,需要通过从类构造函数调用事件处理程序来专门初始化 LabelText 属性或模拟 ValueChanged 事件的触发。

预防措施

Minimum 属性的值必须始终小于 Maximum 属性的值。 以下示例导致 Slider 引发异常:

// Throws an exception!
Slider slider = new Slider
{
    Minimum = 10,
    Maximum = 20
};

C# 编译器生成按顺序设置这两个属性的代码,且将 Minimum 属性设置为 10 时,它大于默认 Maximum 值 1。 可以通过先设置 Maximum 属性来避免此情况下出现的异常:

Slider slider = new Slider
{
    Maximum = 20,
    Minimum = 10
};

在此示例中,可以将 Maximum 设置为 20,因为它大于默认 Minimum 值 0。 设置 Minimum 后,其值小于 Maximum 值 20。

XAML 中存在相同的问题。 必须按顺序设置属性,确保 Maximum 始终大于 Minimum

<Slider Maximum="20"
        Minimum="10" ... />

可以将 MinimumMaximum 值设置为负数,但只能按照 Minimum 始终小于 Maximum 的顺序:

<Slider Minimum="-20"
        Maximum="-10" ... />

Value 属性始终大于或等于 Minimum 值且小于或等于 Maximum。 如果将 Value 设置为该范围之外的值,则会强制使此值位于该范围内,但不会引发异常。 例如,以下示例不会引发异常:

Slider slider = new Slider
{
    Value = 10
};

相反,Value 属性的 Maximum 值将被强制为 1。

前面的示例将 Maximum 设置为 20,将 Minimum 设置为 10:

Slider slider = new Slider
{
    Maximum = 20,
    Minimum = 10
};

如果 Minimum 设置为 10,则 Value 也设置为 10。

如果在将 Value 属性强制转换为其默认值 0 以外的其他值时附加了 ValueChanged 事件处理程序,则会引发 ValueChanged 事件:

<Slider ValueChanged="OnSliderValueChanged"
        Maximum="20"
        Minimum="10" />

如果 Minimum 设置为 10,则 Value 也设置为 10,这会引发 ValueChanged 事件。 在构造页面的其余部分之前,可能会发生这种情况,处理程序可能会尝试引用尚未创建的页面上的其他元素。 你需要向 ValueChanged 处理程序添加一些代码,以检查页面上其他元素的 null 值。 或者,可以在初始化 Slider 值后设置 ValueChanged 事件处理程序。