Click here to Skip to main content
Click here to Skip to main content

Using one DateTimePicker for multiple TextBox controls

, 10 Jul 2005
Rate this:
Please Sign up or sign in to vote.
Using TextBox controls for dates and using only one DateTimePicker control for all the TextBox controls. DateTimePicker is placed on top of the TextBox the user double-clicked and made visible. User may optionally enter a date without using the DateTimePicker. Basic date validation is implemented.

Introduction

Sometimes we have forms with many TextBox controls that are used for dates. If you have a form with a TabControl control and each TabPage contains many TextBox controls for dates and you don't want to use a DateTimePicker for each TextBox control, then go through this article that describes how to use one DateTimePicker for all the TextBox controls. The DateTimePicker control is hidden until a TextBox control's DoubleClick event is raised.

We also need to validate these TextBox controls, because here I allow the user to manually edit the TextBox.Text property. The user may want to delete the date or just modify it manually. I wanted to take the advantage of the DateTime class' built-in validation, so that I need not write a complex date validation procedure. In this demo, I use the DateTime class in conjunction with simple text validations for the TextBox controls.

The following code snippets are key to this small application. Comments are interspersed throughout the code for clarification.

Class-level variable

I declare a class-level variable (txtDateBoxSender) of type TextBox, so that I can access its attributes from any method:

private System.Windows.Forms.TextBox txtDateBoxSender;

Event Handlers

In the InitializeComponent() method, I have the following event handlers for all the date TextBox controls:

  • DateKeyPressed
  • DateBox_TextChanged
  • TextBoxEnter
  • ValidateDate
this.TextBox3.KeyPress += 
    new System.Windows.Forms.KeyPressEventHandler(this.DateKeyPressed);
this.TextBox3.DoubleClick += 
    new System.EventHandler(this.DateBox_TextChanged);
this.TextBox3.Enter += new System.EventHandler(this.TextBoxEnter);
this.TextBox3.Leave += new System.EventHandler(this.ValidateDate);

In the InitializeComponent() method, I have the following event handlers for the DateTimePicker control:

  • dtpDatePicker_Leave
  • dtpDatePicker_ValueChanged
this.dtpDatePicker.Leave += 
    new System.EventHandler(this.dtpDatePicker_Leave);
this.dtpDatePicker.ValueChanged += 
    new System.EventHandler(this.dtpDatePicker_ValueChanged);

Each of these event handlers will be explained later in this article.

Controls

The DateTimePicker control has a custom format: dd-MMM-yyyy. The user may enter a date in any of the following formats in the TextBox controls:

  • mm/dd/yyyy
  • mm/dd/yy
  • mm\dd\yyyy
  • mm\dd\yy
  • mm-dd-yyyy
  • mm-dd-yy

The DateTimePicker control will change the text to dd-MMM-yyyy format.

this.dtpDatePicker.CustomFormat = "dd-MMM-yyyy";
this.dtpDatePicker.Format = 
    System.Windows.Forms.DateTimePickerFormat.Custom

As mentioned earlier, the TextBox controls I'm using for dates have the following events defined:

  • KeyPress
  • DoubleClick
  • Enter
  • Leave

Methods

DateKeyPressed is a simple method to validate data entry in the TextBox controls I use for dates. I allow numbers and the following characters: \, / and -. The KeyPress event is raised each time the user presses a key in the keyboard. If the key pressed doesn't meet the rules, then the character will not be typed in the textbox.

private void DateKeyPressed(Object o, KeyPressEventArgs e)
{
    ///
    ///This event is raised to validate dates.
    ///Acceptable chracters are numbers, forward 
    ///and back slashes, and dashes.
    ///Back slashes may not be common in dates 
    ///but the DateTimePicker
    ///says they are valid. 
    ///
    if( !char.IsNumber(e.KeyChar) && 
                    !(e.KeyChar == Convert.ToChar("-")) 
        && !(e.KeyChar == Convert.ToChar("\\")) 
        && !(e.KeyChar == Convert.ToChar("/"))
        && !char.IsControl(e.KeyChar) )
        e.Handled = true;
}

ValidateDate method is fired when the user leaves the TextBox control. This is a simple way to validate dates in TextBox.Text.

If TextBox.Text is empty, I exit the method. Otherwise, I assign TextBox.Text to the DateTimePicker control. This date assignment is merely to validate the data entry; I really don't need to assign it to the DateTimePicker at this point. If DateTime.Parse is unable to convert the text to a valid date, an Exception is thrown and an appropriate message is displayed.

private void ValidateDate(Object sender, EventArgs e)
{
    ///
    ///This event is raised to validate TextBox controls 
    ///being used for storing a date when the User leaves 
    ///the TextBox control.
    ///
    try
    {
        txtDateBoxSender = (TextBox)sender;
        if (this.txtDateBoxSender.Text.ToString().Trim()=="")
        {return;}
        
        //This date assignment is merely to test 
        //the data entry; I really don't 
        //need to assign it to the DateTimePicker
        this.dtpDatePicker.Value = 
             DateTime.Parse(this.txtDateBoxSender.Text);

        //Format the manually edited date in TextBox.Text
        txtDateBoxSender.Text = 
            string.Format("{0:dd-MMM-yyyy}",
                                this.dtpDatePicker.Value);
        
    }
    catch (Exception ex)
    {
        //You can display the Exception message for 
        //the User, but I decided not to.
        //ex.Message.ToString()

        MessageBox.Show("Please enter a valid date." +
            "\nAllowed formats: " + 
            "mm/dd/yyyy, mm/dd/yy, mm-dd-yyyy, mm-dd-yy." +
            "\nMinimum value: " + 
            this.dtpDatePicker.MinDate.ToShortDateString() +
            "\nMaximum value: " + 
            this.dtpDatePicker.MaxDate.ToShortDateString(),
            "Date Validation", 
            MessageBoxButtons.OK, MessageBoxIcon.Warning);
        
        //You may want to do something with the erroneus value
        //For example, you could undo the change
        //        this.txtDateBoxSender.Undo();
        // or just blank out the TextBox. 
        // (Users may not like that.) 
        //        this.txtDateBoxSender.Text = ""; 
        this.txtDateBoxSender.Undo();

        //Send the User right back 
        //to the control they edited
        this.txtDateBoxSender.Focus();
    }
}

dtpDatePicker_ValueChanged method is fired when the value of the DateTimePicker is changed. We assign the date chosen by the user to the TextBox control that raised the DateBox_TextChanged event.

private void dtpDatePicker_ValueChanged(object sender, System.EventArgs e)
{
    ///
    ///Occurs when value of the DateTimePicker is changed
    ///
    try
    {
        //assign the date chosen by the User to the textbox control
        //that raised the DateBox_TextChanged event
        txtDateBoxSender.Text = string.Format("{0:dd-MMM-yyyy}",
            this.dtpDatePicker.Value);
        this.dtpDatePicker.Visible = false;

        /*     
        if we had to do something different depending 
        on the control the User is editing, then we would 
        have to do something like this:
        
        txtDateBoxSender.Text = string.Format("{0:dd-MMM-yyyy}",
            this.dtpDatePicker.Value);
            
        switch ((string)txtDateBoxSender.Name)
        {
            case "TextBox1":
            { 
                //Do something that is unique 
                //to this TextBox control
                break;
            }
            case "TextBox2":
            { 
                //Do something that is unique 
                //to this TextBox control
                break;
            }
        
            etc...
            Imagine having to write a Case block 
            for more than 50 dates!  
        }
        */
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message.ToString() + 
            "\nAn error occurred in dtp_ValueChanged." +
            "\nControl: " + txtDateBoxSender.Name + 
            ".\nContact Systems staff.\nThank you.",
            "Date Validation", 
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

DateBox_TextChanged method is fired by all the date TextBox controls.

Points of interest

  • In order to place the DateTimePicker control in the appropriate location in our form, we need to find out which TextBox control raised this event. This event handler has two arguments. I will use the object argument to determine the control that raised this event. sender is the control that raised this event. We need to cast sender before assigning it to txtDateBoxSender, because it's an object. In this application, I cast it as TextBox control.
  • Control ctlParent is the control that is the parent (container) of the control that raised this event.
private void DateBox_TextChanged(object sender, System.EventArgs e)
{
    ///
    ///This event is raised by all date TextBoxes.
    ///
    try
    {
        //txtDateBoxSender is the control that raised this event.
        //We need to cast sender, because it's an object.
        //In this app, I know to cast it as TextBox control.
        txtDateBoxSender = (TextBox)sender;
        
        //ctlParent is the control that is the parent (container) of 
        //the control that raised this event
        Control ctlParent = txtDateBoxSender.Parent;

        //We want to place the DateTimePicker control on top of 
        //the TextBox the User double-clicked. 
        //Add the DateTimePicker control to the container (parent)
        //of the control that raised this event. If you don't do this, 
        //the Location of your DateTimePicker control will be relative 
        //to its current parent--in this app, that would be the form--
        //and then your DateTimePicker will be located in the wrong 
        //place.  To see what I mean, just comment out the statement
        //below:
        ctlParent.Controls.Add(this.dtpDatePicker);
        
        //Set DateTimePicker's properties. 
        if (this.txtDateBoxSender.Text != "")
        {
            this.dtpDatePicker.Value = 
                Convert.ToDateTime(this.txtDateBoxSender.Text);
        }

        //Place the DateTimePicker on top of the control 
        //that raised this event and make it visible.
        this.dtpDatePicker.Location = this.txtDateBoxSender.Location; 
        this.dtpDatePicker.BringToFront();
        this.dtpDatePicker.Visible = true;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message.ToString() + 
            "\nAn error occurred in DateBox_TextChanged." +
            "\nControl: " + txtDateBoxSender.Name + ".",
            "Date Validation", 
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

dtpDatePicker_Leave method is fired when the DateTimePicker loses focus. This is where I make the DateTimePicker invisible when the User leaves the control. This handler is called when dtpDatePicker.Leave and dtpDatePicker.MouseLeave events are raised.

private void dtpDatePicker_Leave(object sender, System.EventArgs e)
{
    ///
    ///Occurs when DateTimePicker loses focus
    ///
    this.dtpDatePicker.Visible = false;
}

The TextBoxEnter method reformats a TextBox date from dd-MMM-yyyy to mm-dd-yyyy. The reason I use dd-MMM-yyyy for displaying dates in textboxes is just a personal preference. Use any format that you like.

private void TextBoxEnter(object sender, System.EventArgs e)
{
    ///
    ///This event is fired to reformat a date from dd-MMM-yyyy
    ///to mm-dd-yyyy, because we do not allow letters in our date
    ///textboxes.
    ///
    ///July 12, 2005
    ///
    txtDateBoxSender = (TextBox)sender;
    if (this.txtDateBoxSender.Text != "")
    {
        txtDateBoxSender.Text = 
            DateTime.Parse(txtDateBoxSender.Text).ToString("d", null);
    }
}

Conclusion

I hope you will find these code snippets useful. I have been programming in C# for 3 months, so I'm sure there is room for improvement. I welcome any feedback.

History

  • July 9th, 2005 - Version 1.0.0
  • July 11th, 2005 - version 1.0.1
    • commented out MouseLeave event for DateTimePicker control.
    • removed redundant authorship comments.
    • added code to update the date format of a manually edited TextBox.
    • removed console (never meant to open a console).
  • July 12th, 2005 - version 1.0.2:
    • added TextBoxEnter method for date TextBox controls' Enter event.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

AnnieRivera
Web Developer
United States United States
No Biography provided

Comments and Discussions

 
QuestionFabulous PinmemberCrimsonK830-Apr-12 0:15 
GeneralMy vote of 4 PinmemberMika Wendelius22-Dec-11 9:06 
GeneralObject oriented version Pinmemberjacknpoe24-Jan-07 23:53 
GeneralGreat Control Code - Using one DateTimePicker PinmemberHanksComputer1-Nov-06 17:22 
GeneralGreat!!! Pinmembermsalmank20-Feb-06 21:53 
GeneralRe: Great!!! Pinmembermsalmank20-Feb-06 22:22 
QuestionConsole Application? Pinmemberfwsouthern10-Jul-05 18:07 
AnswerRe: Console Application? PinmemberAnnieRivera11-Jul-05 4:45 
GeneralRe: Console Application? Pinmemberfwsouthern11-Jul-05 5:17 
GeneralRe: Console Application? PinmemberAnnieRivera11-Jul-05 8:53 
GeneralRe: Console Application? Pinmemberfwsouthern11-Jul-05 11:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141030.1 | Last Updated 10 Jul 2005
Article Copyright 2005 by AnnieRivera
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid