Fun with RadLoopingList: Creating a Numeric Picker with RadLoopingList - Introduction

Tuesday, November 08, 2011 by Deyan Ginev | Comments 3

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!

3 Comments

  • Perry 13 Dec 2011
    Hi guys,
    I'm tired of fighting this thing.  I'm new to WP7 programming and keep getting errors with the above code.  This is the last error that I got from your code:
    Error 1 'RadLoopListTest.MainPage' does not contain a definition for 'txtDecimalSeparator' and no extension method 'txtDecimalSeparator' accepting a first argument of type 'RadLoopListTest.MainPage' could be found (are you missing a using directive or an assembly reference?) C:\Users\Perry\workspace\RadLoopListTest\RadLoopListTest\MainPage.xaml.cs 39 18 RadLoopListTest

    Is there something that I'm missing?  TIA.
  • Deyan Ginev 13 Dec 2011
    Hi Perry,
    Just update the XAML code at the part <TextBlock Text="," FontSize="40" VerticalAlignment="Center" Height="110" Padding="0, 58, 0, 0"/> and make it look like: <TextBlock Text="," x:Name="txtDecimalSeparator" FontSize="40" VerticalAlignment="Center" Height="110" Padding="0, 58, 0, 0"/>.
    As you can see, the Name of the text block which is used as a decimal separator is not defined in XAML and therefore accessing it in C# is not possible. After updating the XAML code as shown above, you should be able to compile the code. We are going to update the XAML code above to reflect this. Also, if you continue experiencing difficulties, drop us a line by opening a new support ticket or a thread in our forums regarding this issue.
  • Perry 13 Dec 2011
    Thank you for your help Deyan.  There are a few other problems as well, but I was able to work around them.

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)