The previous section looked at the DatePicker
and TimePicker
controls, whose base class, DateTimePickerBase
, relies on a simpler control called LoopingSelector
to display date and time values.
LoopingSelector
provides all the functionality for an infinitely looping list of values.
LoopingSelector
is not intended to be used day-to-day like other controls presented in this chapter, and as a result it resides in the Microsoft.Phone.Controls.Primitives namespace. Nonetheless, it is a useful control.
To use the control you must define a data source, which can be any object that implements ILoopingSelectorDataSource
. The ILoopingSelectorDataSource
interface defines the following four members:
GetPrevious(object relativeTo)
method
GetNext(object relativeTo
) method
SelectedItem
property
SelectionChanged
event
GetPrevious
and GetNext
allow you to define the order of the data provided to the control. SelectedItem
is used to keep track of the currently selected item in the control. The SelectionChanged
event allows you to programmatically change the selected item in the control, which is normally done via the SelectedItem
property.
To present a selectable list of numeric values to the user, we create an ILoopingSelectorDataSource
called NumericDataSource
(see Listing 9.4).
NumericDataSource
allows you to define a range of integers using two properties: Minimum
and Maximum
.
public class NumericDataSource : ILoopingSelectorDataSource
{
public event EventHandler<SelectionChangedEventArgs> SelectionChanged;
protected virtual void OnSelectionChanged(SelectionChangedEventArgs e)
{
EventHandler<SelectionChangedEventArgs> tempEvent = SelectionChanged;
if (tempEvent != null)
{
tempEvent(this, e);
}
}
public object GetNext(object relativeTo)
{
int nextValue = (int)relativeTo + 1;
return nextValue <= Maximum ? nextValue : Minimum;
}
public object GetPrevious(object relativeTo)
{
int previousValue = (int)relativeTo - 1;
return previousValue >= Minimum ? previousValue : Maximum;
}
int selectedItem = 1;
public object SelectedItem
{
get
{
return selectedItem;
}
set
{
int newValue = (int)value;
if (selectedItem == newValue)
{
return;
}
int oldValue = selectedItem;
selectedItem = newValue;
OnSelectionChanged(new SelectionChangedEventArgs(
new[] {oldValue}, new[] {newValue}));
}
}
public int SelectedNumber
{
get
{
return (int)SelectedItem;
}
set
{
SelectedItem = value;
}
}
int minimum = 1;
public int Minimum
{
get
{
return minimum;
}
set
{
minimum = value;
if (selectedItem < minimum)
{
SelectedItem = value;
}
}
}
int maximum = 100;
public int Maximum
{
get
{
return maximum;
}
set
{
maximum = value;
if (selectedItem > maximum)
{
SelectedItem = value;
}
}
}
}
To use the NumericDataSource
, we expose an instance via a property in a viewmodel, like so:
NumericDataSource numericDataSource
= new NumericDataSource { Minimum = 0, Maximum = 10, SelectedNumber = 5 };
public NumericDataSource NumericDataSource
{
get
{
return numericDataSource;
}
}
A LoopingSelector
can be data bound to the NumericDataSource
property in the viewmodel. Its ItemTemplate
defines the appearance of each item retrieved from the data source. See the following example:
<toolkitPrimitives:LoopingSelector
DataSource="{Binding NumericDataSource}"
Margin="12" Width="200" Height="500" ItemSize="128,128">
<toolkitPrimitives:LoopingSelector.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding}" FontSize="54"
FontFamily="{StaticResource PhoneFontFamilySemiBold}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</toolkitPrimitives:LoopingSelector.ItemTemplate>
</toolkitPrimitives:LoopingSelector>
It is critical to assign values to the LoopingSelector
element’s Width
, Height
, and ItemSize
properties.
Figure 9.20 shows the LoopingSelector
after it has gained focus.
LoopingSelector
is a control ideally suited to the touch-centric environment of the phone.
3.12.160.63