Skip to content

Commit 0515fab

Browse files
committed
Add default implementation of calendar days with events to XCalendar.Core
1 parent cad0305 commit 0515fab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+492
-623
lines changed

XCalendar.Core/Interfaces/ICalendar.cs

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
using System;
2-
using System.Collections.ObjectModel;
32
using System.ComponentModel;
43
using XCalendar.Core.Collections;
54
using XCalendar.Core.Enums;
65
using XCalendar.Core.Models;
76

87
namespace XCalendar.Core.Interfaces
98
{
10-
public interface ICalendar<T> : INotifyPropertyChanged where T : ICalendarDay, new()
9+
/// <summary>
10+
/// An interface representing a calendar.
11+
/// </summary>
12+
/// <typeparam name="T">A model implementing <see cref="ICalendarDay{TEvent}"/> to be used to represent each day in a page.</typeparam>
13+
public interface ICalendar<T> : ICalendar<T, IEvent> where T : ICalendarDay<IEvent>, new()
14+
{
15+
}
16+
/// <summary>
17+
/// An interface representing a calendar.
18+
/// </summary>
19+
/// <typeparam name="T">A model implementing <see cref="ICalendarDay{TEvent}"/> to be used to represent each day in a page.</typeparam>
20+
/// <typeparam name="TEvent">A model implementing <see cref="IEvent"/> to be used to represent calendar events.</typeparam>
21+
public interface ICalendar<T, TEvent> : INotifyPropertyChanged where T : ICalendarDay<TEvent>, new() where TEvent : IEvent
1122
{
1223
#region Properties
1324
ObservableRangeCollection<T> Days { get; }
+6-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
using System;
22
using System.ComponentModel;
3+
using XCalendar.Core.Collections;
34

45
namespace XCalendar.Core.Interfaces
56
{
6-
public interface ICalendarDay : INotifyPropertyChanged
7+
public interface ICalendarDay : ICalendarDay<IEvent>
8+
{
9+
}
10+
public interface ICalendarDay<TEvent> : INotifyPropertyChanged where TEvent : IEvent
711
{
812
DateTime DateTime { get; set; }
913
bool IsSelected { get; set; }
1014
bool IsCurrentMonth { get; set; }
1115
bool IsToday { get; set; }
1216
bool IsInvalid { get; set; }
17+
ObservableRangeCollection<TEvent> Events { get; set; }
1318
}
1419
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
namespace XCalendar.Maui.Interfaces
1+
using System;
2+
3+
namespace XCalendar.Core.Interfaces
24
{
35
public interface IEvent
46
{
57
string Title { get; set; }
68
string Description { get; set; }
79
DateTime DateTime { get; set; }
8-
Color Color { get; set; }
910
}
1011
}

XCalendar.Core/Models/Calendar.cs

+71-3
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,22 @@ namespace XCalendar.Core.Models
1616
/// <summary>
1717
/// A class representing a calendar.
1818
/// </summary>
19-
public class Calendar : Calendar<CalendarDay>
19+
public class Calendar : Calendar<CalendarDay, Event>
2020
{
2121
}
2222
/// <summary>
2323
/// A class representing a calendar.
2424
/// </summary>
25-
/// <typeparam name="T">A model implementing <see cref="ICalendarDay"/> to be used to represent each day in a page.</typeparam>
26-
public class Calendar<T> : ICalendar<T> where T : ICalendarDay, new()
25+
/// <typeparam name="T">A model implementing <see cref="ICalendarDay{TEvent}"/> to be used to represent each day in a page.</typeparam>
26+
public class Calendar<T> : Calendar<T, Event> where T : ICalendarDay<Event>, new()
27+
{
28+
}
29+
/// <summary>
30+
/// A class representing a calendar.
31+
/// </summary>
32+
/// <typeparam name="T">A model implementing <see cref="ICalendarDay{TEvent}"/> to be used to represent each day in a page.</typeparam>
33+
/// <typeparam name="TEvent">A model implementing <see cref="IEvent"/> to be used to represent calendar events.</typeparam>
34+
public class Calendar<T, TEvent> : ICalendar<T, TEvent> where T : ICalendarDay<TEvent>, new() where TEvent : IEvent
2735
{
2836
#region Fields
2937
protected static readonly ReadOnlyCollection<DayOfWeek> DaysOfWeek = DayOfWeekExtensions.DaysOfWeek;
@@ -46,6 +54,7 @@ public class Calendar : Calendar<CalendarDay>
4654
private DateTime? _rangeSelectionStart;
4755
private DateTime? _rangeSelectionEnd;
4856
private SelectionType _selectionType = SelectionType.None;
57+
private ObservableRangeCollection<TEvent> _events = new ObservableRangeCollection<TEvent>();
4958
#endregion
5059

5160
#region Properties
@@ -438,6 +447,31 @@ public SelectionType SelectionType
438447
}
439448
}
440449
}
450+
public ObservableRangeCollection<TEvent> Events
451+
{
452+
get
453+
{
454+
return _events;
455+
}
456+
set
457+
{
458+
if (_events != value)
459+
{
460+
if (_events != null)
461+
{
462+
_events.CollectionChanged -= Events_CollectionChanged;
463+
}
464+
465+
if (value != null)
466+
{
467+
value.CollectionChanged += Events_CollectionChanged;
468+
}
469+
470+
_events = value;
471+
OnPropertyChanged();
472+
}
473+
}
474+
}
441475
#endregion
442476

443477
#region Events
@@ -472,6 +506,8 @@ public Calendar()
472506
SelectedDates.CollectionChanged += SelectedDates_CollectionChanged;
473507
}
474508

509+
Events.CollectionChanged += Events_CollectionChanged;
510+
475511
//Not needed because days are updated in previous lines of code.
476512
UpdateDays(NavigatedDate);
477513
}
@@ -686,6 +722,7 @@ public virtual void UpdateDay(T day, DateTime newDateTime)
686722
day.IsToday = IsDateTimeToday(day.DateTime);
687723
day.IsSelected = IsDateTimeSelected(day.DateTime);
688724
day.IsInvalid = IsDateTimeInvalid(day.DateTime);
725+
UpdateDayEvents(day);
689726
}
690727
/// <summary>
691728
/// Updates the dates displayed on the calendar.
@@ -764,6 +801,33 @@ public virtual void UpdateDays(DateTime navigationDate)
764801

765802
OnDaysUpdated();
766803
}
804+
public virtual void UpdateDayEvents(T day)
805+
{
806+
//It is known that the only thing that the events of the day depend on is the DateTime of the day, and that all events will have the same date.
807+
//So, only update the events if the existing ones' DateTime does not match the day's DateTime.
808+
//If the day has no events, there is no way to tell if it's because the day hasn't been updated before or if there are no events with that date, so update it either way.
809+
if (day.Events.Count > 0 && day.DateTime.Date == day.Events[0].DateTime.Date)
810+
{
811+
return;
812+
}
813+
814+
IEnumerable<TEvent> events = Events.Where(x => x.DateTime.Date == day.DateTime.Date);
815+
816+
//No use in replacing the collection if the source and target are both empty.
817+
if (day.Events.Count == 0 && !events.Any())
818+
{
819+
return;
820+
}
821+
822+
//SequenceEqual could be omitted to improve performance but in the vast majority of cases there won't even be more than 5 events in one day, so impact on performance should be negligible
823+
//compared to always changing the collection and updating the binding.
824+
if (day.Events.SequenceEqual(events))
825+
{
826+
return;
827+
}
828+
829+
day.Events.ReplaceRange(events);
830+
}
767831
/// <summary>
768832
/// Navigates the calendar by the specified <see cref="TimeSpan"/> using the navigation rule properties set in the calendar (<see cref="NavigationLowerBound"/>, <see cref="NavigationUpperBound"/> <see cref="NavigationLoopMode"/>).
769833
/// </summary>
@@ -968,6 +1032,10 @@ private int CoerceRows(int value)
9681032
{
9691033
return AutoRows ? GetMonthRows(NavigatedDate, AutoRowsIsConsistent, StartOfWeek) : value;
9701034
}
1035+
private void Events_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
1036+
{
1037+
UpdateDays(NavigatedDate);
1038+
}
9711039
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
9721040
{
9731041
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

XCalendar.Core/Models/CalendarDay.cs

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
using System;
22
using System.ComponentModel;
33
using System.Runtime.CompilerServices;
4+
using XCalendar.Core.Collections;
45
using XCalendar.Core.Interfaces;
56

67
namespace XCalendar.Core.Models
78
{
8-
public class CalendarDay : ICalendarDay
9+
public class CalendarDay : CalendarDay<Event>
10+
{
11+
}
12+
13+
public class CalendarDay<TEvent> : ICalendarDay<TEvent> where TEvent : IEvent
914
{
1015
#region Fields
1116
private DateTime _dateTime = DateTime.Today;
1217
private bool _isSelected;
1318
private bool _isCurrentMonth;
1419
private bool _isToday;
1520
private bool _isInvalid;
21+
private ObservableRangeCollection<TEvent> _events = new ObservableRangeCollection<TEvent>();
1622
#endregion
1723

1824
#region Properties
@@ -91,6 +97,21 @@ public bool IsInvalid
9197
}
9298
}
9399
}
100+
public ObservableRangeCollection<TEvent> Events
101+
{
102+
get
103+
{
104+
return _events;
105+
}
106+
set
107+
{
108+
if (_events != value)
109+
{
110+
_events = value;
111+
OnPropertyChanged();
112+
}
113+
}
114+
}
94115
#endregion
95116

96117
#region Events

XCalendar.Forms/Models/Event.cs XCalendar.Core/Models/Event.cs

+4-21
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
using System;
22
using System.ComponentModel;
33
using System.Runtime.CompilerServices;
4-
using Xamarin.Forms;
5-
using XCalendar.Forms.Interfaces;
4+
using XCalendar.Core.Interfaces;
65

7-
namespace XCalendar.Forms.Models
6+
namespace XCalendar.Core.Models
87
{
98
public class Event : IEvent, INotifyPropertyChanged
109
{
1110
#region Fields
1211
private string _title;
1312
private string _description;
1413
private DateTime _dateTime = DateTime.Today;
15-
private Color _color;
1614
#endregion
1715

1816
#region Properties
@@ -31,7 +29,8 @@ public string Title
3129
}
3230
}
3331
}
34-
public string Description {
32+
public string Description
33+
{
3534
get
3635
{
3736
return _description;
@@ -60,22 +59,6 @@ public DateTime DateTime
6059
}
6160
}
6261
}
63-
public Color Color
64-
{
65-
get
66-
{
67-
return _color;
68-
}
69-
set
70-
{
71-
if (_color != value)
72-
{
73-
_color = value;
74-
OnPropertyChanged();
75-
}
76-
}
77-
}
78-
7962
#endregion
8063

8164
#region Events

XCalendar.Forms/Interfaces/IComplexCalendarDay.cs

-10
This file was deleted.

XCalendar.Forms/Interfaces/IEvent.cs

-13
This file was deleted.
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Xamarin.Forms;
2+
using XCalendar.Core.Models;
3+
4+
namespace XCalendar.Forms.Models
5+
{
6+
public class ColoredEvent : Event
7+
{
8+
#region Fields
9+
private Color _color;
10+
#endregion
11+
12+
#region Properties
13+
public Color Color
14+
{
15+
get
16+
{
17+
return _color;
18+
}
19+
set
20+
{
21+
if (_color != value)
22+
{
23+
_color = value;
24+
OnPropertyChanged();
25+
}
26+
}
27+
}
28+
#endregion
29+
}
30+
}

0 commit comments

Comments
 (0)