I am trying to create a new datagridcolumn control. I need a datetimepicker, with up/down spinner, that allows me to set starttime, endtime and interval. I only need to change the time, not the date.
I have a CalendarColumn working, thanks to some links from jmcilhinney, but this shows a dropdown calendar control.
I'm thinking there must be some way of combining what I have already with something like this, but its way past my ability.
Can anybody help / advise on this ?
Thanks
Bob
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
Not you again! Like I said, you need to propagate the desired properties of the editing control through the cell to the column. I'll post my classes as they are at the moment so you can see what I've done. You may even be able to use them "as is". I'm not 100% sure of how far I got with them because I've been concentrating on a MaskedTextBox column recently. Note that the code is in C# so you can either compile them in C# Express, convert them using a code converter or else just use them to get some ideas and write your own code for your own classes.
Last edited by jmcilhinney; Jun 20th, 2006 at 06:55 PM.
There's one more thing to note. I created a customised version of the TextBox column and cell classes to allow me to specify my own error icon. Those classes were included in the same namespace but I think you'll find that if they are not present the standard classes will be used seamlessly. If I remember correctly you would have been completely unaware of the difference but I thought I'd mention it in case I didn't remember correctly.
I'm not sure what you used to convert the C# code but whatever it was it invented that ConversionHelpers class itself because it's nothing to do with me. It seems to have used it wherever the C# "as" keyword was used. For instance, the line you quote above looks like this in your converted code:
Note also that you don't have to include all the functionality that I have. For instance, you may not need the Checked, ShowCheckBox, MaxDate, MinDate, ZeroTime and ErrorIcon properties.
Last edited by jmcilhinney; Jun 21st, 2006 at 06:18 AM.
Trying to compile the C# code directly now, just one error to sort out and its a simple one... what do I need to reference ?
Bob
"Error 1 The type or namespace name 'ToolboxBitmap' could not be found (are you missing a using directive or an assembly reference?) C:\Projects\DataGridViewDTPColumn\DataGridViewDateTimePickerColumn.cs 20 6 DataGridViewDTPColumn"
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
Here's how you find the answer to that yourself. That ToolboxBitmap is an attribute and the actual class for attributes always ends in "Attribute", so the actual class is ToolboxBitmapAttribute. You go to the MSDN library and search for "toolboxbitmapattribute class". You read the class overview topic that is retruned in the results and it tells you that it is the System.Drawing.ToolboxBitmapAttribute class. I've imported that namespace at the top of my column class file.
Ah, that's because I implemented that method in my custom TextBox cell class. I had it in the DateTimePicker cell class originally but when I decided to inherit my own class instead of the standard I commented it out. You can just uncomment it, or you're welcome to my TextBox column classes as well if you like. All it adds at the moment is the ability to specify your own error icon, which is then inherited by my other columns. I intend to add some other properties, like PasswordChar and CharacterCasing, in the not too distant future.
I have the control working in context now, with a spinner rather than calendar dropdown.
Could you please give me some pointers as to how I can now...
- Have a min and max TIME setting, 6am - 8pm, the date portion should be assigned from a variable at runtime _dDiaryDate.
- Make the up/down increment the time in 15min intervals, rather than it only affecting the time portion active. (hours or minutes)
Thanks again,
Bob
Last edited by staticbob; Jun 22nd, 2006 at 06:12 AM.
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
Note that if you want to change the date portion again at any stage you'll have to remove either or both of those limits and then reset them again afterwards or else you'll get an exception thrown. Note also that you'll have to do this individually for each cell if they are to have different dates.
2. That's not how the DateTimePicker works. If you want that behaviour then you're going to have to code it in your editing control class. Be warned though that you may run into some classes and methods that are in the System.Windows.Forms.dll assembly and declared Friend, thus you cannot use them and will have to reproduce their behaviour yourself. I used Reflector a lot while I was coding my columns to see how the Framework classes actually work.
I want to make sure the users can't select a time in ENDTime that is before STARTTime
-------------
Also, how can I make the values in a new row blank, until the user clicks into the control. At the moment, a new row has datetime.now, as set here...
Sorry, can't quite grasp whats going on here with the showCheckBox etc etc
Code:
public override object DefaultNewRowValue
{
get
{
if (this.IsInEditMode || !this._showCheckBox || this._checked)
{
//DateTime.Now :
// The default value for a populated cell is the current date and, optionally, time.
return this.ZeroTime ? DateTime.Now : DateTime.Now;
}
else
{
// An unchecked check box in a cell that is not being edited indicates a null value.
return DBNull.Value;
}
}
}
Bob
Last edited by staticbob; Jun 22nd, 2006 at 10:00 AM.
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
Just like the regular DateTimePicker control, if you do not display the check box in the control then it must always have a value. The check box is what allows you to specify a null value, by unchecking it. A cell must have its ShowCheckBox property set to True and its Checked property set to False in order to have a null value.
As for your first question, I'd be inclined to handle the CellValueChanged event of the grid. You then test the ColumnIndex to see if you're in the StartTime column. If you are then you use the Value of that cell to set the MinDate property of the cell in the same row in the EndTime column. You may similarly use the Value in the EndTime column to set the MaxDate property of the StartTime column. If you don't then setting a StartTime after the current EndTime should automatically adjust the EndTime value too.
You got the row index already because its the same as the current cell. You know the column index of the column that contains the end time. That gives you the cell. Cast it as the appropriate type and set it MinDate property.
Private Sub dgv_Visitors_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgv_Visitors.CellValueChanged
But I am getting an error when changing the first timecolumn (4).
Code:
Error: Value of '23/06/2006 00:00:00' is not valid for 'MaxDate'. 'MaxDate' must be greater than or equal to MinDate.
Parameter name: MaxDate
Err No: 5
Exception: ArgumentOutOfRangeException
Stack Trace:
at System.Windows.Forms.DateTimePicker.set_MaxDate(DateTime value)
at Wunnell.Windows.Forms.DataGridViewDateTimePickerCell.SetMaxDate(Int32 rowIndex, DateTime value) in C:\_VSProjects\DataGridViewDTPColumn\DataGridViewDTPColumn\DataGridViewDateTimePickerCell.cs:line 767
How do I stop the event firing again when I'm setting the value of the 2nd time column ? That seems to be the problem...
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
I'm still having slight issues with this control. This is the only code I have interacting with my datagridview at the moment....
VB Code:
Private Sub dgv_Visitors_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgv_Visitors.CellValueChanged
Try
If e.RowIndex < 0 Then Return
If e.ColumnIndex < 4 Or e.ColumnIndex > 5 Then Return
... just trying to set the min&max dates according to the times selected. This is partially working. I am seeing this error when modifying col(5)...
Code:
Assertion Failed: Abort=Quit, Retry=Debug, Ignore=Continue
---------------------------
at DataGridViewDateTimePickerCell.Constrain(DateTime value) C:\_VSProjects\DataGridViewDTPColumn\DataGridViewDTPColumn\DataGridViewDateTimePickerCell.cs(446)
at DataGridViewDateTimePickerCell.InitializeEditingControl(Int32 rowIndex, Object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) C:\_VSProjects\DataGridViewDTPColumn\DataGridViewDTPColumn\DataGridViewDateTimePickerCell.cs(609)
at DataGridView.InitializeEditingControlValue(DataGridViewCellStyle& dataGridViewCellStyle, DataGridViewCell dataGridViewCell)
at DataGridView.BeginEditInternal(Boolean selectAll)
at DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)
at DataGridView.OnCellMouseDown(HitTestInfo hti, Boolean isShiftDown, Boolean isControlDown)
at DataGridView.OnCellMouseDown(DataGridViewCellMouseEventArgs e)
at DataGridView.OnMouseDown(MouseEventArgs e)
at Control.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
at Control.WndProc(Message& m)
at DataGridView.WndProc(Message& m)
at ControlNativeWindow.OnMessage(Message& m)
at ControlNativeWindow.WndProc(Message& m)
at NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Form.ShowDialog(IWin32Window owner)
at Form.ShowDialog()
at ProjectWorkbook.main() C:\_VSProjects\PWBV3\Modules\ProjectWorkbook.vb(55)
The only change I have made to the control code is....
Code:
if (this.IsInEditMode || !this._showCheckBox || this._checked)
{
//DateTime.Now :
// The default value for a populated cell is the current date and, optionally, time.
return this.ZeroTime ? this.MinDate : this.MinDate; // DateTime.Now : DateTime.Now;
}
else
Can you see any problems with this ?
I have attached the c# control code as it stands now.
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
After drilling down into the values at runtime, I think this could be a problem....
------------
?dgv_Visitors(4, e.RowIndex).Value
#6/26/2006# {Date}
Date: #6/26/2006#
------------
?ctype(dgv_Visitors(e.ColumnIndex, e.RowIndex).Value,DateTime).TimeOfDay
{System.TimeSpan}
Days: 0
Hours: 0
MaxValue: {System.TimeSpan}
Milliseconds: 0
Minutes: 0
MinValue: {System.TimeSpan}
Seconds: 0
Ticks: 0
--------------
- No time ???
Strange that this only occurs on Case 5, Case 4 works fine ?
Bob
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
John, any idea why this is happening ? (See attached .avi)
- A new row appears with the default value, mindate. (6:00am)
- As soon as you begin edit on that new row, the values from the dtp column disappear. (I have the datagridview set to "EditonEnter")
- When I then edit these columns, NOW shows, but if I click out of the cell without making a change it disappears again.
- When moving between the columns if I don't make changes, I get an error, At the time of the error, both Min and Max date have zeor time values, which I just can't understand.
Code:
System.ArgumentOutOfRangeException was unhandled by user code
Message="Value of '27/06/2006 06:00:00' is not valid for 'Value'. 'Value' should be between 'MinDate' and 'MaxDate'.\r\nParameter name: Value"
Source="System.Windows.Forms"
ParamName="Value"
StackTrace:
at System.Windows.Forms.DateTimePicker.set_Value(DateTime value)
at Wunnell.Windows.Forms.DataGridViewDateTimePickerCell.InitializeEditingControl(Int32 rowIndex, Object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) in C:\_VSProjects\DataGridViewDTPColumn\DataGridViewDTPColumn\DataGridViewDateTimePickerCell.cs:line 605
at System.Windows.Forms.DataGridView.InitializeEditingControlValue(DataGridViewCellStyle& dataGridViewCellStyle, DataGridViewCell dataGridViewCell)
This is the only code I have interacting with the dgv...
This On LOAD
VB Code:
'Set-up DTP columns
Dim dtp_starttime As JMCDataGridViewDateTimePickerColumn = dgv_Visitors.Columns(4)
Dim dtp_endtime As JMCDataGridViewDateTimePickerColumn = dgv_Visitors.Columns(5)
'Public Overloads Function Nz(ByVal Field As Object, ByVal ValIfNull As Date) As Date
' If IsDBNull(Field) Then
' Return ValIfNull
' Else
' Return CDate(Field)
' End If
'End Function
Catch ex As Exception
PWBlib.EH.Log(ex)
End Try
End Sub
I just can't see why I'm getting this error, nor can I understand why I "Loose" the default entries on row edit. I have re-created this grid in a stand alone app and the default remains when you edit a new row.
Help, again please !
Bob
Last edited by staticbob; Jun 30th, 2006 at 04:48 AM.
"I dislike 7 am. If 7 am were a person, I would punch 7 am in the biscuits." - Paul Ryan, DailyRamblings
public override object DefaultNewRowValue
{
get
{
if (this.IsInEditMode || !this._showCheckBox || this._checked)
{
//DateTime.Now :
// The default value for a populated cell is the current date and, optionally, time.
return this.ZeroTime ? DateTime.Today : DateTime.Now;
}
else
{
// An unchecked check box in a cell that is not being edited indicates a null value.
return this.MinDate;
}
}
}
Whenever using this control, the first thing my users do is select the date they are completing the report for. The default is the current date, but they could, using a dtp control, select a date in the past to complete the report for. Changing the DTP value sets a public _dDiaryDate on my usercontrol.
It also does this...
VB Code:
Dim dtp_starttime As JMCDataGridViewDateTimePickerColumn = dgv_Visitors.Columns(4)
Dim dtp_endtime As JMCDataGridViewDateTimePickerColumn = dgv_Visitors.Columns(5)
Re:Create New DatagridViewColumn control using vb.net 2005 Express
Has anyone made any further progress on this CalendarColumn control?
I'm been attempting to extend this control a bit further over the last few weeks but have stopped and started so many times I've become lost.
i.e. bound to a database.
null dates after Enable Adding.
Having the calendarcolumn blank before row add.
Cancelling the add.
Setting min and max dates on control initialization.
Committing changes on row index change.
etc.
Any further positive progressive help would be greatly appreciated?
Last edited by BarrySumpter; Oct 22nd, 2006 at 04:34 AM.
would you accept to share the code you are talking about : allowing to manage dateTimePicker in datagridview, with minDate, maxDate , etc... features ?
You need to handle the EditingControlShowing event of your datagridview and test to see if the type of e.Control is CalendarEditingControl. If it is, you cast it to CalendarEditingControl and you can access all of its members including MinDate and MaxDate... Just do a search for "DataGridView EditingControlShowing" in this forum and you should find some sample code (may be not for your specific type, but close enough that you can see how it's done).