Overview

Namespace: TheTechIdea.Beep.Winform.Controls.Calendar
Assembly: TheTechIdea.Beep.Winform.Controls.dll
Inheritance: BaseControl

BeepCalendar is the most decomposed control in the Beep library, split across 90+ partial files organized into 8 subsystems. It provides a complete calendar experience with 7 view modes (Month, Week, WorkWeek, Day, Timeline, Agenda, List), full event lifecycle management (add, update, delete, undo/redo), conflict detection, mouse/touch interaction with drag-to-create and drag-to-move, and a theme-aware painting pipeline. An optional sidebar mini-calendar provides quick date navigation.

The control uses a centralized Paint() dispatcher that routes to view-mode-specific renderers, a style-based painter system, and a legacy renderer fallback. During design time in Visual Studio, it renders a simplified preview.

Key Features

  • 7 View Modes — Month (7-column grid, up to 5 events per cell with overflow), Week/WorkWeek (7-day grid with hourly time slots), Day (single day with 24 hourly slots), Timeline (horizontal time spans), Agenda/List (chronological event list). Configurable density: Compact, Standard, Comfortable.
  • Event CRUD — Add, update, delete events with a three-phase mutation pipeline (EventMutating → execution → EventMutated + history recording). Cancelable pre-mutation.
  • Undo/Redo — Two-stack history system (_undoStack + _redoStack). Each mutation records full before/after state. Convenience API: CanUndo, CanRedo, Undo(), Redo().
  • Conflict Detection — Three policy modes: None, Warn, Strict. Checks scheduling overlap before commit. Events fire ConflictDetected with conflicting event details.
  • Drag-to-Create — Click-drag on date cells or empty surfaces to create new events. Visual ghost preview during drag. Ctrl+drag copies existing events.
  • Time Snapping — Configurable snap interval (default 15 min). Events snap to nearest N-minute boundary during drag operations.
  • CalendarEventEditor — QuickEdit (560x420) and DialogEdit (720x620) modes. Fields: Title, Start/End DateTimePickers, AllDay CheckBox, Location, Status, Organizer, Description.
  • Categories & Resources — Color-coded categories with hierarchy. Room/equipment resource scheduling.
  • Sidebar — Compact mini-calendar with month navigation, dot indicators for days with events, today highlight.
  • Theme-Aware — 9-file LayoutTheme subsystem maps IBeepTheme tokens to calendar colors (cells, headers, today, selected, events, weekends).

View Modes

ModeEnum ValueLayoutBest For
MonthCalendarViewMode.Month7-column grid (Sun-Sat), 5-6 rows. Up to maxEventsPerCell event blocks per day. "+N more" overflow indicator.Monthly overview, event browsing
WeekCalendarViewMode.Week7-day columns with hourly time slots on left. Event bars span their time range. Current time line (red).Weekly planning, time-based scheduling
WorkWeekCalendarViewMode.WorkWeekSame as Week but 5 columns (Mon-Fri only).Business-week scheduling
DayCalendarViewMode.DaySingle day with 24 one-hour slots (~60px each). All-day events in header band. Event blocks show title, time, location.Daily agenda, time management
TimelineCalendarViewMode.TimelineHorizontal time axis with event spans. Configurable time scale. Supports resource grouping on Y axis.Project timelines, resource scheduling
AgendaCalendarViewMode.AgendaChronological event list with date headers. Each row: time, title, location, category badge.Event list for date ranges
ListCalendarViewMode.ListSimple scrollable event list. Multi-day events span multiple entries with "continues" indicator.Quick event browse

Properties

PropertyTypeDefaultDescription
ViewModeCalendarViewModeMonthActive view mode: Month, Week, WorkWeek, Day, Timeline, Agenda, List
CurrentDateDateTimeDateTime.TodayThe date currently displayed/navigated to
SelectedDateDateTime?nullCurrently selected date (click or navigate)
EventsObservableCollection<CalendarEvent>EmptyCollection of calendar events. Supports mutation pipeline.
CategoriesList<EventCategory>EmptyEvent categories with Name, Color, Icon, optional parent
ResourcesList<CalendarResource>EmptyResources for room/equipment scheduling
DensityModeCalendarDensityModeStandardCompact (small fonts, tight spacing), Standard, Comfortable (large fonts, spacing)
ShowSidebarboolfalseShow compact mini-calendar in sidebar panel
ShowWeekNumbersboolfalseShow ISO week numbers in Month/Week views
ShowTodayButtonbooltrueShow "Today" navigation button
InteractionSnapIntervalMinutesint15Snap interval for event time adjustment during drag
ConflictPolicyModeCalendarConflictPolicyModeNoneNone (no checking), Warn (fire event, don't block), Strict (fire event, block overlaps)
CanUndo / CanRedobool (read-only)-Whether undo/redo operations are available
EventEditorICalendarEventEditorCalendarEventEditorEditor instance for editing event details
MaxEventsPerCellint5Max visible event blocks in month cell before "+N more"
FirstDayOfWeekDayOfWeekSundayFirst day of the week column
MinimumDate / MaximumDateDateTime?nullDate range constraints for navigation and event creation

Events

EventTypeDescription
DateSelectedEventHandler<EventArgs>A date was clicked/navigated to
EventSelectedEventHandler<CalendarEvent>An event was clicked/selected
CreateEventRequestedEventHandler<CreateEventRequestEventArgs>Drag-to-create completed. Set e.CreatedEvent to provide the new event.
EventMutatingEventHandler<CalendarEventMutationEventArgs>Pre-mutation. Cancelable via e.Cancel=true.
EventMutatedEventHandler<CalendarEventMutationEventArgs>Post-mutation. Event has been added/updated/deleted.
ConflictDetectedEventHandler<CalendarConflictEventArgs>Scheduling conflict detected. e.ConflictingEvents lists conflicts.
InteractionStartedEventHandler<CalendarInteractionEventArgs>Mouse drag interaction started (move, resize, create)
InteractionUpdatedEventHandler<CalendarInteractionEventArgs>Mouse drag position updated
InteractionCompletedEventHandler<CalendarInteractionEventArgs>Mouse drag interaction completed
InteractionCancelledEventHandler<CalendarInteractionEventArgs>Mouse drag interaction cancelled (Escape key)

Methods

MethodReturnDescription
NavigateToDate(DateTime)voidNavigate to a specific date
Today()voidNavigate to today's date
Next() / Previous()voidNavigate to next/previous period based on ViewMode
Undo() / Redo()boolUndo or redo the last event mutation
GetEventsForDate(DateTime)IEnumerable<CalendarEvent>Get all events for a specific date
GetEventsForRange(DateTime, DateTime)IEnumerable<CalendarEvent>Get events within a date range
FindById(string)CalendarEvent?Find event by unique ID
ResetViewButtonStates()voidRefresh undo/redo button enabled states

Interaction System

16 partial files handle all pointer/touch/mouse events with view-mode-specific hit testing:

  • Drag Modes — ResolveDragMode() returns CalendarInteractionMode: MoveEvent (event block in Day/Week/WorkWeek/Timeline), ResizeStart/End (event block edges), SelectEvent (Month/Agenda/List), RangeSelect (Day/Week date cells), CreateEvent (empty surface).
  • Hit Testing — 8 files: HitTesting.cs dispatches to view-specific resolvers (MonthView, WeekView, DayView, TimelineView, TimedView, Agenda). Returns CalendarInteractionHitTestResult with TargetKind (EventBlock/DateCell/EmptySurface), RequestedMode, Location, and Date.
  • Timing Snap — InteractionSnapIntervalMinutes (default 15). Events snap to nearest interval. Timing.cs, Snap.cs, Snap.Location.cs handle the snapping logic.
  • Ctrl+Drag Copy — IsCopyModifierDown() checks for Ctrl. When active, dragging an existing event creates a copy at the drop location.
  • Commitment — Commit.cs dispatches to NewEvent.cs (create from proposal), Copy.cs (Ctrl+drag copy), or ExistingEvent.cs (mutation). All route through EventMutating → CRUD → EventMutated → History.

Event Management

Event Model

CalendarEvent: Id, Title, Start, End, IsAllDay, Location, Description, Status, Category (references EventCategory), Organizer, CreatedDate, ModifiedDate.

Mutation Pipeline

  1. Pre-mutation — RaiseMutating fires EventMutating. Cancelable.
  2. Execution — Data change occurs (add/update/delete).
  3. Post-mutation — RaiseMutated fires EventMutated. History record created. View button states updated.

CalendarEventEditor

Implements ICalendarEventEditor. Two modes: QuickEdit (560x420 compact) and DialogEdit (720x620 full form). TryEdit(request, out editedEvent) opens a BeepDialogForm with CalendarEventEditorContent (UserControl) containing Title, Start/End DateTimePickers, AllDay CheckBox, Location, Status ComboBox, and optional Advanced panel (Organizer, Description).

Conflict Detection

CalendarConflictPolicyMode: None (disabled), Warn (fire ConflictDetected but allow), Strict (fire and block). Conflict resolution checks scheduling overlap. GetConflicts(event) returns conflicting events.

Theming

The LayoutTheme subsystem (9 files) handles theme token resolution:

FileRole
LayoutTheme.csMain coordinator, initializes all theme-related visuals
LayoutTheme.ApplyTheme.csMaps IBeepTheme tokens to calendar colors, fonts, borders, padding
LayoutTheme.Layout.csCell positions, margins, grid spacing calculations
LayoutTheme.MonthCells.csMonth view cell colors: today, selected, hovered, weekend, other-month, events
LayoutTheme.HeaderText.csHeader text formatting, day-of-week labels, month/year title
LayoutTheme.ResponsiveLabels.csText truncation for narrow cells
LayoutTheme.Controls.csNavigation buttons, view selector, density toggle visual properties
LayoutTheme.Controls.Categories.csEvent category color mapping from theme

Architecture

Partial File Organization (90+ files)

SubsystemFilesKey Contents
Core6Constructor, public API, lifecycle, style, appearance
Commands5Public commands, execution core, helpers, duplicate detection
Event Operations13CRUD (Add/Remove/Upsert), History (Undo/Redo), Navigation, Queries, Editor
Interactions16Pointer events, timing snap, proposals, hit testing (7 views), commitment
Painting11Pipeline, Month/Week/Day/List/Timeline views, design-time, sidebar, header formatting
LayoutTheme9Theme application, cell colors, header text, responsive labels, categories
Visual Updates3Flush (full redraw), Scope (partial invalidation), Strategy (dirty-rect)
Types & Fields5Enums, EventArgs, command types, event model

Paint Dispatcher

private void Paint(Graphics g, Rectangle bounds)
{
    if (IsDesignModeSafe)
        DrawDesignTimePreview(g, bounds);       // VS designer
    else if (_usePainterSystem && _stylePainter != null)
        DrawWithPainter(g, contentRect);        // New system
    else
        DrawWithLegacyRenderer(g, contentRect);  // Fallback
}

Code Examples

Basic Calendar Setup

var cal = new BeepCalendar();
cal.ViewMode = CalendarViewMode.Month;
cal.CurrentDate = DateTime.Today;
cal.DensityMode = CalendarDensityMode.Standard;
cal.ShowSidebar = true;
cal.ShowWeekNumbers = true;

// Add sample events
cal.Events.Add(new CalendarEvent
{
    Title = "Team Standup",
    Start = DateTime.Today.AddHours(9),
    End = DateTime.Today.AddHours(9.5),
    Category = categories["Meeting"]
});

cal.Events.Add(new CalendarEvent
{
    Title = "Lunch with Client",
    Start = DateTime.Today.AddHours(12),
    End = DateTime.Today.AddHours(13),
    Location = "Bistro 45"
});

Event Management with Validation

cal.EventMutating += (s, e) =>
{
    if (e.Kind == CalendarEventMutationKind.Delete
        && e.Original.Category == "Locked")
        e.Cancel = true;
};

cal.EventMutated += (s, e) =>
    Console.WriteLine($"{e.Kind}: {e.Result.Title}");

// Conflict detection
cal.ConflictPolicyMode = CalendarConflictPolicyMode.Strict;
cal.ConflictDetected += (s, e) =>
    MessageBox.Show($"Cannot schedule: {e.Description}");

Interaction Events

cal.InteractionStarted += (s, e) =>
    Console.WriteLine($"Started: {e.Mode}");

cal.CreateEventRequested += (s, e) =>
{
    e.CreatedEvent = new CalendarEvent
    {
        Title = "New Event",
        Start = e.RequestedStart,
        End = e.RequestedStart.AddHours(1)
    };
};

cal.InteractionSnapIntervalMinutes = 30;  // Snap to :00/:30

Meeting Scheduler Example

public class MeetingScheduler
{
    private BeepCalendar cal;
    private List<DateTime> bookedSlots = new();

    private void Calendar_InteractionCompleted(object s, CalendarInteractionEventArgs e)
    {
        var selectedTime = e.Date;
        if (IsTimeSlotAvailable(selectedTime))
            ScheduleMeeting(selectedTime);
        else
            MessageBox.Show("This slot is already booked");
    }

    private bool IsTimeSlotAvailable(DateTime dt)
        => !bookedSlots.Any(s => Math.Abs((s - dt).TotalMinutes) < 60);

    private void ScheduleMeeting(DateTime dt)
    {
        bookedSlots.Add(dt);
        cal.Events.Add(new CalendarEvent
        {
            Title = "New Meeting",
            Start = dt,
            End = dt.AddHours(1)
        });
    }
}