internal void ScrollAppointmentIntoView(IAppointment appointment) { RadCalendar calendar = this.Owner; if (calendar != null) { CalendarMultiDayViewModel model = calendar.Model.multiDayViewModel; var appointmentInfos = model.appointmentInfos; if (appointmentInfos != null && appointmentInfos.Count > 0) { DateTime startDate = calendar.DisplayDate; DateTime endDate = calendar.DisplayDate.AddDays(calendar.MultiDayViewSettings.VisibleDays - 1); CalendarAppointmentInfo appointmentInfo = appointmentInfos.FirstOrDefault(a => a.childAppointment == appointment && startDate <= a.Date && endDate >= a.Date); if (appointmentInfo != null) { RadRect layoutSlot = appointmentInfo.layoutSlot; if (this.scrollViewer.VerticalOffset != layoutSlot.Y) { this.isScrollingInvoked = true; this.scrollViewer.ChangeView(0.0f, layoutSlot.Y, 1.0f); } } } } }
private void SetColumnsOfIntersectedAppointments(IEnumerable <CalendarAppointmentInfo> intersectedAppointments, CalendarAppointmentInfo parentAppointmentInfo, int columnIndex) { for (int i = 0; i < intersectedAppointments.Count(); i++) { CalendarAppointmentInfo app = intersectedAppointments.ElementAt(i); if (app == parentAppointmentInfo) { int index = columnIndex; while (intersectedAppointments.Any(a => a.arrangeColumnIndex == index)) { index++; } app.arrangeColumnIndex = index; continue; } if (app.arrangeColumnIndex == null) { IEnumerable <CalendarAppointmentInfo> childIntersectedAppointments = intersectedAppointments .Where(a => a.layoutSlot.IntersectsWith(app.layoutSlot) && a.columnIndex == app.columnIndex); this.SetColumnsOfIntersectedAppointments(childIntersectedAppointments, app, columnIndex + 1); } } }
/// <summary> /// Evaluates the appearance settings to be applied on the respective calendar appointment control. /// </summary> /// <param name="context">The CalendarAppointmentInfo context.</param> /// <param name="cell">The CalendarCellModel cell.</param> public DataTemplate SelectTemplate(CalendarAppointmentInfo context, CalendarCellModel cell) { if (cell == null) { return(null); } return(this.SelectTemplateCore(context, cell)); }
internal void UpdateUI(IEnumerable <CalendarCellModel> cellsToUpdate = null) { if (this.Owner.AppointmentSource == null) { return; } if (cellsToUpdate == null) { cellsToUpdate = this.Owner.Model.CalendarCells; } int index = 0; RadCalendar calendar = this.Owner; foreach (CalendarCellModel cell in cellsToUpdate) { CalendarAppointmentInfo info = new CalendarAppointmentInfo(); info.Date = cell.Date; info.Appointments = this.Owner.AppointmentSource.GetAppointments((IAppointment appointment) => { return(cell.Date.Date >= appointment.StartDate.Date && cell.Date.Date <= appointment.EndDate.Date); }); if (info.Appointments.Count > 0) { foreach (var appointment in info.Appointments) { info.Subject += (info.Subject != null ? Environment.NewLine : string.Empty) + appointment.Subject; } var element = this.GetDefaultVisual(index); element.Clip = new RectangleGeometry() { Rect = new Rect(0, 0, cell.LayoutSlot.Width, cell.LayoutSlot.Height) }; element.appointmentInfo = info; calendar.PrepareContainerForAppointment(element, info); RadRect layoutSlot = cell.layoutSlot; layoutSlot = XamlContentLayerHelper.ApplyLayoutSlotAlignment(element, layoutSlot); XamlContentLayer.ArrangeUIElement(element, layoutSlot, false); index++; } } while (index < this.realizedCalendarCellDefaultPresenters.Count) { this.realizedCalendarCellDefaultPresenters[index].Visibility = Visibility.Collapsed; index++; } }
private void ArrangeIntersectedAppointments() { double gridLineThickness = this.Calendar.GridLinesThickness > 0 ? this.Calendar.GridLinesThickness : 1; foreach (var appointmentInfo in this.appointmentInfos) { if (!appointmentInfo.isArranged) { List <CalendarAppointmentInfo> intersectedAppointments = this.appointmentInfos.Where(a => a.layoutSlot.IntersectsWith(appointmentInfo.layoutSlot) && a.columnIndex == appointmentInfo.columnIndex).ToList(); int intersectedAppointmentsCount = intersectedAppointments.Count; if (intersectedAppointmentsCount > 1) { this.SetColumnsOfIntersectedAppointments(intersectedAppointments, appointmentInfo, 0); int columnsCount = intersectedAppointments.Max(a => a.arrangeColumnIndex.Value) + 1; var orderedIntersectedAppointments = intersectedAppointments.OrderBy(a => a.arrangeColumnIndex).ToList(); double maxWidth = appointmentInfo.layoutSlot.Width / columnsCount; for (int i = 0; i < intersectedAppointmentsCount; i++) { CalendarAppointmentInfo intersectedAppointment = orderedIntersectedAppointments[i]; if (!intersectedAppointment.isArranged) { RadRect layout = intersectedAppointment.layoutSlot; layout.X = layout.X + (maxWidth * intersectedAppointment.arrangeColumnIndex.Value); layout.Width = maxWidth; intersectedAppointment.layoutSlot = layout; intersectedAppointment.isArranged = true; } else { RadRect layout = intersectedAppointment.layoutSlot; if (layout.Width > maxWidth) { this.OffsetChildIntersectedAppointments(intersectedAppointment, maxWidth); } } } } } } }
private void OffsetChildIntersectedAppointments(CalendarAppointmentInfo intersectedAppointment, double maxWidth) { var childIntersectedAppointments = this.appointmentInfos.Where(a => a.layoutSlot.IntersectsWith(intersectedAppointment.layoutSlot) && a.columnIndex == intersectedAppointment.columnIndex).ToList(); RadRect layout = intersectedAppointment.layoutSlot; double offset = (layout.Width - maxWidth) * intersectedAppointment.arrangeColumnIndex.Value; layout.X -= offset; layout.Width = maxWidth; intersectedAppointment.layoutSlot = layout; foreach (CalendarAppointmentInfo app in childIntersectedAppointments) { if (app.isArranged && app.layoutSlot.Width > maxWidth) { this.OffsetChildIntersectedAppointments(app, maxWidth); } } }
private AppointmentControl GetDefaultAllDayAppointmentVisual(CalendarAppointmentInfo info) { AppointmentControl visual; if (this.recycledAppointments.Count > 0) { visual = this.recycledAppointments.Dequeue(); } else if (this.fullyRecycledAppointments.Count > 0) { visual = this.fullyRecycledAppointments.Dequeue(); visual.ClearValue(AppointmentControl.VisibilityProperty); } else { visual = this.CreateDefaultAllDayAppointmentVisual(); } this.realizedAppointmentPresenters.Add(info, visual); return(visual); }
private void ArrangeAllDayAppointment(RadRect viewRect) { AppointmentSource appointmentSource = this.Calendar.appointmentSource; if (this.allDayAppointmentInfos == null) { this.allDayAppointmentInfos = new List <CalendarAppointmentInfo>(); } else { this.allDayAppointmentInfos.Clear(); } if (appointmentSource != null) { MultiDayViewSettings settings = this.Calendar.multiDayViewSettings; double appoitmentHeight = settings.AllDayAppointmentMinHeight; foreach (var cell in this.CalendarCells) { LinkedList <IAppointment> appointments = appointmentSource.GetAppointments((IAppointment appointment) => { return(cell.Date.Date >= appointment.StartDate.Date && cell.Date.Date <= appointment.EndDate.Date && appointment.IsAllDay); }); if (appointments.Count > this.allDayAreaRowCount) { this.allDayAreaRowCount = appointments.Count; } var sorterAppointments = appointments.OrderByDescending(a => a.EndDate.Ticks - a.StartDate.Ticks).ToList(); var containedInfos = this.allDayAppointmentInfos.Where(a => sorterAppointments.Contains(a.childAppointment)); double prevBottom = cell.layoutSlot.Y - this.dayViewLayoutSlot.Y; foreach (var appointment in sorterAppointments) { while (true) { int widthCoeff; int xCoeff; DateTime startAppointmentDate = appointment.StartDate; if (this.Calendar.multiDayViewSettings.WeekendsVisible) { widthCoeff = (appointment.EndDate - startAppointmentDate).Days; xCoeff = (cell.Date - startAppointmentDate.Date).Days; } else { widthCoeff = CalendarMathHelper.GetBusinessDaysCount(startAppointmentDate, appointment.EndDate); startAppointmentDate = CalendarMathHelper.SetFirstAvailableBusinessDay(startAppointmentDate, 1); xCoeff = CalendarMathHelper.GetBusinessDaysCount(startAppointmentDate.Date, cell.Date); } RadRect layoutSlot = new RadRect(cell.layoutSlot.X - (xCoeff * this.cellWidth), prevBottom, this.cellWidth + (this.cellWidth * widthCoeff) - this.Calendar.GridLinesThickness / 2, appoitmentHeight); if (containedInfos.FirstOrDefault(a => a.layoutSlot.IntersectsWith(layoutSlot)) == null) { CalendarAppointmentInfo containedInfo = containedInfos.FirstOrDefault(a => a.childAppointment == appointment); if (containedInfo != null) { break; } CalendarAppointmentInfo info = new CalendarAppointmentInfo(); info.Date = cell.Date; info.Appointments = appointments; info.columnIndex = cell.ColumnIndex; info.Brush = appointment.Color; info.cell = cell; info.childAppointment = appointment; info.DetailText = appointment.Description; info.Subject = appointment.Subject; info.IsAllDay = appointment.IsAllDay; info.layoutSlot = layoutSlot; this.allDayAppointmentInfos.Add(info); prevBottom = layoutSlot.Bottom + settings.AllDayAppointmentSpacing; break; } prevBottom = layoutSlot.Bottom + settings.AllDayAppointmentSpacing; } } } int maxVisibleRows = settings.AllDayMaxVisibleRows; this.totalAllDayAreaHeight = this.allDayAreaRowCount > maxVisibleRows ? maxVisibleRows * appoitmentHeight + maxVisibleRows * settings.AllDayAppointmentSpacing + appoitmentHeight / 2 : this.allDayAreaRowCount * appoitmentHeight + this.allDayAreaRowCount * settings.AllDayAppointmentSpacing; if (this.allDayAreaRowCount == 0) { this.totalAllDayAreaHeight = 0; } } }
internal void ArrangeAppointments() { AppointmentSource appointmentSource = this.Calendar.appointmentSource; if (this.appointmentInfos == null) { this.appointmentInfos = new List <CalendarAppointmentInfo>(); } else { this.appointmentInfos.Clear(); } if (appointmentSource != null) { MultiDayViewSettings settings = this.Calendar.multiDayViewSettings; foreach (var calendarCell in this.CalendarCells) { LinkedList <IAppointment> appointmentsPerCell = appointmentSource.GetAppointments((IAppointment appointment) => { return(calendarCell.Date.Date >= appointment.StartDate.Date && calendarCell.Date.Date <= appointment.EndDate.Date && !(appointment.IsAllDay && settings.ShowAllDayArea)); }); var orderedAppointments = new LinkedList <IAppointment>(appointmentsPerCell.OrderBy(a => a.StartDate)); foreach (var appointment in orderedAppointments) { if ((appointment.StartDate.Date == calendarCell.Date.Date && appointment.StartDate.TimeOfDay > settings.DayEndTime) || (appointment.EndDate.Date == calendarCell.Date.Date && appointment.EndDate.TimeOfDay < settings.DayStartTime)) { continue; } double startY = this.DateToVerticalPosition(calendarCell.Date.Date, appointment.StartDate); DateTime endDate = appointment.EndDate.TimeOfDay > settings.DayEndTime ? appointment.EndDate.Add(TimeSpan.FromTicks(settings.DayEndTime.Ticks - appointment.EndDate.TimeOfDay.Ticks)) : appointment.EndDate; double endY = this.DateToVerticalPosition(calendarCell.Date.Date, endDate); if (startY < endY) { CalendarAppointmentInfo info = new CalendarAppointmentInfo(); info.Date = calendarCell.Date; info.Appointments = orderedAppointments; info.columnIndex = calendarCell.ColumnIndex; info.Brush = appointment.Color; info.cell = calendarCell; info.childAppointment = appointment; info.DetailText = appointment.Description; info.Subject = appointment.Subject; info.IsAllDay = appointment.IsAllDay; DateTime currentAppointmentStartDate = appointment.StartDate; DateTime currentAppointmentEndDate = appointment.EndDate; if (!this.Calendar.multiDayViewSettings.WeekendsVisible) { currentAppointmentStartDate = CalendarMathHelper.SetFirstAvailableBusinessDay(currentAppointmentStartDate, 1); currentAppointmentEndDate = CalendarMathHelper.SetFirstAvailableBusinessDay(currentAppointmentEndDate, -1); } info.hasPreviousDay = currentAppointmentStartDate.Date < calendarCell.Date; info.hasNextDay = currentAppointmentEndDate.Date > calendarCell.Date; int xCoeff = (calendarCell.Date - appointment.StartDate.Date).Days; RadRect layoutSlot = new RadRect(calendarCell.layoutSlot.X - this.timeRulerWidth, startY, calendarCell.layoutSlot.Width, endY - startY); info.layoutSlot = layoutSlot; this.appointmentInfos.Add(info); } } } this.ArrangeIntersectedAppointments(); } }
internal void UpdateUI(IEnumerable <CalendarCellModel> cellsToUpdate = null) { if (this.Owner.AppointmentSource == null) { return; } if (cellsToUpdate == null) { cellsToUpdate = this.Owner.Model.CalendarCells; } int index = 0; RadCalendar calendar = this.Owner; foreach (CalendarCellModel cell in cellsToUpdate) { CalendarAppointmentInfo info = new CalendarAppointmentInfo(); info.Date = cell.Date; info.Appointments = this.Owner.AppointmentSource.GetAppointments((IAppointment appointment) => { return(cell.Date.Date >= appointment.StartDate.Date && cell.Date.Date <= appointment.EndDate.Date); }); if (info.Appointments.Count > 0) { AppointmentControl element = new AppointmentControl(); foreach (var appointment in info.Appointments) { info.Subject += (info.Subject != null ? Environment.NewLine : string.Empty) + appointment.Subject; } element = this.GetDefaultVisual(index); element.Clip = new RectangleGeometry() { Rect = new Rect(0, 0, cell.LayoutSlot.Width, cell.LayoutSlot.Height) }; element.Header = info.Subject; element.Background = info.Brush; element.appointmentInfo = info; XamlContentLayerHelper.MeasureVisual(element); if (element != null) { StyleSelector styleSelector = calendar.AppointmentStyleSelector; if (styleSelector != null) { var style = styleSelector.SelectStyle(info, element); if (style != null) { element.Style = style; } } AppointmentTemplateSelector headerTemplateSelector = calendar.AppointmentHeaderTemplateSelector; if (headerTemplateSelector != null) { DataTemplate template = headerTemplateSelector.SelectTemplate(info, info.cell); if (template != null) { element.HeaderTemplate = template; } } RadRect layoutSlot = cell.layoutSlot; layoutSlot = XamlContentLayerHelper.ApplyLayoutSlotAlignment(element, layoutSlot); XamlContentLayer.ArrangeUIElement(element, layoutSlot, false); index++; } } } while (index < this.realizedCalendarCellDefaultPresenters.Count) { this.realizedCalendarCellDefaultPresenters[index].Visibility = Visibility.Collapsed; index++; } }
private void RecycleAppointmentVisual(CalendarAppointmentInfo appointmentInfo, AppointmentControl visual) { this.realizedAppointmentPresenters.Remove(appointmentInfo); this.recycledAppointments.Enqueue(visual); }
/// <summary> /// When implemented by a derived class, provides a way to tap into the default calendar appointment control appearance logic through the passed /// <see cref="CalendarAppointmentInfo" /> argument instance. /// </summary> /// <param name="context">The CalendarAppointmentInfo context.</param> /// <param name="cell">The CalendarCellModel cell.</param> protected abstract DataTemplate SelectTemplateCore(CalendarAppointmentInfo context, CalendarCellModel cell);