Both the DatePicker
and TimePicker
allow you to change the full-screen picker page using the DateTimePickerBase.PickerPageUri
property. This property is normally specified using a component URI, with the assembly and path to the PhoneApplicationPage
. In the following example a DatePicker
uses a custom picker page, located in an Examples assembly:
<toolkit:DatePicker Value="{Binding Date, Mode=TwoWay}"
Header="date with custom picker"
PickerPageUri="/Examples;component/CustomDatePickerView.xaml" />
The task of the picker page is to allow the user to select a DateTime
value, and then to use the NavigationService
to navigate back to the original page. A picker page must implement the IDateTimePickerPage
interface. This interface consists of a single nullable DateTime
property called Value
.
A custom picker page called CustomDatePickerView
is located in the ControlExamples/WindowsPhoneToolkit/DateAndTimePickers directory in the downloadable sample code. The sample allows the user to select from an arbitrary list of DateTime
values.
The viewmodel consists of a list of DateTime
values that the user selects from, a single DateTime
property that tracks the selected date, and a command that is used to set the selected date value from buttons in the view.
The list of dates is defined in the viewmodel like so:
readonly List<DateTime> dates = new List<DateTime>();
public IEnumerable<DateTime> Dates
{
get
{
return dates;
}
}
The list is populated with five DateTime
values, within the viewmodel constructor:
for (int i = 1; i < 6; i++)
{
dates.Add(DateTime.Now.AddYears(i));
}
Each DateTime
value in the list is presented as a button in the view.
Within the viewmodel, a property called Date
holds the selected date:
DateTime? date = DateTime.Now;
public DateTime? Date
{
get
{
return date;
}
set
{
Assign(ref date, value);
}
}
An ICommand
is used to set the Date
property via buttons in the view. The ICommand
is shown in the following excerpt:
readonly DelegateCommand<DateTime?> setDateCommand;
public DelegateCommand<DateTime?> SetDateCommand
{
get
{
return setDateCommand;
}
}
The setDateCommand
is initialized in the viewmodel constructor. The constructor accepts an Action
parameter that is used during execution of the SetDateCommand
to call the NavigationService.GoBack
method, after a DateTime
value has been selected by the user. The constructor is shown in full in the following excerpt:
public CustomDatePickerViewModel(Action completeAction)
{
for (int i = 1; i < 6; i++)
{
dates.Add(DateTime.Now.AddYears(i));
}
setDateCommand = new DelegateCommand<DateTime?>(
dateTime =>
{
if (dateTime == null)
{
return;
}
Date = dateTime;
if (completeAction != null)
{
completeAction();
}
});
}
The custom picker view initializes its viewmodel, passing it a lambda expression, which allows the viewmodel to return to the calling page.
Note
As an alternative to passing the viewmodel a lambda expression, you may want to consider using a dedicated INavigationService
for your app. Such a service is discussed in Chapter 29, “Storing App Data in a Local Database,” and exists as part of the Calcium framework for Windows Phone http://calciumsdk.com.
Passing a reference to a page property, as shown in this example, causes the page to remain alive, ineligible for garbage collection, for the lifetime of the viewmodel. If the viewmodel does not share the same lifetime as the view, then a memory leak may ensue. In this example, the lifetime of the viewmodel is the same as the view’s, and hence it is not an issue.
When the viewmodel determines that a DateTime
value has been acquired, it invokes the specified Action
, and the page with the DatePicker
retrieves the DateTime
value from the page’s Value
property (see Listing 9.3).
public partial class CustomDatePickerView
: PhoneApplicationPage, IDateTimePickerPage
{
public CustomDatePickerView()
{
InitializeComponent();
DataContext = new CustomDatePickerViewModel(
() => NavigationService.GoBack());
}
CustomDatePickerViewModel ViewModel
{
get
{
return (CustomDatePickerViewModel)DataContext;
}
}
public DateTime? Value
{
get
{
return ViewModel.Date;
}
set
{
ViewModel.Date = value;
}
}
}
The XAML for the view contains a ListBox
that is bound to the list of DateTime
values. A DataTemplate
is used to present each DateTime
as a button. Each button is bound to the SetDateCommand
of the viewmodel, as shown in the following excerpt:
<StackPanel x:Name="ContentPanel" Grid.Row="1">
<ListBox ItemsSource="{Binding Dates}"
SelectedItem="{Binding Date}">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}"
Command="{Binding DataContext.SetDateCommand,
ElementName=page}"
CommandParameter="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
When visible, the custom picker page presents the five DateTime
values, as shown in Figure 9.19.
3.138.60.166