I recently ran into an interesting issue when using the DatePicker control that is available in the Silverlight for Windows Phone Toolkit. At first glance it looked like everything was working fine, but on closer inspection, I noticed that it seemed that the date I was selecting was not being returned from the control. Once I figured out what was happening, I realized the same thing can happen when using the related TimePicker control.
I discovered this when working on a Master/Details application. The Master list provided a view of a list of items, where each item contains a set of properties that includes a Date. Through the Master page, the user can select to edit an item, which navigates to a dedicated Editing page and opens the details of the item to edit…a fairly common scenario. The general logic is as follows:
NavigationService.Navigate(new Uri("/EditingPage.xaml?Id=" + selectedItem.Id, UriKind.Relative));
Excerpt form Page Markup:
The OnNavigatedTo override code follows:
The DatePicker and TimePicker controls are included in the Silverlight for Windows Phone Toolkit. The Toolkit consists of a set of controls and other utilities that are released “out of band” from the regular tools’ release. The first formal release of this toolkit was in November 2010, followed by a February 2011 update. In addition to not having to wait for a new update to the full SDK for these tools, they are also published on CodePlex with full source code, which provides great insight into how things work, both for educational and forensic purposes.
The DatePicker and TimePicker controls offer a touch-optimized experience for selecting the corresponding values. The value is initially presented in the phone UI in text format. When the control is selected, a series of 3 rotating lists are presented for selecting a specific value, as illustrated below:
“Control View” for Date Picker & TimePicker controls
The DatePicker Control In “Picker” View |
The TimePicker Control in “Picker” View |
At the heart of the problem is the fact that although it may not be immediately obvious, the DatePicker and TimePicker controls actually use full-blown PhoneApplicationPage pages to present their selection lists (though the fact that they contain ApplicationBar buttons is probably a big hint.) However, in some regards, these pages do not behave like “normal” pages – for example, when the application is deactivated and subsequently reactivated, you are not returned to the picker-page, but rather to your page that contains the control. The picker controls go to some length to simulate this popup behavior:
So now we have a page that is pretending to be a popup…we’ve all done something like this, and know from experience that inevitably it leads to problems…if you aren’t aware of the masquerade and don’t anticipate the “true” behavior, complications soon follow. In this case, “closing the popup” results in a traditional page navigation sequence…including the execution of the OnNavigatedTo handler, which dutifully retrieves the Id of the item being edited from the query string, and loads the object to be edited into the page, which is then bound to the controls, including the DatePicker control….uh-oh. Wait a minute! How does the list-page communicate its selection back to the original page? Once again it is time to go back to the toolkit source code.
It is important to note the relationship between the Page Navigation override methods and the Frame Navigation events:
Note that the OnNavigatedTo handler is invoked a few steps AFTER the firing of the Navigated event. Therefore, any values set in the Navigated event can easily be overwritten in the OnNavigatedTo handler, which is exactly the case that I ran into. The control’s value was being set to the value selected in the picker page, which was in fact triggering all the necessary bindings. Then the code in the OnNavigatedTo override was resetting this with the original object value.
That’s Nice…Now What?
As I see it, there is a general solution that can be applied, with two possible manifestations. I have to admit that they both feel a little awkward…maybe I’ll stumble into something down the road that leaves me feeling less “dirty.” With that wonderful preamble, let’s look at the solution.
The general solution is to record that the current navigation is being triggered as a result of a call to the picker control and use that information to prevent and/or repair the undesired value override. I mentioned there were (at least) two ways to do this.
The first approach involves using the OnNavigatedFrom override to detect if the target page is a DatePickerPage (or TimePickerPage), and if so, record a token in State that a Picker operation is in-progress. In OnNavigatedTo, detect this token, retrieve the value that must have been set when the control was updated, and bypass the use of the query string id to reset the underlying value. (This is missing something for tombstoning, which is detailed below.)
In the second approach, the control’s ValueChanged event that was described above can be used in a similar value to determine that a picker operation is in progress, which can then be used to bypass the use of the query string id, as mentioned above.
It is generally a good practice to add support for “remembering” the values that have been changed when the application is deactivated and restoring them when the application is reactivated, in order to save the user’s hard work on the page. In that case, in OnNavigatedFrom the necessary details can be preserved (the code below uses a serializable object and just inserts that into the Page State dictionary), and in OnNavigatedTo, retrieve the value if necessary and use it for editing if present, and possibly override the saved date value if necessary. If the value is not available for retrieval, the page navigation must be the result of the initial request, so the Id should be retrieved from the query string, and subsequently the item to be edited retrieved form its source.
Hopefully, if anyone else is seeing the same issue, this can shed some light on the problem and present some possible solutions. The DatePicker and TimePicker controls are convenient and visually appealing approaches to presenting the data they represent in a touch-friendly manner. However, to be used effectively, it is important to understand their nature as separate pages, despite any efforts they may make to masquerade as something else.
Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…
Cloud management is difficult to do manually, especially if you work with multiple cloud…
Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…
https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…
FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…
Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…