![]() |
VOOZH | about |
dotnet add package Vapolia.WheelPicker --version 5.0.2
NuGet\Install-Package Vapolia.WheelPicker -Version 5.0.2
<PackageReference Include="Vapolia.WheelPicker" Version="5.0.2" />
<PackageVersion Include="Vapolia.WheelPicker" Version="5.0.2" />Directory.Packages.props
<PackageReference Include="Vapolia.WheelPicker" />Project file
paket add Vapolia.WheelPicker --version 5.0.2
#r "nuget: Vapolia.WheelPicker, 5.0.2"
#:package Vapolia.WheelPicker@5.0.2
#addin nuget:?package=Vapolia.WheelPicker&version=5.0.2Install as a Cake Addin
#tool nuget:?package=Vapolia.WheelPicker&version=5.0.2Install as a Cake Tool
| Maui (net8), Xamarin Forms, Native (xamarin & .net8) - iOS + Android |
|---|
| 👁 NuGet 👁 Nuget |
| 👁 Image |
Definition from Apple 🍏 :
A Wheel Picker is a view that uses a spinning-wheel or slot-machine metaphor to display one or more sets of values.
This interactive UI control mimics a slot machine user interface on Android, while on iOS, it makes it easy to use multi-wheel pickers.
Enterprise support available: contact sales
Source code available: contact sales
WheelPicker (hot reload & trimming enabled)vapolia.WheelPicker (can be used in layout .xml files)UIPickerViewModel (can be used in storyboards)dotnet add package Vapolia.WheelPicker
If you are using Maui, you need to add this line to your CreateMauiApp():
...
using Vapolia.WheelPickers;
...
builder
.UseMauiApp<App>()
.UseWheelPicker();
xmlns:wp="clr-namespace:Vapolia.WheelPickers;assembly=Vapolia.WheelPicker" to the root tag<wp:WheelPicker ItemsSourceSimple="{Binding MyListProperty}">
<wp:WheelDefinition Width="Auto" HorizontalOptions="Left" Alignment="Center" />
</wp:WheelPicker>
The WheelPicker is made of 2 parts:
<wp:WheelPicker> ... </wp:WheelPicker> which contains 1 or more wheels and present them like a Horizontal StackLayout does.wp:WheelDefinition, each representing a vertical interactive wheel.wp:WheelDefinition has a customizable template to display each item of the wheel.The WheelPicker is bound to a single data source through ItemsSource="{Binding SomeProperty}".
The type of SomeProperty can be:
For 1 wheel:
IReadOnlyCollection<T>. Ex: List<string>For more than 1 wheel:
IReadOnlyCollection<IReadOnlyCollection<T>>. Ex: List<List<MyItemModel>>wp:WheelDefinition.<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:wp="clr-namespace:Vapolia.WheelPickers;assembly=Vapolia.WheelPicker"
x:Class="WheelPickerDemo.Forms.MainPage">
<VerticalStackLayout>
<wp:WheelPicker HorizontalOptions="Fill" SelectedItemsIndex="0"
ItemsSource="{Binding Days}"
Command="{Binding ItemSelectedCommand}">
<wp:WheelDefinition Width="Auto" HorizontalOptions="Left" Alignment="Center" />
</wp:WheelPicker>
</VerticalStackLayout>
</ContentPage>
In the code behind, set the binding context to your view model containing the items to display.
For the example below ItemsSource is bound to a list of strings.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageModel();
}
}
public class MainPageModel
{
public List<string> Days { get; } = new () { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
public Command ItemSelectedCommand { get; }
public MainPageModel()
{
//Component is the index of the wheel triggering the command.
//Row is the index of the currently displayed item at the center of the wheel for this Component.
//ItemIndexes are the current indexes of all wheels of the WheelPicker control
ItemSelectedCommand = new Command<(int Component, int Row, IList<int> ItemIndexes)>(tuple =>
{
var selectedValue = Days[tuple.Row];
//...
});
}
}
You can customize how each item is rendered by using custom templates.
By default, the control converts all items to strings and renders those strings with the specified style.
You can fully customize the style and content of the items. However, there is a constraint: there is only one template per wheel, which renders all items of that wheel. If you have multiple wheels in the same WheelPicker, you can set one template per wheel.
For example, below is a templated picker with 3 wheels. All properties are bindable and can be dynamically changed.
Note how SelectedItemsIndex is used to initialize the position of the 3 wheels to the specified item indexes.
<wp:WheelPicker x:Name="SlotPicker" ItemsSource="{Binding Slot.ItemsSource}"
SelectedItemsIndex="1 10 7"
Command="{Binding Slot.ItemSelectedCommand}"
ItemTextSelectedColor="Lime"
ItemTextFont="Italic"
HorizontalOptions="Fill"
SelectionLinesColor="Aquamarine">
<wp:WheelDefinition Width="*" HorizontalOptions="Left" Alignment="Center" IsCircular="True">
<DataTemplate>
<Label Text="{Binding .}" TextColor="Black" FontSize="30" />
</DataTemplate>
</wp:WheelDefinition>
<wp:WheelDefinition Width="*" HorizontalOptions="Left" Alignment="Center" IsCircular="True" RowHeight="100">
<DataTemplate>
<Image Source="{Binding .}" HeightRequest="100" Aspect="AspectFit" />
</DataTemplate>
</wp:WheelDefinition>
<wp:WheelDefinition Width="*" HorizontalOptions="Left" Alignment="Center" IsCircular="True" RowHeight="100">
<DataTemplate>
<Image Source="{Binding .}" HeightRequest="100" Aspect="AspectFit" />
</DataTemplate>
</wp:WheelDefinition>
</wp:WheelPicker>
Those examples are extracted from the demo projects in this repository.
A simple picker with one wheel:
<wp:WheelPicker ItemsSource="{Binding DayPicker.ItemsSource}">
<wp:WheelDefinition Width="Auto" HorizontalOptions="Left" Alignment="Center" />
</wp:WheelPicker>
A templated picker with one wheel:
<wp:WheelPicker ItemsSource="{Binding DayPicker.ItemsSource}">
<wp:WheelDefinition Width="*" HorizontalOptions="Left" Alignment="Center" IsCircular="True" RowHeight="48">
<DataTemplate>
<Image Source="{Binding .}" HeightRequest="48" Aspect="AspectFill" />
</DataTemplate>
</wp:WheelDefinition>
</wp:WheelPicker>
A picker with 3 wheels:
The width of the center wheel is computed automatically, and items are aligned differently inside each wheel.
<wp:WheelPicker SelectionLinesColor="Navy"
HorizontalSpaceBetweenWheels="40"
ItemsSource="{Binding DatePicker.ItemsSource}"
SelectedItemsIndex="0,0,0"
Command="{Binding DatePicker.ItemSelectedCommand}"
HorizontalOptions="Fill">
<wp:WheelDefinition Width="*" HorizontalOptions="Right" />
<wp:WheelDefinition Width="Auto" HorizontalOptions="Left" />
<wp:WheelDefinition Width="*" HorizontalOptions="Left" />
</wp:WheelPicker>
A templated picker with 3 wheels:
All properties are bindable and can be dynamically changed.
<wp:WheelPicker x:Name="SlotPicker" ItemsSource="{Binding Slot.ItemsSource}"
SelectedItemsIndex="0 0 0"
Command="{Binding Slot.ItemSelectedCommand}"
ItemTextSelectedColor="Lime"
ItemTextFont="Italic"
HorizontalOptions="Fill"
SelectionLinesColor="Aquamarine">
<wp:WheelDefinition Width="*" HorizontalOptions="Left" Alignment="Center" IsCircular="True" RowHeight="100">
<DataTemplate>
<Image Source="{Binding .}" HeightRequest="100" Aspect="AspectFit" />
</DataTemplate>
</wp:WheelDefinition>
<wp:WheelDefinition Width="*" HorizontalOptions="Left" Alignment="Center" IsCircular="True" RowHeight="100">
<DataTemplate>
<Image Source="{Binding .}" HeightRequest="100" Aspect="AspectFit" />
</DataTemplate>
</wp:WheelDefinition>
<wp:WheelDefinition Width="*" HorizontalOptions="Left" Alignment="Center" IsCircular="True" RowHeight="100">
<DataTemplate>
<Image Source="{Binding .}" HeightRequest="100" Aspect="AspectFit" />
</DataTemplate>
</wp:WheelDefinition>
</wp:WheelPicker>
<details><summary>Click to expand</summary>
WheelPicker
Definition
IList<WheelDefinition> WheelDefinitions Default Contentobject ItemsSource Accepts both IReadOnlyCollection<T> and IReadOnlyCollection<IReadOnlyCollection<T>>Appearance
double HorizontalSpaceBetweenWheelsColor SelectionLinesColorItem appearance (used by the default item template, when no custom item template is specified)
Font ItemTextFontColor ItemTextColorColor ItemTextSelectedColorSelection
IList<int> SelectedItemsIndex One index per wheel.ICommand Command Triggered when any of the wheel's index has changedEventHandler<WheelChangedEventArgs> SelectedItemIndexChanged Triggered when any of the wheel's index has changedvoid Spin(int items, int wheelIndex = 0) items: the number of item to spinSelectedItemsIndex is a list of integers, where each integer represents the selected index within a wheel. In XAML, you can use a space- or comma-separated string of integers.
WheelDefinition
GridLength WidthWheelItemAlign HorizontalOptionsWheelItemAlign Alignmentbool IsCircularDataTemplate ImageItemTemplatedouble RowHeightWhen a wheel's Width is set to Auto, the control computes the max width of all strings in the data source (if object are strings). When set to * (star), the width of the wheel will be proportional to the remaining space. See the Grid control for more information about GridLength.
HorizontalOptions is used to align a wheel inside the available width of the WheelPicker, if it is larger than the width of the wheel.
Alignment is used to align the items within a wheel.
</details>
<details><summary>Click to expand</summary>
Sample usage in axml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<vapolia.WheelPicker
android:id="@+id/wheelView"
app:itemWidths="* Auto *"
app:itemAligns="Right Left Left"
app:itemHeights="15dp 15dp 15dp"
app:selectedItemTextColor="#ff228b22"
app:wp_itemTextColor="#ffffb6c1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF" />
</LinearLayout>
var wheelView = FindViewById<WheelPicker>(Resource.Id.wheelView);
wheelView.SelectedItemIndexChanged += (sender, args) =>
{
var text = $"Wheel {args.WheelIndex} selection changed to item index {args.SelectedItemIndex}";
};
wheelView.ItemsSource = new List<string> { "Monday", "Tuesday", "Wednesday" };
wheelView.SelectedItemsIndex = new [] { 0 };
vapolia.WheelPicker
Definition
WheelPicker Appearance
Appearance of a wheel (a picker can have multiple wheels)
Appearance of items inside a wheel
Selection
Templating
SelectedItemsIndex is a list of integers. Each integer represents the selected index within a wheel.
ItemWidths: see chapter below
Alignments or Gravities is used to align a wheel inside the available WheelPicker's width, if it is larger than the width of the wheel.
ItemAligns is used to align the items within a wheel.
</details>
<details><summary>Click to expand</summary>
On iOS, this library utilizes the native UIPickerView along with a custom UIPickerViewModel to significantly simplify the use of this control.
Sample usage:
var picker = new UIPickerView {ShowSelectionIndicator = true, BackgroundColor = UIColor.White};
var pickerViewModel = new WheelPickerModel(picker);
picker.Model = pickerViewModel;
pickerViewModel.ItemsSource = new [] { "Monday", "Tuesday", "Wednesday" };
pickerViewModel.SelectedItemsIndex = new [] { 0 };
pickerViewModel.ItemAligns = new List<WheelItemAlign> { WheelItemAlign.Left };
Vapolia.WheelPickerIos.WheelPickerModel
Definition
Appearance
Item appearance
Selection
Templating
SelectedItemsIndex is a list of integer. Each integer represents the selected index inside a wheel.
ItemWidths: see chapter below
Alignments is used to align a wheel inside the available WheelPicker's width, if it is larger than the wheel's width.
ItemAligns is used to align the items inside a wheel.
</details>
<details><summary>Click to expand</summary>
ItemWidths is used to choose the width of each wheel. It is a space separated string consisting of a combination of float numbers, stars (optionally prepended with a float number), or the "Auto" string.
The total width of the WheelPicker is distributed between the wheels by respecting either :
Examples of ItemWidths:
"*": one wheel having the full width of WheelPicker"* *": two wheels, each of the same width, exactly half of the width of the Wheel Picker"* * *": three wheels, each of the same width, exactly one third of the width of the Wheel Picker"100 2* *": three wheels, first has a 100 device pixel width, second is twice the size of the third, and 3*-100=width of the WheelPicker, which resolves to *=WheelPickerWidth-100"* Auto *": three wheels, the middle wheel's width is computed from the largest string in its items source (if items source contains strings).</details>
The Wheel Picker provides an event and a Command when the selection changes, making it easy to use with or without mvvm frameworks.
It also implements INotifyPropertyChanged.
This control supports hot reload and live preview.
Enterprise support is available: contact sales
Source code is available: contact sales
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-android34.0 net8.0-android34.0 is compatible. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-ios17.5 net8.0-ios17.5 is compatible. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 6.0.0-pre1 | 349 | 9/14/2025 |
| 5.0.2 | 1,264 | 8/27/2024 |
| 5.0.1 | 265 | 8/15/2024 |
| 5.0.1-pre9 | 838 | 1/26/2024 |
| 5.0.1-pre8 | 417 | 1/8/2024 |
| 5.0.1-pre7 | 275 | 11/2/2023 |
| 4.8.0 | 885 | 7/14/2022 |
| 4.7.2 | 1,060 | 5/22/2021 |
| 4.7.2-pre1 | 655 | 3/17/2021 |
| 4.7.1 | 4,042 | 9/28/2020 |
| 4.7.0 | 919 | 9/24/2020 |
| 4.6.4 | 1,300 | 8/18/2020 |
| 4.6.3 | 967 | 7/11/2020 |
| 4.6.2 | 880 | 7/10/2020 |
| 4.6.1 | 891 | 7/9/2020 |
| 4.6.0 | 1,099 | 5/24/2020 |
| 4.6.0-pre1 | 722 | 5/24/2020 |
This package supports both Maui apps and native apps (including Xamarin Forms apps).
Sample use and documentation:
https://github.com/softlion/Wheelpicker-Samples
Commercial support is available at https://vapolia.eu/
This library has no dependency on SkiaSharp, and uses only hardware accelerated low level platform calls.
It is fast, small, and reliable.
,----,
,/ .`|
,` .' : ,---, ,-.
; ; /,--.' | ,--/ /| ,---,
.'___,/ ,' | | : ,---, ,--. :/ | /_ ./| ,---. ,--,
| : | : : : ,-+-. / |: : ' / ,---, | ' : ' ,'\ ,'_ /|
; |.'; ; : | |,--. ,--.--. ,--.'|' || ' / /___/ \. : | / / | .--. | | :
`----' | | | : ' | / \ | | ,"' |' | : . \ \ ,' '. ; ,. :,'_ /| : . |
' : ; | | /' :.--. .-. | | | / | || | \ \ ; ` ,'' | |: :| ' | | . .
| | ' ' : | | | \__\/: . . | | | | |' : |. \ \ \ ' ' | .; :| | ' | | |
' : | | | ' | : ," .--.; | | | | |/ | | ' \ \ ' \ | | : |: | : ; ; |
; |.' | : :_:,'/ / ,. | | | |--' ' : |--' \ ; ; \ \ / ' : `--' \
'---' | | ,' ; : .' \| |/ ; |,' : \ \ `----' : , .-./
`--'' | , .-./'---' '--' \ ' ; `--`----'
`--`---' `--`
5.0.2
update dependencies.
5.0.1
Initial release for Maui Android and iOS.