windows phone开发学习--自定义datetimepicker

在做开发的时候,经常会碰见设定时间日期的,本来silverlight库中有calendar控件,但是windows phone为了压缩空间砍掉了很多控件,calendar控件也自然没有了。不过好在silverlight toolkit包中提供了一个可以取代calendar的控件,比如datetimepicker,timepicker,这些控件放在手机上显然更合适,基本满足了大多数情况下的要求。下图展示的就是datetimepicker控件

windows phone开发学习--自定义datetimepicker_第1张图片


话说回来,没有一样东西是万能的,但是偶尔也有一些例外情况而这些控件不能很好的解决,例如我要求实现带“天数,星期,小时”混杂在一起的选项设定时就不行了,为了用户体验的一致性,我们也希望选则页面能像自带的控件这样布局,于是改写就产生了。

其实通过查阅原来控件的源代码可以知道大致是如何实现的,这其中用到一个最主要的控件是LoopingSelector,详细介绍可以看这里:http://www.cnblogs.com/holyenzou/archive/2011/09/13/2174918.html

其实三个类就能搞定这个控件,其中两个类貌似是通用的,格式也是固定的,包括一个抽象类和一个子类

抽象类如下:

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

子类如下:

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;
        }
    }
}

使用的时候只需要创建子类对象,设定参数即可

例如我这里就实现了自定义“天数-小时-分钟”的控件

前台xaml代码:

<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 PhoneFontSizeNormal}"
    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="*" />
            <ColumnDefinition Width="*" />
            <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,9,20" ItemSize="100,100" Grid.Column="1" Name="selectorHour" Width="90"  />
        <toolkitPrimitives:LoopingSelector FontSize="48" HorizontalAlignment="Left" ItemMargin="20,9,9,20" ItemSize="100,100" Grid.Column="2" Name="selectorMinute" Width="90" />
        <TextBlock FontSize="24" HorizontalAlignment="Right" Grid.Column="0" Text="天" TextWrapping="Wrap" VerticalAlignment="Center" Width="50" />
        <TextBlock FontSize="24" HorizontalAlignment="Right" Grid.Column="1" Text="小时" TextWrapping="Wrap" VerticalAlignment="Center" Width="50" />
        <TextBlock FontSize="24" HorizontalAlignment="Right" Grid.Column="2" Text="分钟" TextWrapping="Wrap" VerticalAlignment="Center" Width="50" />
    </Grid>
</UserControl>

后台cs代码:

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>
        /// 选择天、时、分的控件
        /// </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.RegisterAttached("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; }
        }

    }
    
}

设定显示界面上的初始值就在这三句

 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 };

实现效果如下
windows phone开发学习--自定义datetimepicker_第2张图片


通过这种方法,可以做出很多类似的控件,不过为了布局美观,最好不要超过三栏。

你可能感兴趣的:(windows,object,calendar,equals,Class,silverlight,phone)