Detect dropping appointment on another

10 posts, 0 answers
  1. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 11 Nov 2011 Link to this post

    Hi,

    I use timeline view with resource grouping and snap appointments (see attached image).
    The appointments fill up a whole day.
    The appointments can be dragged between different days for the same resource or even between different resources.

    I need to detect on drop, if I drop the appointment on a slot that alredy contains an appointment or if it is empty.
    How can I do that?

    I have a custom DragDropBehavior that looks like this:
    public class CustomDragDropBehavior : ScheduleViewDragDropBehavior
       {
           public event EventHandler<EventArgs<TimeScheduleShift>> NewShiftDropped;
     
           public override void Drop(DragDropState state)
           {
               if (state.IsControlPressed)
               {
                   // TODO: Copy shift
               }
     
               if (state.SourceAppointmentsSource == state.DestinationAppointmentsSource)
               {
                   if (state.Appointment != null && state.DestinationSlots.Count() > 0)
                   {
                       // Get dragged shift
                       TimeScheduleShift shift = state.Appointment as TimeScheduleShift;
                       if (shift != null)
                       {
                           // Get destionation slot (where shift is dropped)
                           DragDropSlot slot = state.DestinationSlots.First() as DragDropSlot;
                           if (slot != null && slot.Resources.Count() > 0)
                           {
                               // Get destination slot's employee
                               TimeScheduleEmployeeResource employee = slot.Resources.First() as TimeScheduleEmployeeResource;
                               if (employee != null)
                               {
                                   // Check if destination employee is different from source employee
                                   int employeeId = 0;
                                   Int32.TryParse(employee.ResourceName, out employeeId);
                                   if (employeeId != 0 && employeeId != shift.EmployeeId)
                                       shift.EmployeeId = employeeId;
                               }
                           }
                       }
                   }
     
                   base.Drop(state);
               }
               else
               {
                   // Get dropped shift
                   var newShift = state.Appointment as TimeScheduleShift;
                   // Get time slot where shift was dropped
                   Slot droppedAtSlot = state.DestinationSlots.First();
     
                   // Calculate offset between default shift start and actual dropped at start
                   TimeSpan offset = droppedAtSlot.Start - newShift.Start;
                   // Set new times based on dropped time
                   newShift.Start = newShift.Start.Add(offset);
                   if (newShift.BreakStart.HasValue)
                       newShift.BreakStart = newShift.BreakStart.Value.Add(offset);
                   if (newShift.BreakStop.HasValue)
                       newShift.BreakStop = newShift.BreakStop.Value.Add(offset);
                   newShift.End = newShift.End.Add(offset);
                   newShift.ActualStart = newShift.Start;
                   newShift.ActualEnd = newShift.End;
     
                   // Add shift to collection
                   (state.DestinationAppointmentsSource as ObservableCollection<TimeScheduleShift>).Add(newShift);
     
                   if (NewShiftDropped != null)
                       NewShiftDropped(this, new EventArgs<TimeScheduleShift>(newShift));
               }
           }
       }

    In this code I can find out if I dropped the appointment on another resource (Employee) and change it's ID.
    But I also need to find out if the destination slot already contained an appointment before the drop.

    Regards,
    Håkan


  2. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 16 Nov 2011 Link to this post

    Hello Håkan,

    Please find attached a simple example which implements how you can implement ConflictCheckingBehavior in RadScheduleView. Download it and give it a try.

    Hope this helps.

    Greetings,
    Yana
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft banner
  4. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 05 Jan 2012 Link to this post

    Hi Yana!

    I tried your example and it works as it is designed for, but in my case I do not want to prevent drag/drop over existing appointments, but I want to detect it.

    In my CustomDragDropBehavior I have overridden the Drop event and from the DragDropState I can get a hold of both the dropped appointment and the slot I drop it in, but I can't seem to find out if there are any existing appointments in that slot.
    From state.DestinationAppointmentsSource I get all appointments in my view, not only in the slot.

    I guess I can check the Resources and the time span but there must be an easier way?
    Since you have made your example work so easy, it's almost what I want.
    I guess I don't have enought knowledge of LINQ to manage it.

    To make it harder (maybe).
    My slots can contain several appointment on the same resource and time frame.
    And I would (if it is possible) like to detect exactly which appointment I drop on.
    In that case it is not enought to just check the resource and timespan, I guess I have to check the mouse pointer or something?

    Do you have any ideas?

    Regards,
    Håkan
  5. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 06 Jan 2012 Link to this post

    Hi Håkan,

    You can get the appointments in the slot in Drop event like this:

    public override void Drop(DragDropState state)
    {
        var appsInTheSlot = state.DestinationSlots.SelectMany(sl => state.DestinationAppointmentsSource
            .OfType<IAppointment>()
            .Where(a => a.IntersectsWith(sl) && !state.DraggedAppointments.Contains(a)));
     
        base.Drop(state);
    }

    Please try it and let us know whether it helps.

    All the best,
    Yana
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  6. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 09 Jan 2012 Link to this post

    Hi Yana!

    Thanks for the code example, it almost worked.
    My view is grouped on Resource also, so with this code I get all appointments for that slot, regardless of resource.
    I want only the appointment in the slot belonging to the target resource also.

    Is that possible?

    Regards,
    Håkan
  7. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 09 Jan 2012 Link to this post

    Hello Håkan,

    Please modify the method like this:

    public override void Drop(DragDropState state)
    {
        var res = state.DestinationSlots.SelectMany(sl => state.DestinationAppointmentsSource
            .OfType<IAppointment>()
            .Where(a => this.AreOverlapping(a,sl) && !state.DraggedAppointments.Contains(a)));
        base.Drop(state);
    }

    and add the AreOverlapping and AreIntersected methods to the CustomDragDropBehavior class:

    private static bool AreIntersected(IEnumerable<IResource> first, IEnumerable<IResource> other)
    {
        IEnumerable<IResource> firstResources = first
            .Distinct();
     
        IEnumerable<IResource> otherResources = other              
            .Distinct();
     
        return firstResources.Where((IResource r) => otherResources.Contains(r)).Count() == firstResources.Count();
    }
     
    private bool AreOverlapping(IAppointment appointment, Slot slot)
    {
        return appointment.IntersectsWith(slot) && AreIntersected(appointment.Resources.OfType<IResource>(), slot.Resources.OfType<IResource>());          
    }

    Hope it's ok now.

    All the best,
    Yana
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  8. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 10 Jan 2012 Link to this post

    Hi Yana!

    That did the trick, thanks!
    I have one more question though...

    In my TimelineView every slot is one whole day and the appointments fill up the whole day graphically even if its actual time range is less.

    To the problem:
    Lets say one resource have two appointments in the same slot, one can for example be 07:00-11:00 and another 11:00-16:00. Both appoinments fill up the whole slot in width and are placed below each other (see attached image). And that is exactly how we want to display them.

    The problem occurs if I drag another appointment into this slot and drop in on top of one of these existing appointments, I want to detect exactly which appoinment it was dropped on (need to show a dialog with a question if it should replace the existing).
    Is there anyway I can detect which appointment that was under the mouse pointer when I drop it.
    From the Drop event I can get the slot and both appoinments, but not the exact appointment it was dropped on, or...?

    If it doesn't work, I guess I have to check the actual time range on the dragged appointment and compare it to the appointments in the dropped slot, if any one is overlapping I can take it. The problem then is that both may be overlapping or intersecting...

    Regards,
    Håkan

  9. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 12 Jan 2012 Link to this post

    Hello Håkan,

    Currently you cannot find the exact location on which the appointment is dropped.  You can get only the Slot and the appointments in it.

    We are sorry for the inconvenience and hope this is not a show stopper for you.

    All the best,
    Yana
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  10. Sally
    Sally avatar
    6 posts
    Member since:
    Apr 2012

    Posted 25 Jun 2012 Link to this post

    Yana,

    Is there a way to detect if the DragDropState.DestinationSlots are Overlapping with a SpecialSlot (not an Appointment) on the ScheduleView? The DragDropState doesn't seem to contain any SpecialSlot information, it only contains the Appointments on the ScheduleView.   I would like to write code in the CanDrop function based on the SpecialSlot the dragged appointment is currently overlapping.  

    Thanks,
    Sally
  11. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 28 Jun 2012 Link to this post

    Hello Sally,

    This is correct - DragDropState does not contain information about the SpecialSlots and I am afraid that the required approach cannot be easily achieved with RadScheduleView.

    All the best,
    Yana
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Back to Top
DevCraft banner