A few weeks ago we received a support ticket from a customer using RadControls for Windows Phone 7 who wanted to use RadLoopingList to create a control that will allow the end-user to pick numbers in the range 0.00 – 99.99. The requirement was that each decimal position should be represented by a looping list allowing for selection between all digits from 0 to 9. We managed to quickly set up a small WP7 project that demonstrates how this can be done with RadLoopingList and helped our customer in creating a control that looks this way:
Since this scenario could prove useful for many of you, I decided to share it by explaining the steps we took to build this simple control out of already existing components from the RadControls for Windows Phone 7 suite. In another blog post that is yet to come I will extend this behavior by using RadPickerBox and thus creating a RadDate- or RadTimePicker like control for numeric values.
As you can see, the main page contains four RadLoopingList instances that are bound to four different LoopingListDataSource instances providing all the digits in the range 0-9. Between the second and third looping lists there is a text block representing a decimal separator. The logic behind is quite simple: when the selection in one of the looping lists changes, the selected value is generated by taking the selected digits from all looping lists and composing it accordingly. Additionally, I have modified the styles for the looping list items a bit so that they fit in this scenario and also for better readability.
Let's start with the XAML that builds the page:
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"Transparent"
HorizontalAlignment
=
"Center"
>
<
Grid.RowDefinitions
>
<
RowDefinition
/>
<
RowDefinition
Height
=
"Auto"
/>
</
Grid.RowDefinitions
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
telerikPrimitives:RadLoopingList
ItemWidth
=
"110"
ItemHeight
=
"110"
x:Name
=
"loopingList1"
IsCentered
=
"True"
IsExpanded
=
"False"
/>
<
telerikPrimitives:RadLoopingList
ItemWidth
=
"110"
ItemHeight
=
"110"
x:Name
=
"loopingList2"
IsCentered
=
"True"
IsExpanded
=
"False"
/>
<
TextBlock
Text
=
","
FontSize
=
"40"
VerticalAlignment
=
"Center"
Height
=
"110"
Padding
=
"0, 58, 0, 0"
/>
<
telerikPrimitives:RadLoopingList
ItemWidth
=
"110"
ItemHeight
=
"110"
x:Name
=
"loopingList3"
IsCentered
=
"True"
IsExpanded
=
"False"
/>
<
telerikPrimitives:RadLoopingList
ItemWidth
=
"110"
ItemHeight
=
"110"
x:Name
=
"loopingList4"
IsCentered
=
"True"
IsExpanded
=
"False"
/>
</
StackPanel
>
<
TextBlock
x:Name
=
"txtValue"
Grid.Row
=
"1"
/>
</
Grid
>
We have a grid panel holding four RadLoopingLists and a TextBlock in the middle that shows the decimal separator. Below the StackPanel that holds the RadLoopingLists I have put a TextBlock that will show the currently selected value in the numeric picker control. Now let's look at the code:
public
MainPage()
{
InitializeComponent();
IntegerLoopingListDataSource dataSource =
new
IntegerLoopingListDataSource(10);
this
.loopingList1.DataSource = dataSource;
this
.loopingList1.SelectedIndexChanged +=
this
.OnLoopingList_SelectedIndexChanged;
this
.loopingList1.ScrollCompleted +=
this
.OnLoopingList_ScrollCompleted;
this
.loopingList2.DataSource = dataSource;
this
.loopingList2.SelectedIndexChanged +=
this
.OnLoopingList_SelectedIndexChanged;
this
.loopingList2.ScrollCompleted +=
this
.OnLoopingList_ScrollCompleted;
this
.loopingList3.DataSource = dataSource;
this
.loopingList3.SelectedIndexChanged +=
this
.OnLoopingList_SelectedIndexChanged;
this
.loopingList3.ScrollCompleted +=
this
.OnLoopingList_ScrollCompleted;
this
.loopingList4.DataSource = dataSource;
this
.loopingList4.SelectedIndexChanged +=
this
.OnLoopingList_SelectedIndexChanged;
this
.loopingList4.ScrollCompleted +=
this
.OnLoopingList_ScrollCompleted;
this
.UpdateSelection();
this
.txtDecimalSeparator.Text = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator;
}
In the constructor of my page I bind all RadLoopingLists to an instance of the IntegerLoopingListDataSource class (code available just in a second). I also bind to the ScrollCompleted and SelectedIndexChanged events of all looping lists in order to be able to compose the currently selected value (done in the SelectedIndexChanged event by calling the UpdateSelectedValue method), and to collapse all visual items but the selected one to mimic the behavior in the date and time picker controls (done in the ScrollCompleted) event. Here is the code:
private
void
OnLoopingList_ScrollCompleted(
object
sender, Telerik.Windows.Controls.LoopingList.LoopingListScrollEventArgs e)
{
RadLoopingList typedSender = sender
as
RadLoopingList;
typedSender.IsExpanded =
false
;
}
private
void
OnLoopingList_SelectedIndexChanged(
object
sender, EventArgs e)
{
this
.UpdateSelectedValue();
}
private
void
UpdateSelectedValue()
{
int
thousands =
this
.loopingList1.SelectedIndex;
int
hundreds =
this
.loopingList2.SelectedIndex;
int
tens =
this
.loopingList3.SelectedIndex;
int
ones =
this
.loopingList4.SelectedIndex;
this
.selectedValue = thousands * 10.0 + hundreds + tens / 10.0 + ones / 100.0;
this
.txtValue.Text =
"Value: "
+
this
.selectedValue;
}
Here is the code of my special IntegerLoopingListDataSource class:
public
class
IntegerLoopingListDataSource : LoopingListDataSource
{
public
IntegerLoopingListDataSource(
int
count)
:
base
(count)
{
}
protected
override
LoopingListDataItem GetItemCore(
int
index)
{
return
new
LoopingListDataItem(index.ToString());
}
protected
override
void
UpdateItemCore(LoopingListDataItem dataItem,
int
logicalIndex)
{
dataItem.Text = logicalIndex.ToString();
}
}
Yes, this is everything you need to do in order to have this neat experience in your WP app. In a further blog post related to this scenario I am also going to demonstrate how to integrate this user control with RadPickerBox and thus create the ultimate number picker control for WP7!
Stay tuned!