During development, you may often encounter calendar controls in the Silverlight library. However, many controls are removed for the Windows Phone to compress space, and the calendar controls are lost. Fortunately, the Silverlight toolkit provides a control that can replace calendar, such as datetimepicker and timepicker. These controls are more suitable on mobile phones and basically meet the requirements in most cases. The datetimepicker control is displayed.
In other words, nothing is omnipotent, but occasionally there are some exceptions that these controls cannot solve very well. For example, I want to implement "Days, weeks, hours "cannot work when the options are mixed together. To ensure the consistency of user experience, we also hope that the page can be layout like the built-in controls, so the rewrite will be generated.
In fact, by looking at the source code of the original control can know how to achieve, which uses a major control is loopingselector, detailed introduction can see here: http://www.cnblogs.com/holyenzou/archive/2011/09/13/2174918.html
In fact, three classes can solve this control. Two of the classes seem to be generic and the format is fixed, including an abstract class and a subclass.
The abstract class is as follows:
using System;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using Microsoft.Phone.Controls.Primitives;namespace _365Plus.ItemControls{ // abstract the reusable code in a base class // this will allow us to concentrate on the specifics when implementing deriving looping data source classes public abstract class LoopingDataSourceBase : ILoopingSelectorDataSource { private object selectedItem; #region ILoopingSelectorDataSource Members public abstract object GetNext(object relativeTo); public abstract object GetPrevious(object relativeTo); public object SelectedItem { get { return this.selectedItem; } set { // this will use the Equals method if it is overridden for the data source item class if (!object.Equals(this.selectedItem, value)) { // save the previously selected item so that we can use it // to construct the event arguments for the SelectionChanged event object previousSelectedItem = this.selectedItem; this.selectedItem = value; // fire the SelectionChanged event this.OnSelectionChanged(previousSelectedItem, this.selectedItem); } } } public event EventHandler<SelectionChangedEventArgs> SelectionChanged; protected virtual void OnSelectionChanged(object oldSelectedItem, object newSelectedItem) { EventHandler<SelectionChangedEventArgs> handler = this.SelectionChanged; if (handler != null) { handler(this, new SelectionChangedEventArgs(new object[] { oldSelectedItem }, new object[] { newSelectedItem })); } } #endregion }}
Subclass:
using System;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;namespace _365Plus.ItemControls{ public class IntLoopingDataSource : LoopingDataSourceBase { private int minValue; private int maxValue; private int increment; public IntLoopingDataSource() { this.MaxValue = 10; this.MinValue = 0; this.Increment = 1; this.SelectedItem = 0; } public int MinValue { get { return this.minValue; } set { if (value >= this.MaxValue) { throw new ArgumentOutOfRangeException("MinValue", "MinValue cannot be equal or greater than MaxValue"); } this.minValue = value; } } public int MaxValue { get { return this.maxValue; } set { if (value <= this.MinValue) { throw new ArgumentOutOfRangeException("MaxValue", "MaxValue cannot be equal or lower than MinValue"); } this.maxValue = value; } } public int Increment { get { return this.increment; } set { if (value < 1) { throw new ArgumentOutOfRangeException("Increment", "Increment cannot be less than or equal to zero"); } this.increment = value; } } public override object GetNext(object relativeTo) { int nextValue = (int)relativeTo + this.Increment; if (nextValue > this.MaxValue) { nextValue = this.MinValue; } return nextValue; } public override object GetPrevious(object relativeTo) { int prevValue = (int)relativeTo - this.Increment; if (prevValue < this.MinValue) { prevValue = this.MaxValue; } return prevValue; } }}
When using this function, you only need to create a subclass object and set parameters.
For example, I have implemented the custom "days-hours-Minutes" control.
Front-end XAML code:
<Usercontrol X: class = "_ 365plus. itemcontrols. datetimenumberpicker "xmlns =" http://schemas.microsoft.com/winfx/2006/xaml/presentation "xmlns: x =" http://schemas.microsoft.com/winfx/2006/xaml "xmlns: D =" http://schemas.microsoft.com/expression/blend/2008 "xmlns: MC =" http://schemas.openxmlformats.org/markup-compatibility/2006 "MC: ignorable = "D" fontfamily = "{staticresource phonefontfamilynormal}" fontsize = "{staticresource quota}" foreground = "{staticresource phoneforegroundbrush}" D: designheight = "480" d: designwidth = "480" xmlns: toolkitprimitives = "CLR-namespace: Microsoft. phone. controls. primitives; Assembly = Microsoft. phone. controls. toolkit "> <grid X: Name =" layoutroot "> <grid. columndefinitions> <columndefinition width = "*"/> </grid. columndefinitions> <toolkitprimitives: loopingselector fontsize = "48" horizontalalignment = "Left" itemmargin = "20, 9, 9, 20" itemsize = "100,100" grid. column = "0" name = "selectorday" width = "90"/> <toolkitprimitives: loopingselector fontsize = "48" horizontalalignment = "Left" itemmargin = "20, 9, 100,100 "itemsize =" "grid. column = "1" name = "selectorhour" width = "90"/> <toolkitprimitives: loopingselector fontsize = "48" horizontalalignment = "Left" itemmargin = "20, 9, 100,100 "itemsize =" "grid. column = "2" name = "selectorminute" width = "90"/> <textblock fontsize = "24" horizontalalignment = "right" grid. column = "0" text = "day" textwrapping = "Wrap" verticalalignment = "center" width = "50"/> <textblock fontsize = "24" horizontalalignment = "right" Grid. column = "1" text = "Hour" textwrapping = "Wrap" verticalalignment = "center" width = "50"/> <textblock fontsize = "24" horizontalalignment = "right" Grid. column = "2" text = "min" textwrapping = "Wrap" verticalignment = "center" width = "50"/> </GRID> </usercontrol>
Backend CS code:
Using system; using system. collections. generic; using system. LINQ; using system. net; using system. windows; using system. windows. controls; using system. windows. documents; using system. windows. input; using system. windows. media; using system. windows. media. animation; using system. windows. shapes; using Microsoft. phone. controls. primitives; namespace _ 365plus. itemcontrols {public partial class datetimenumberpicker: Usercontrol {// <summary> /// select the day, hour, and minute controls /// </Summary> Public datetimenumberpicker () {initializecomponent (); selectorday. datasource = new intloopingdatasource () {minvalue = 0, maxvalue = 30, selecteditem = 0}; selectorhour. datasource = new intloopingdatasource () {minvalue = 0, maxvalue = 23, selecteditem = 0}; selectorminute. datasource = new intloopingdatasource () {minvalue = 0, maxvalue = 59, selecteditem = 0}; selectorday. isexpandedchanged + = onselectorisexpandedchanged; selectorhour. isexpandedchanged + = onselectorisexpandedchanged; selectorminute. isexpandedchanged + = onselectorisexpandedchanged; _ selectorday = selectorday; _ selectorhour = selectorhour; _ selectorminute = selectorminute;} public static readonly dependencyproperty colorproperty = dependencyproperty. registerattac Hed ("maxday", typeof (INT), typeof (datetimenumberpicker), new propertymetadata (INT) 30, datetimenumberpicker. onmaxdaypropertychanged); Private Static void onmaxdaypropertychanged (dependencyobject D, dependencypropertychangedeventargs e) {datetimenumberpicker control = D as datetimenumberpicker; If (control! = NULL) {control. selectorday. datasource = new intloopingdatasource () {minvalue = 0, maxvalue = (INT) E. newvalue, selecteditem = 0 };}public int maxday {get {return (INT) getvalue (colorproperty) ;}set {setvalue (colorproperty, value );}} private void onselectorisexpandedchanged (Object sender, dependencypropertychangedeventargs e) {If (bool) E. newvalue) {// ensure that only one selector is expanded at a time selectorday. isexpanded = (sender = selectorday); selectorhour. isexpanded = (sender = selectorhour); selectorminute. isexpanded = (sender = selectorminute) ;}} private loopingselector _ selectorday; Public loopingselector selectorday {get {return _ selectorday;} // set {_ selectorday = value ;}} private loopingselector _ selectorhour; Public loopingselector selectorhour {get {return _ selectorhour;} // set {_ selectorhour = value ;}} private loopingselector _ selectorminute; public loopingselector selectorminute {get {return _ selectorminute;} // set {_ selectorminute = value ;}}}}
Set the initial values on the display interface in these three sentences
selectorDay.DataSource = new IntLoopingDataSource() { MinValue = 0, MaxValue = 30, SelectedItem = 0 }; selectorHour.DataSource = new IntLoopingDataSource() { MinValue = 0, MaxValue = 23, SelectedItem = 0 }; selectorMinute.DataSource = new IntLoopingDataSource() { MinValue = 0, MaxValue = 59, SelectedItem = 0 };
The implementation result is as follows:
In this way, you can make a lot of similar controls, but to make the layout beautiful, it is best not to exceed three columns.