Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

iOS UIPickerView-like control in WPF

0.00/5 (No votes)
7 Nov 2011 1  
Sample code and walkthrough for creating a UIPickerView (the tumblers UI common on the iPhone) control in WPF.

Introduction

In this article, I will describe a UIPickerView-like control I created using WPF. The UIPickerView is an iOS control for picking an item from a list via a tumbler. Typically, this control is associated with touch input, but I have found it to work well with the mouse as well. I can envision it being potentially useful in a desktop application, especially if a touch-enabled monitor is part of the system.

wpfuipicker.PNG

Background

A couple of months ago, while writing an article on user interface design, I was trying to think of different ways to construct a date/time control. One of the ideas I came up with was to use tumblers for the different date/time parts, just like in a UIPickerView control. During that exploration, I created a prototype WPF implementation. I have decided to clean up that prototype and share it with the CodeProject community.

Using the Code

Using the control is pretty straightforward. Simply include the WpfUIPickerLib namespace in your XAML file and create a WpfUIPickerControl element. There are only two custom dependency properties you need to be aware of:

  • AlwaysOpen: If set to True, WpfUIPickerControl will always be open and the tumblers will be visible. If set to False (the default), the control will look like a textbox displaying only the selected value(s). Clicking on the control will open it and the tumblers will then become visible, enabling the user to pick a new value. Clicking anywhere outside the control will close it (if AlwaysOpen is False).
  • Tumblers: This dependency property is a list of WpfUIPickerLib.TumblerData objects that represent the different tumblers you want to display. Each TumblerData instance represents a different tumbler in the control.

The following XAML demonstrates including the WpfUIPickerLib namespace and how to declare a WpfUIPickerControl object:

<Window x:Class="WpfUIPicker.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfui="clr-namespace:WpfUIPickerLib;assembly=WpfUIPickerLib"
        Title="MainWindow" Height="300" Width="325"
        x:Name="thisWnd">
    <StackPanel>
        <TextBlock Text="WpfUIPickerControl with AlwaysOpen set to True" 
               HorizontalAlignment="Center" />
        <wpfui:WpfUIPickerControl HorizontalAlignment="Center" AlwaysOpen="True" 
           Tumblers="{Binding ApparelTumblers, ElementName=thisWnd}" />
        <TextBlock Text="WpfUIPickerControl with AlwaysOpen set to False" 
           HorizontalAlignment="Center" Margin="0,20,0,0"/>
        <wpfui:WpfUIPickerControl HorizontalAlignment="Center" 
           AlwaysOpen="False" Tumblers="{Binding DateTimeTumblers, ElementName=thisWnd}" />
    </StackPanel>
</Window>

The TumblerData object is a thin wrapper around the list of values you want to display in a single tumbler (ToString will be called on each value). It is needed by the control to trigger updates, to get/set the selected value, and to display a "seperator" (optional). Because I originally created this control for date/time, I wanted the "closed" version of the control to be able to display string tokens between tumbler values. For example, if I created three tumblers for the date (month, day, year), and the user picked 9 for the month, 5 for the day, and 2005 for the year, then I wanted the closed version of the control to display "09/05/2005". To support this usage, you can just set the string "/" to be the separator in the TumblerData object for the month and day tumblers. The TumblerData.Seperator property is ignored if the control is set to AlwaysOpen=true.

The following code demonstrates how to create TumblerData objects for a date/time implementation that supports dates from 1/1/1990 to 12/31/2011:

public List<TumblerData> DateTimeTumblers
{
    get
    {
        List<TumblerData> retVal = new List<TumblerData>();
        List<int> years = new List<int>();
        for (int i = 1990; i < 2012; ++i)
            years.Add(i);

        List<string> months = new List<string>();
        for (int i = 1; i <= 12; ++i)
            months.Add(String.Format("{0:d2}", i));

        List<string> days = new List<string>();
        for (int i = 1; i <= 31; ++i)
            days.Add(String.Format("{0:d2}", i));

        List<string> hours = new List<string>();
        for (int i = 1; i <= 12; ++i)
            hours.Add(String.Format("{0:d2}", i));

        List<string> min = new List<string>();
        for (int i = 0; i < 60; ++i)
            min.Add(String.Format("{0:d2}", i));

        retVal.Add(new TumblerData(months, 8, "/"));
        retVal.Add(new TumblerData(days, 4, "/"));
        retVal.Add(new TumblerData(years, 12, ""));
        retVal.Add(new TumblerData(hours, 10, ":"));
        retVal.Add(new TumblerData(min, 0, ""));
        retVal.Add(new TumblerData(
               new string[] { "AM", "PM" }.ToList<object>(), 0, ""));
        return retVal;
    }
}

Points of Interest

WpfUIPickerControl supports three different ways to change the value of a tumbler: drag, mouse wheel, and just click on the desired value. The control implements "closed" by hiding non-selected values (hence the funky binding in the valueTemplate). Each tumbler is rendered as a StackPanel within a grid on a canvas. Drag is implemented by changing the Canvas.Top property on the grid.

History

The first iPhone was unveiled by Steve Jobs on January 9, 2007.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here