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.
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.