Articles in this section
Category / Section

How to select week in calendar xamarin.forms?

3 mins read

Calendar week selection

Xamarin.Forms calendar supports selecting the entire week using the selection mode is 'RangeSelection' and binding ' SelectedDates ' property of SfCalendar using the MVVM pattern. Calendar week day collection will be retrieved from giving a single selected date in the calendar. Based on the selected date we can generate all calendar week days and bind it to `SelectedDates`.

Step 1

Create a `ViewModel` class and add `SelectedDays` property in the `CalendarViewModel` class.

C#:

    public class CalendarViewModel : INotifyPropertyChanged
    {
        private SelectionRange selectedDays;
        
        /// <summary>
        /// Selected Days
        /// </summary>
        public SelectionRange SelectedDays
        {
            get
            {
                return selectedDays;
            }
            set
            {
                selectedDays = value;
                RaisePropertyChanged("SelectedDays");
            }
        }
 
        /// <summary>
        /// Property changed event handler
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
 
        /// <summary>
        /// Raising Property changed event
        /// </summary>
        /// <param name="propertyName"></param>
        public void RaisePropertyChanged(string propertyName)
        {
            this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Step 2

Create the `CalendarBehavior` class and wire the `SelectionChanged` event for week selection. You can get selected date from ` SelectionChanged` event and based on the selected date you can generate calendar week days by calling ` GetTotalWeekDays()`.

C#:

   /// <summary>
    /// Calendar Behavior class
    /// </summary>
    public class CalendarBehavior : Behavior<ContentPage>
    {
        private CalendarViewModel viewModel;
        private readonly IList<int> weekNumbers = new List<int>();
 
        /// <summary>
        /// Begins when the behavior attached to the view. 
        /// </summary>
        /// <param name="bindable">bindable value</param>
        protected override void OnAttachedTo(BindableObject bindable)
        {
            base.OnAttachedTo(bindable);
            var calendar = (bindable as MainPage).FindByName<SfCalendar>("calendar");
            if (calendar == null)
            {
                return;
            }
 
            calendar.SelectionChanged += Calendar_SelectionChanged;
        }
 
        /// <summary>
        /// Selection Changed event
        /// </summary>
        /// <param name="sender">return the object</param>
        /// <param name="e">Selection Changed Event Args</param>
        private void Calendar_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (viewModel == null)
            {
                viewModel = (CalendarViewModel)(sender as SfCalendar).BindingContext;
            }
 
            if (e.DateAdded.Count == 0)
            {
                viewModel.SelectedDays = GetTotalWeekDays(e.DateAdded[0]);
            }
            else
            {
                if (GetWeekOfYear(e.DateAdded[0]) != GetWeekOfYear(e.DateAdded[e.DateAdded.Count - 1]))
                {
                    viewModel.SelectedDays = GetTotalWeekDays(e.DateAdded[0], e.DateAdded[e.DateAdded.Count - 1]);
                }
                else
                {
                    viewModel.SelectedDays = GetTotalWeekDays(e.DateAdded[0]);
                }
            }
        }
 
        /// <summary>
        /// Retrieve Week Days from the given date ranges.
        /// </summary>
        /// <param name="startDateRange">dateTime value</param>
        /// <param name="endDateRange">endDateTime value</param>
        /// <returns></returns>
        public SelectionRange GetTotalWeekDays(DateTime startDateRange, DateTime? endDateRange = null)
        {
            if (endDateRange == null)
            {
                var days = DayOfWeek.Sunday - startDateRange.DayOfWeek;
                var startDate = startDateRange.AddDays(days);
                ObservableCollection<DateTime> dates = new ObservableCollection<DateTime>();
                for (var i = 0; i < 7; i++)
                {
                    dates.Add(startDate.Date);
                    startDate = startDate.AddDays(1);
                }
 
                return new SelectionRange(dates[0], dates[dates.Count - 1]);
            }
            else
            {
                ObservableCollection<DateTime> dates = new ObservableCollection<DateTime>();
                var startDayOfWeek = DayOfWeek.Sunday - startDateRange.DayOfWeek;
                var startDate = startDateRange.AddDays(startDayOfWeek);
 
                var endDayOfWeek = DayOfWeek.Saturday - endDateRange?.DayOfWeek;
                var endDate = endDateRange?.AddDays((int)endDayOfWeek);
 
                var difference = (endDate - startDate);
 
                for (var i = 0; i < ((TimeSpan)difference).Days + 1; i++)
                {
                    dates.Add(startDate.Date);
                    startDate = startDate.AddDays(1);
                }
 
                return new SelectionRange(dates[0], dates[dates.Count - 1]);
            }
        }
 
        /// <summary>
        /// Method for Get Week
        /// </summary>
        /// <param name="time">time value</param>
        /// <returns></returns>
        public static int GetWeekOfYear(DateTime time)
        {
            DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
            if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
            {
                time = time.AddDays(3);
            }
            return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Sunday);
        }
    }

Step 3

Now bind the `SelectedDays` property of the `ViewModel` class with Calendar `SelectedRange` property, set the `SelectionMode` as `RangeSelection` and `CalendarViewModel` as the `BindingContext` for the calendar

XAML:

    <ContentPage.Content>
        <calendar:SfCalendar x:Name="calendar" 
                             SelectionMode="RangeSelection" 
                             SelectedRange="{Binding SelectedDays}">
       <calendar:SfCalendar.BindingContext>
                <local:CalendarViewModel/>
      </calendar:SfCalendar.BindingContext>
        </calendar:SfCalendar>
       <ContentPage.Behaviors>
           <local:CalendarBehavior />
       </ContentPage.Behaviors>   
    </ContentPage.Content>

Sample outputs:

Selection of calendar week days

Figure 1: Selecting single of calendar week by single selection

Swiping selection of calendar week days

Figure 2: Selecting multiple of calendar weeks by swiping selected weeks.

 

Sample link: https://github.com/SyncfusionExamples/calendar-week-selection

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please sign in to leave a comment
Access denied
Access denied