Thursday, March 12, 2015

WPF: Simple TimePicker User Control for WPF

Hey Guys!
WPF gives us DatePicker but it doesn’t give us TimePicker. I tried to create a very simple TimePicker user control.

And the bumper offer is that it is free. Use it wherever you want. J
Hope this will help you a lot.

XAML Code:
==========

I used TextBlocks to show Hours and Minutes. Up and Down buttons are attached to increment decrement hours and minutes. Drop down with AM/PM values actually add/subtracts 12 hours from actual time based on your selection. I have created SelectedTime dependency property to do bindings.

<UserControl x:Class="UserControls.ucDateTimeUpDown"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d">
    <Grid>
        <Border BorderBrush="Black" BorderThickness=".25" />
        <StackPanel Orientation="Horizontal">


            <TextBlock x:Name="AddHoursTextBox"
                       MinWidth="20"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="{Binding DisplayTimeHours,
                                      Mode=OneWay}"
                       TextAlignment="Center" />
            <StackPanel HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Orientation="Vertical">
                <Button x:Name="HourUpButton" Click="HourUpButton_OnClick">
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Border BorderBrush="Black" BorderThickness=".25">
                                <Viewbox Width="10" Height="10">
                                    <Image Source="{StaticResource UpImage}" />
                                </Viewbox>
                            </Border>
                        </ControlTemplate>
                    </Button.Template>
                </Button>

                <Button x:Name="HourDownButton"
                        Margin="0,-1,0,0"
                        Click="HourDownButton_OnClick">
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Border BorderBrush="Black" BorderThickness=".25">
                                <Viewbox Width="10" Height="10">
                                    <Image Source="{StaticResource DownImage}" />
                                </Viewbox>
                            </Border>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </StackPanel>
            <TextBlock Margin="3,0,0,0"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="h." />
            <TextBlock Margin="3,0,0,0"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text=":"
                       TextAlignment="Center" />
            <TextBlock x:Name="AddMinutesTextBox"
                       MinWidth="20"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="{Binding DisplayTimeMinutes,
                                      Mode=OneWay}"
                       TextAlignment="Center" />


            <StackPanel HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Orientation="Vertical">
                <Button x:Name="MinutesUpButton" Click="MinutesUpButton_OnClick">
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Border BorderBrush="Black" BorderThickness=".25">
                                <Viewbox Width="10" Height="10">
                                    <Image Source="{StaticResource UpImage}" />
                                </Viewbox>
                            </Border>
                        </ControlTemplate>
                    </Button.Template>
                </Button>

                <Button x:Name="MinutesDownButton"
                        Margin="0,-1,0,0"
                        Click="MinutesDownButton_OnClick">
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Border BorderBrush="Black" BorderThickness="0.25">
                                <Viewbox Width="10" Height="10">
                                    <Image Source="{StaticResource DownImage}" />
                                </Viewbox>
                            </Border>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </StackPanel>
            <TextBlock Margin="3,0,3,0"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="m." />

            <ComboBox x:Name="AmPmComboBox"
                      MinWidth="45"
                      HorizontalAlignment="Center"
                      VerticalAlignment="Center"
                      BorderThickness=".25"
                      ItemsSource="{Binding AmPmTypes}"
                      SelectedItem="{Binding DisplayAmPm}" />
        </StackPanel>


    </Grid>
</UserControl>

Code behind:
=========

The code behind may not be so good. We can restructure and re-factor this code. I made this user control in hurry so pardon me for code quality.

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace UserControls
{
  /// <summary>
  /// Interaction logic for ucDateTimeUpDown.xaml
  /// </summary>
  public partial class ucDateTimeUpDown : UserControlINotifyPropertyChanged
  {
    #region Private Member variable

    private DateTime _currentTime = DateTime.UtcNow;
    private bool _adHours;
    private bool _addMinutes;
    private ObservableCollection<string> _amPmTypes 
new ObservableCollection<string>();
    private string _displayAmPm;

    #endregion

    #region Constructors

    public ucDateTimeUpDown()
    {
      InitializeComponent();
      this.DataContext = this;
      AmPmTypes.Add("AM");
      AmPmTypes.Add("PM");
      CurrentTime = DateTime.UtcNow.ToLocalTime();
      SelectedTime = CurrentTime.ToLocalTime().ToString("t");
    }

    #endregion

    #region Public Properties

    public ObservableCollection<string> AmPmTypes
    {
      get { return _amPmTypes; }
      set { _amPmTypes = value; }
    }

    public string DisplayTime
    {
      get { return _currentTime.ToLocalTime().ToString("t"); }
    }


    public string DisplayAmPm
    {
      get
      {
        if (_currentTime.ToLocalTime().Hour >= 0 
&& _currentTime.ToLocalTime().Hour < 12)
          _displayAmPm = AmPmTypes.FirstOrDefault(s => s.Equals("AM"));
        else
        {
          if (_currentTime.ToLocalTime().Hour >= 12)
          {
            _displayAmPm = AmPmTypes.FirstOrDefault(s => s.Equals("PM"));
          }
        }

        return _displayAmPm;
      }
      set
      {
        if (!value.Equals(_displayAmPm))
        {
          if (value.Equals("PM"))
            CurrentTime = CurrentTime.ToLocalTime().AddHours(12);
          else
          {
            CurrentTime = CurrentTime.ToLocalTime().AddHours(-12);
          }
        }
        _displayAmPm = value;
      }
    }

    public string DisplayTimeHours
    {
      get
      {
        var hours = _currentTime.ToLocalTime().Hour;
        return hours > 12 ? (hours - 12).ToString("00") : hours.ToString("00");
        //return hours.ToString();
      }
      set
      {
        var hour = 0;
        Int32.TryParse(valueout hour);
        CurrentTime = CurrentTime.ToLocalTime().AddHours(hour);
        OnPropertyChanged("DisplayTime");
        OnPropertyChanged("DisplayTimeHours");
        OnPropertyChanged("DisplayTimeMinutes");
      }
    }

    public string DisplayTimeMinutes
    {
      get { return _currentTime.ToLocalTime().Minute.ToString("00"); }
      set
      {
        var minutes = 0;
        Int32.TryParse(valueout minutes);
        CurrentTime = CurrentTime.ToLocalTime().AddMinutes(minutes);
        OnPropertyChanged("DisplayTime");
        OnPropertyChanged("DisplayTimeHours");
        OnPropertyChanged("DisplayTimeMinutes");
      }
    }

    public DateTime CurrentTime
    {
      get { return _currentTime; }
      set
      {
        _currentTime = value;

        OnPropertyChanged("CurrentTime");
        OnPropertyChanged("DisplayTime");
        OnPropertyChanged("DisplayTimeHours");
        OnPropertyChanged("DisplayTimeMinutes");
        OnPropertyChanged("DisplayAmPm");
        SelectedTime = value.ToLocalTime().ToString("t");
      }
    }

    #endregion

    #region Dependency Properties

    public static readonly DependencyProperty SelectedTimeProperty 
DependencyProperty.Register(
      "SelectedTime"typeof (string), typeof (ucDateTimeUpDown), 
new PropertyMetadata(default(string)));

    public string SelectedTime
    {
      get { return ((DateTime) GetValue(SelectedTimeProperty))
.ToLocalTime().ToString("t"); }
      set { SetValue(SelectedTimeProperty, value); }
    }

    #endregion

    #region Methods

    private void MinutesUpButton_OnClick(object sender, RoutedEventArgs e)
    {
      CurrentTime = CurrentTime.AddMinutes(1);
      SelectedTime = CurrentTime.ToLocalTime().ToString("t");
    }

    private void MinutesDownButton_OnClick(object sender, RoutedEventArgs e)
    {
      CurrentTime = CurrentTime.AddMinutes(-1);
      SelectedTime = CurrentTime.ToLocalTime().ToString("t");
    }

    private void HourUpButton_OnClick(object sender, RoutedEventArgs e)
    {
      CurrentTime = CurrentTime.AddHours(1);
      SelectedTime = CurrentTime.ToLocalTime().ToString("t");
    }

    private void HourDownButton_OnClick(object sender, RoutedEventArgs e)
    {
      CurrentTime = CurrentTime.AddHours(-1);
      SelectedTime = CurrentTime.ToLocalTime().ToString("t");
    }

    #endregion

    #region INotifyPropertyChanged Implementation

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
      if (null != PropertyChanged)
      {
        PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
      }
    }

    #endregion
  }
}



I hope you will find above user control quite useful. You suggestions are welcome. Please send your comments and improvement suggestion.

Have a good day!

2 comments:

  1. Hi Siddharth!
    I like your solution and I want to use it, but I have a problem. I store the time data in sql database, and when I want to write them in a DataDrid the initial values are always the current hour-minutes. Please help me, how can I pass my stored data.
    Best regads, Csaba Papp

    ReplyDelete
  2. Wpf: Simple Timepicker User Control For Wpf >>>>> Download Now

    >>>>> Download Full

    Wpf: Simple Timepicker User Control For Wpf >>>>> Download LINK

    >>>>> Download Now

    Wpf: Simple Timepicker User Control For Wpf >>>>> Download Full

    >>>>> Download LINK 2E

    ReplyDelete