I need your help for a particular point in using the RadScheduler.
The appointement displayed in my Scheduler should start and end at some specific time values. The start time should be(08:00;10:00;13:00;15:00) and the end time should be (10:00;12:00;15:00;17:00).
When an user modify one appointement (in all way), I want to check if the start and end times are correct. If not the value should be round to the nearest legal value (cancelling the operation with a message box is also an acceptable solution).
Exemple: If the user set the start time to 9:00 the value is corrected to 08:00.
I have tried to use the Appointements.CollectionChanged event of the Scheduler to change this. But if I correct the value at this time, the scheduler does not update correctly. (The text inside the appointement is changed but not the graphique square. You can see it in the attachement). How could I fix it?
As adding validation rules in a changed event is never a good idea. If you know a way to prevent the user draging or realesing the mouse at an illegal time. It will be perfect !
5 Answers, 1 is accepted
Thank you for writing.
To achieve the desired functionality you can use a combination of the following events.
- First instead of using Appointements.CollectionChanged event you can use Appointements.CollectionChanging event, this way the scheduler will be updated correctly.
- Second for the resizing you can use the appointment MouseUp event to set the appointment valid start and end times:
void
radScheduler1_AppointmentMouseUp(
object
sender, SchedulerAppointmentMouseEventArgs e)
{
Appointment appointment = e.Appointment
as
Appointment;
if
(appointment !=
null
)
{
if
(e.Appointment.Start.Hour != 8)
{
DateTime temp = appointment.StartDateTime;
appointment.Start =
new
DateTime(temp.Year, temp.Month, temp.Day, 8, temp.Minute, temp.Second);
}
}
}
- Third you can use the AppointmentDropping event to prevent the user to drop the appointment in particular time frame:
void
radScheduler1_AppointmentDropping(
object
sender, Telerik.WinControls.UI.AppointmentMovingEventArgs e)
{
if
(e.NewDate.Hour != 8)
{
RadMessageBox.Show(
"cannot drop here"
);
e.Cancel =
true
;
}
}
I hope this will be useful. Should you have further questions, I would be glad to help.
Regards,
Dimitar
Telerik
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
Hi Dimitar,
Thank you for writing your answer. I have tried your different solution and here are my conculsion:
First - Appointments.CollectionChanging
I don't know why, but in my project this event is never raised ! Does it work on your side ?
Second - Scheduler.AppointmentMouseUp Event
It looks like the AppointementMouseUp Event is raised after then Appointments.CollectionChanged event. As I try to save the change to my database in this event, there is a short time where the data could be incorrect (in fact my database raise an exception if the value is not legal). I have a exception on the Appointments.CollectionChanged, then values are checked in the AppointementMouseUp event, finally the change are saved.
Don't know if I should use a boolean flag set on mousedown to prevent this exception. As the visual object of an appointement is stuck to ruler value. It Could be a solution to change this behavior. (I don't think that's a simple task :-))
Third - Scheduler.AppointementDropping Event
It's a good solution. Many thank ! I add a event Handler on the AppointementDropped Event to round the End of the dropped Appointement to the nearest legal value. I notice that the Appointments.CollectionChanged event do not raise when I do a drop operation. As I set the end value with my rounding operation, this event is finally raised. Don't know if it is the desired behavior.
Thank you for writing back.
The CollectionChanging event is fired only when a appointment is added or removed from the AppointmentsCollection. In my opinion it would be best to use the CollectionChanged event for handling edit, add and resize of appointments. Follows modified version of my previous code to reflect your remarks. What it does is to correct the appointment start and end times when adding and to correct the appointment start time when resizing:
bool
isResizing =
false
;
void
radScheduler1_AppointmentResized(
object
sender, AppointmentResizedEventArgs e)
{
isResizing =
true
;
}
void
Appointments_CollectionChanged(
object
sender, Telerik.WinControls.Data.NotifyCollectionChangedEventArgs e)
{
Appointment appointment = e.NewItems[0]
as
Appointment;
if
(appointment !=
null
)
{
if
(e.Action != NotifyCollectionChangedAction.Batch)
{
// all actions that differ from bach have a new item colection
if
(isResizing ==
false
&& appointment.StartDateTime.Hour != 8 && appointment.End.Hour != 12)
{
DateTime temp = appointment.StartDateTime;
appointment.Start =
new
DateTime(temp.Year, temp.Month, temp.Day, 8, temp.Minute, temp.Second);
temp = appointment.End;
appointment.End =
new
DateTime(temp.Year, temp.Month, temp.Day, 12, temp.Minute, temp.Second);
}
else
{
if
(appointment.Start.Hour != 8)
{
DateTime temp = appointment.StartDateTime;
appointment.Start =
new
DateTime(temp.Year, temp.Month, temp.Day, 8, temp.Minute, temp.Second);
}
isResizing =
false
;
}
}
else
{
// when we have a bach operation we must validate all apontments
foreach
(Appointment app
in
radScheduler1.Appointments)
{
if
(app.Start.Hour != 8)
{
DateTime temp = appointment.StartDateTime;
app.Start =
new
DateTime(temp.Year, temp.Month, temp.Day, 8, temp.Minute, temp.Second);
}
}
}
}
radScheduler1.SchedulerElement.Refresh();
}
Also when you do drop operations the CollectionChanged event is fired with a batch action. Batch action is returned when several actions have been made at once for example when performing action in a BeginUpdate/EndUpdate block which the drag and drop operation uses. When the event is fired with batch action you must validate all appointments.
I hope this information helps. Should you have any other questions, I will be glad to assist you.
Regards,
Dimitar
Telerik
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
Thanks for your explanation.
Now I understand better how the AppointementChanged work with the batch "option".
I have modified my Appointment.CollectionChanged Sub to handle the batch. It is not perfect because I have some trouble with Entity Framework (some inner batch event are launched in a add event and it's getting in concurrency exception).
I fix it in hurry with an huggly try catch. It's working fine in a point of view of functionnal test ! (Just pray that's my user won't have to much imagination).
I think that's I could make something cleaner if I move my context.SaveChange to another place. (form closing, a timer sub started on appointementchanged, a save button)
The subject of this thread is fully answered for me.
Thank you very much
Thank you for writing back.
I am glad that my explanations were useful for you and you managed to find solution for your case.
Indeed moving the saving logic to a save button for example will be a much better solution than the try catch block. By my opinion a save button or when closing the form is way better place for that logic.
Please let me know if there is something else I can help you with.
Regards,
Dimitar
Telerik
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>