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

Working with Dates on Windows Phone 7

2 Dec 2010 3  
Article presents various data editors—all built with the help of MobileForms Toolkit from Resco.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

Article presents various data editors—all built with the help of MobileForms Toolkit from Resco.

Introduction

Windows Phone 7 (WP7) programming combines several technologies:

  • .NET (WP7 uses a subset of the full .NET class library.)
  • C#
  • Silverlight for WP7. (A simplification of the desktop SVL.)

Mastering these technologies for a programmer coming from (say) Windows Mobile programming is a real problem. This article shows how to work with dates using MobileForms Toolkit from Resco.

Prerequisites

The target audience is a C# programmer with a reading knowledge of Silverlight. At the very minimum the reader should understand basic Silverlight controls and layout.

You need to have installed Windows Phone Developer Tools.

Further you should install Resco MobileForms Toolkit, Windows Phone 7 Edition from http://www.resco.net/developer/mobileformstoolkit/. The Toolkit contains a set of useful controls that simplify Windows Phone 7 programming.

Simple use Cases

MobileForms Toolkit

The screenshots above are notoriously known to all Windows Phone 7 users. Yes, the famous date/time pickers.

The MobileForms Toolkit does not (yet) provide direct access to these pickers, instead it packages them into a few higher level controls. Following screenshot shows three of these controls in action:

MobileForms Toolkit

Here is the corresponding XAML code:

 xmlns:r="clr-namespace:Resco.Controls;assembly=Resco.Controls"
		…
	<r:DateEditor Text="{Binding Path=ModifiedOn}"  
             TextDecoration="Underline" FormatString="{}{0:D}" />1
	<r:TimeEditor Text="{Binding Path=ModifiedOn}"  
             FormatString="{}Modified on {0:t}" />
	<r:DetailItemDateTime Label="Last Transaction"  DataMember="ModifiedOn" />
	<r:DetailItemDateTime Label="Last Transaction"  
             DataMember="ModifiedOn" TimeVisibility="Collapsed" />
1) Leading {} is not part of the actual format string. It is a XAML escape allowing subsequent use of curly brackets.

The DataContext is set to an object with the property

public DateTime ModifiedOn { get; set; }

All controls act as editors of this property. (The effect is achieved through binding.)

DateEditor/TimeEditor are text controls that open corresponding picker upon a click. The above code demonstrates custom formatting; normally you would not use it.

DetailItemDateTime uses appearance typical for all DetailItem-derived classes 2, i.e. (optional) label and specific look&feel. You can set it up as date or time editor (using DateVisibility/TimeVisibility properties) or as a full DateTime editor (default). Instead of binding, you can use simpler DataMember syntax 3. You can customize date and time formats and a number of other properties.

2) These controls are primarily intended for use in DetailView form where they provide common look&feel. As the sample code demonstrates, they can be used independently as well.

by explicit binding

3) DataMember refers to the property name to be used for binding that is created in the class code. This terminology is commonly used in the .NET world for data-related controls. In fact we could replace
		DataMember="ModifiedOn"
			by explicit binding
			Value={Binding Path=ModifiedOn, Mode=TwoWay}

So much for the basic date controls. In the future more similar controls will be added depending on the user requests. The rest of this article will demonstrate some interesting uses of another control – MonthCalendar.

Selecting dates using MonthCalendar

MonthCalendar is a rather advanced control. Its task is to schematically present a series of appointments. However, all we need right now is the ability to select a single date. No appointments 4, just the reaction to selection change.

4) In other words, we shall use null DataSource.

The UI looks as follows:

MobileForms Toolkit

A MonthCalendar control is in the bottom part. You can list individual months and select suitable day.

A TextBlock in the upper part will reflect current selection. This is just to prove the concept. Your arrangement will probably differ – for example a popup dialog with ok/cancel buttons.

The important code is almost trivial:

 // Excerpt from MonthCalendarPage.xaml
	<StackPanel Orientation="Horizontal">
	<r:PhoneTextControl  Text="Selected date:  />
	<r:PhoneTextControl  x:Name="m_selected" />
	</StackPanel>
	<r:MonthCalendar x:Name="m_calendar"  Height="480" SelectionChanged="DayChanged"/>

	    // MonthCalendarPage.xaml.cs
		// Calendar has null DataSource; we only react to the item  selection.
		public partial class MonthCalendarPage : PhoneApplicationPage
		{
		public  MonthCalendarPage()
		{
		InitializeComponent();
		}
		                private  void DayChanged(object sender, EventArgs e)
		{
		DateTime?  dt = m_calendar.SelectedDate;
		if  (dt != null)
		m_selected.Text  = m_calendar.SelectedDate.Value.ToString("d");
		//  NavigationService.GoBack();         
                  // Also  possible: Return to previous page
		}
		}

XAML code defines MonthCalendar instance and a text field providing feedback for date selection. As we mentioned above – this is just a proof of the concept. For the real use you would need to package MonthCalendarPage into a new DateEditor class somehow:

  • It could be a PhoneTextControl-derived class (i.e. a TextBlock with formatting capabilities), that could be bound to a DateTime-based property. The control would open MonthCalendarPage inside a Popup as a reaction to the MouseLeftButtonDown event.
  • Or it could be a HyperlinkButton-derived control able to bind to a DateTime-based property. This solution would replace the use of a Popup by the HyperlinkNavigation.

Both solutions require additional non-trivial programming. A bit easier is the direct usage of MonthCalendarPage. (NavigationService.GoBack()) However, you still need to handle the transfer of the edited date.

Date multi-selector using MonthCalendar

Here is another interesting example – MonthCalendar control used to select multiple dates. The control allows you to page month by month and select/unselect individual days. A brief summary of the current selection is displayed at the top of the page.

MobileForms Toolkit

Calendar is implemented as a collection of 1-day events; the event is represented by DateTime object 5. Except the ICalendarDataSource implementation we shall provide two methods:

  • AddOrRemove() is used as a toggle – A new date is added to the list, an old one is removed.
  • ToString() provides brief summary of the current selection
5 Calendar is a class implementing ICalendarDataSource - a minimalistic interface designed for appointment modeling. The appointment (event) is a time interval plus some GUI representation. MonthCalendar itself provides default visualization of the appointments (blue rectangles). That’s good enough. Concerning the time, we need just one characteristic – the day. Hence we don’t need any special class, but can use standard DateTime class right away
public class MyCalendar : ICalendarDataSource
	{
	//  An event is represented by DateTime object
	List<DateTime>  m_list = new List<DateTime>();
	//  Return list of events between start-end dates
	IEnumerable  ICalendarDataSource.GetRange(DateTime start, DateTime end)
	{
	var  list = new List<Object>();
	foreach(  DateTime d in m_list)   {
	if(  start <= d  &&  d <= end )
	list.Add(d);
	}
	return  list;
	}
	//  Returns time interval describing given event
	void  ICalendarDataSource.GetElementRange(object elem, 
             out DateTime start, out DateTime  end)      {
    // In  our case the event itself describes the time interval
	start  = end = (DateTime)elem ;
	}
	//  Reaction to the click
	public  void AddOrRemove(DateTime dt)
	{
	foreach  (DateTime d in m_list)  {
	if  (d == dt)  {
	m_list.Remove(d);                // Old event is removed
	return;
	}
	}
	m_list.Add(dt);                     // No old event found =>  add a new event
	}
	// Used  for presentation purposes
		public  override string ToString()
		{
		DateTime  min = DateTime.MaxValue;
		DateTime  max = DateTime.MinValue;
		foreach  (DateTime d in m_list)  {
		if  (min > d)  min = d;
		if  (max < d  max = d;
		}
		if  (m_list.Count == 0)
		return  "Nothing; click some day(s)";
		if  (m_list.Count == 1)
		return  min.ToString("d");
		else
		return  String.Format("{0} days; {1:d} - {2:d}", m_list.Count, min, max);
		}
	}

We can finally implement MonthCalendarPage.

        // C# code
		public partial class MonthCalendarPage : PhoneApplicationPage
		{
		// We  use static DataSource to provide continuity between
                  // multiple uses of  MonthCalendarPage.
		//Replace  by the implementation that best suits to your needs.
		static  MyCalendar DataSource = new MyCalendar();
		public  ICalendarDataSource MyCalendar  {
		get  { return DataSource; }
		}
		                public  MonthCalendarPage()  {
			DataContext  = this;
			InitializeComponent();
			m_selected.Text  = DataSource.ToString();
			}
			                //  SelectionChanged event handler
			private  void DayChanged(object sender, EventArgs e)   {
			DateTime?  val = m_calendar.SelectedDate;
			if  (val != null)  {
			DateTime  dt = val.Value;
			DataSource.AddOrRemove(dt);
			m_selected.Text  = DataSource.ToString();
			//  A trick to force calendar refresh because
                            // theResetList method is private.
			//m_calendar.ResetList();
			// (Will be available in  next release.)
			DateTime  x = m_calendar.Date;
			//  Just force Date change
			m_calendar.Date  = m_calendar.Date.AddDays(1);
			// Revert  the original ate value
			m_calendar.Date  = x;
			}
			}
			}

	// Excerpt from MonthCalendarPage.xaml
	<StackPanel Grid.Row="1">
	<StackPanel  Orientation="Horizontal">
	<r:PhoneTextControl  Text="Selected date:" Margin="10" />
	<r:PhoneTextControl  x:Name="m_selected" />
	</StackPanel>
	<r:MonthCalendar  x:Name="m_calendar" Height="480"  
	    SelectionChanged="DayChanged"/>
	</StackPanel>

StringToDayTimeConverter

Ever wondered how the dates can be entered into Xaml? For example

 <WeekCalendar  Minimum="11/1/2010"  Maximum="11/30/2011" Date="today" />

Well, Silverlight is simpler than WPF, but this is one of many examples where one really misses WPF power. We cannot add the ability to read dates to a (for example) system class, but if the code is under our control, then all we need to do is to define suitable TypeConverter attribute for the property we want to use in Xaml.

Here is an example how the WeekCalendar control defines the property used in the Xaml code above:

        // The only added line
		[TypeConverter(typeof(StringToDateTimeConverter))]
		public DateTime Minimum   { get; set; }

StringToDateTimeConverter class is part of the namespace Resco.Controls.Tools. The nice thing about this converter is that it not only handles a lot of date formats (it is based on DateTime.TryParse()), but also special strings “today” and “Today”.

Note you don’t need to add any converter to numeric types as the Silverlight handles the conversion automatically.

What’s Next

Resco is a company with a long tradition of mobile programming covering many platforms and both end-user applications and developer tools. The Toolkit – as it is published now –matured a bit since the first version. However, this is still an early development stage. In the near future existing controls will be enhanced and new ones added.

Any feedback is welcome – either here or directly at Resco forums.

About the Author

Jan Slodicka. Programming for over 30 years. Covered several desktop platforms and programming languages. Since 2003 working for Resco on mobile technologies – Palm OS, Windows Mobile, now Windows Phone 7.

You can contact me at: jano (at) resco (dot) net.

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