I am using UltraWinSchedule (2008.1), and specifically the UltraCalendarInfo component, and I am using the standard AppoinmentDialog and the standard AppointmentRecurrenceDialog to work with appointments.
I am binding the AllPropertiesMember of the UltraCalendarInfo to a datasource that is a generic list of a custom class that has a property type of byte(), which in turn gets persisted to a SQL Server table into a column of varbinary(max).
Nulls are allowed in the SQL Server column, because appointments may be entered into the table outside of the standard AppointmentDialog (such as a user simply entering a startdate, enddate, and subject in an UltraWinGrid).
I am having two problems with this methodology:
The first problem is that when I read the null SQL column into the class, I get an error that ‘Object of type System.DBNull cannot be converted to System.Byte()’. To get around this, in the SQL datareader method, I set the value to an empty Byte () using System.Text.Encoding.UTF8.GetBytes(String.Empty), when the value read from the database is system.dbnull. I also tried defaulting the SQL column to ‘0x’ so that it would never be Null.
Either workaround prevents the error however, now the appointment will not show on the calendar. So in other words, I can’t seem to figure out how to read in a ‘Null’ AllProperties column, and have the calendar still use the other bound properties (StartDate, EndDate, and Subject) to place the appointment properly on the calendar.
A related error occurs when I try to add an appointment to an Ultrawingrid bound to the same datasource. When the record is added via the grid, the AllProperties Property will initially be ‘nothing’, and I get an error originating from: UltraWinSchedule.Appoinment.FromBytes, that indicates <Buffer cannot be null. Parameter name: buffer>. I can work around this error by setting the private member of the AllProperties Property as in:
Private _allProperties() As Byte = System.Text.Encoding.UTF8.GetBytes(String.Empty)
but this causes the same issue in that the appointment will not show up on the calendar.
Assuming I add a regular (non-recurring) appointment through the calendar, everything works fine because the AllProperties member will be set with a value that is not null when the AppointmentDialog is closed, and will be read back and forth into the database properly.
The second problem I have is that in this custom class I also have a Property RecurrenceID of type (System.Guid). When I try to add a recurrence (hit save and close on the appointment dialog, after creating the recurrence), I get an error message originating from Infragistics.Win.UltraWinSchedule.Appointment.BoundPropertySet that indicates ‘Object of System.DBNull connot be converted to type System.guid’.
In the Infragistics WinSchedule sample entitled ‘DataBinding VB.sln’, there is a similar situation with a UltraCalendarInfo and an UltraWinGrid bound to the same datasource (however in this example it is bound to a datatable not a generic list). In this sample, it appears that you can add an appointment via the grid or the calendar and no errors are generated.
As a work round for the first problem, I can probably force users to always enter appointments through the calendar, (the currently existing appointments in the table will have to be deleted and re-added via the Appointment dialog) and that will ensure the AllProperties column cannot be null. However, that does not solve my second problem with the recurrenceID error.
I appreciate if any one might have any comments on this or if anyone has a similar situation., or if you need further clarification of my problem please let me know.
Thanks!
The WinSchedule data binding layer was desgined to work best when the contents of the Appointments collection is manipulated through the object model, i.e., using the Add/Remove/Clear methods.
The Appointment class exposes a Save method which returns a byte array that represents the object graph of that instance. When you allow creation of new appointments through the UltraGrid (with the user providing only the Subject, StartDateTime and EndDateTime, you can call the Save method on that resulting Appointment to return a byte array that is compatible with the AllPropertiesMember. I'm not sure what you would use as a trigger, but if you can populate that field with such a byte array before the Appointment record is created (or, at least, before the ListChanged notification hits the WinSchedule data binding layer), that will most likely satisfy the non-null constraint.
Thank you very much for the reply Brian!
That is an interesting suggestion thank you!
Just before the error occurs, the Get is read on my AllProperties Property which returns the private _allProperties member. On an initial add, this private member will be nothing, so I may be able to intercept that, and create a compatible AllProperites member, by creating a new appointment, setting the Start date, End date, and Subect, and calling the Appoinmment.Save method and assigning that to the private _alProperites member at that time, such as:
Public Property AllProperties() As Byte()
Get
If _allProperties Is Nothing Then
Dim newappt As New Appointment(StartDate, EndDate)
newappt.Subject = Subject
newappt.AllDayEvent = AllDayEvent
_allProperties = newappt.Save
End If
Return _allProperties
End Get
Set(ByVal value As Byte())
SetMember(_allProperties, value, "AllProperties")
End Set
End Property
Private _allProperties() As Byte
If I can't make that work, and I decide to go the route of only allowing appointment editing via the calendar (i.e. manipulating the appointments via the object model as you suggest), I still am having a problem binding the RecurrenceID to a property of type System.Guid (described as my second problem in the above post).
Do you possibly have any advice on possibly conquering that issue? That error occurs when exclusively using the calendar dialogs, and occurs when I press Save and Close on the stock appointment dialog after adding a recurrence.
Thanks again!
Assuming the problem is that the Guid data type cannot handle null values, make the property of type Nullable<Guid>.
I believe the appointment object returns System.DBNull.Value when the recurrence ID is not used. The Nullable(of Guid) type can handle "Nothing", but it cannot handle System.DBNull.Value such as:
Private m_recurrenceID As Nullable(Of Guid) = System.DBNull.Value 'causes compile error
I am not too familar with datatables, but I believe the datacolumns are more tolerant to DBNull.Value which is why the infragistics databinding sample works so well.
I was able to work around this problem by changing my Property to type of "Object " (not ideal but ok for this purpose) which handles System.DBNull.Value.
Thank you for all of you help on this issue!