Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 91519

Adding pages programmatically to CarouselPage

$
0
0

Hello everybody!

_I realized the crutch! It works, but I would like to know better approaches to this task. _

I have Months that I want to display in CarouselPage. Here are the problems I faced:
1. At the start, display the second page, the first page on the left, and the third page on the right;
2. Assign a unique identifier to each page (in my case it was the date of the first day of each month);
3. Add pages if user swipe left or right;
4. Add ActivityIndicator to the entire CarouselPage (I added it in templates for each page);
5. Translate CarouselPage events into commands, I get an exception if I use Convac.Behaviors or my own EventToCommandBehavior class.

Month Carousel Page Xaml:

<?xml version="1.0" encoding="utf-8" ?>
<base:CarouselBasePage
    x:Class="MDOSchedule.UI.Pages.AllJobs.CarouselAllJobsWeekPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:base="clr-namespace:MDOSchedule.UI.Pages.Base;assembly=MDOSchedule"
    xmlns:templates="clr-namespace:MDOSchedule.UI.Templates;assembly=MDOSchedule"
    xmlns:week="clr-namespace:MDOSchedule.UI.Views.Week;assembly=MDOSchedule"

    x:Name="This"
    Title="{Binding CurrentDate, StringFormat='{0:MMMM yyyy}'}"
    BindingContextChanged="CarouselAllJobsWeekPage_OnBindingContextChanged"
    CurrentPageChanged="CarouselAllJobsWeekPage_OnCurrentPageChanged"
    ItemsSource="{Binding Weeks}"
    PagesChanged="CarouselAllJobsWeekPage_OnPagesChanged">

    <CarouselPage.ToolbarItems>
        <ToolbarItem
            Command="{Binding RefreshItemsCommand}"
            Icon="ic_refresh.png"
            Order="Primary" />
    </CarouselPage.ToolbarItems>

    <CarouselPage.ItemTemplate>
        <DataTemplate>
            <ContentPage Title="{Binding DateOfFirstDayOfWeek}">

                <AbsoluteLayout>
                    <week:ScheduleWeekView
                        AbsoluteLayout.LayoutBounds="0,0,1,1"
                        AbsoluteLayout.LayoutFlags="All"
                        ItemTappedCommand="{Binding ItemTappedCommand}"
                        WeekItems="{Binding Days}" />

                    <templates:ActivityIndicatorTemplate BindingContext="{Binding Source={x:Reference This}, Path=BindingContext}" />
                </AbsoluteLayout>
            </ContentPage>
        </DataTemplate>
    </CarouselPage.ItemTemplate>

</base:CarouselBasePage>

Month Carousel Page Xaml.CS:

    public partial class CarouselAllJobsMonthPage : CarouselBasePage
        {
            #region Private Fields

            private CarouselAllJobsMonthViewModel _viewModel;

            private bool _isInitialized;

            #endregion


            #region Init

            public CarouselAllJobsMonthPage()
            {
                InitializeComponent();
            }

            #endregion


            #region Events

            private void CarouselAllJobsMonthPage_OnBindingContextChanged(object sender, EventArgs e)
            {
                _viewModel = BindingContext as CarouselAllJobsMonthViewModel;
            }

            private void CarouselAllJobsMonthPage_OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (!_isInitialized
                    && Children.Count > 2)
                {
                    CurrentPage = this.Children[1];
                    _isInitialized = true;
                }
            }

            private void CarouselAllJobsMonthPage_OnCurrentPageChanged(object sender, EventArgs e)
            {
                _viewModel.CurrentPageChangedCommand.Execute(this.CurrentPage);
            }

            #endregion
        }

My Carousel View Model:

public class CarouselAllJobsMonthViewModel : BaseViewModel
    {
        // Fields

        #region Public Fields

        public ObservableCollection<Month> Months
        {
            get => Get<ObservableCollection<Month>>();
            set => Set(value);
        }   

        public DateTime CurrentDate
        {
            get => Get<DateTime>();
            set => Set(value);
        }

        #endregion


        #region Private Fields

        private DateTime _previousDate;
        private int _pagesCount = 3;

        private int _pageIndex = 1;

        #endregion


        // Methods  

        #region Commands

        public ICommand RefreshItemsCommand =>
            new Command(async () => await ShowLoading(RefreshItems));

        public ICommand ItemTappedCommand => 
            new Command<DayInfo>(DayTapped);    

        public ICommand CurrentPageChangedCommand => 
            new Command<ContentPage>(async page => await LoadNextPage(page));


        private async Task RefreshItems()
        {
            Months[_pageIndex].Weeks = GetMonth(CurrentDate).Weeks;

            await Task.Delay(1500);
        }

        private void DayTapped(DayInfo obj)
        {

        }

        private async Task LoadNextPage(ContentPage page)
        {
            if (!DateTime.TryParse(page?.Title,
                                   DateTimeFormatInfo.InvariantInfo,
                                   DateTimeStyles.None,
                                   out DateTime newDate))
                return;

            if (newDate.DateEqualsByDay(CurrentDate))
                return;

            await ShowLoading(async () =>
            {
                // Calculate current position and Time
                _previousDate = this.CurrentDate;
                this.CurrentDate = newDate;

                _pageIndex += newDate < _previousDate ? -1 : 1;

                // Add to the head
                if (newDate.DateEqualsByDay(Months[0].FirstDayOfMonth))
                {
                    Months.Insert(0, GetMonth(CurrentDate.AddMonths(-1)));
                    _pagesCount++;
                    await Task.Delay(1500);
                }
                // Add to the tail      
                else if (newDate.DateEqualsByDay(Months[_pagesCount - 1].FirstDayOfMonth))
                {
                    Months.Add(GetMonth(CurrentDate.AddMonths(1)));
                    _pagesCount++;
                    await Task.Delay(1500);
                }
            });
        }

        #endregion


        #region Init



        #endregion


        #region Override Methods

        public override async Task OnPageAppearing()
        {
            await ShowLoading(async () =>
            {
                Months = new ObservableCollection<Month>
                {
                    GetMonth(DateTime.Now.AddMonths(-1)),
                    GetMonth(DateTime.Now),
                    GetMonth(DateTime.Now.AddMonths(1)),
                };

                CurrentDate = Months[0].FirstDayOfMonth;
            });
        }

        #endregion


        #region Private Methods 


        #endregion


        #region Test

        private Month GetMonth(DateTime monthTime)
        {
            var weeks = new List<Week>();

            DateTime firstDayOfMonth = new DateTime(monthTime.Year, monthTime.Month, 1);

            var lastMondayOfPreviousMonth = firstDayOfMonth;
            while (lastMondayOfPreviousMonth.DayOfWeek != DayOfWeek.Monday)
                lastMondayOfPreviousMonth = lastMondayOfPreviousMonth.AddDays(-1);

            var currentDate = lastMondayOfPreviousMonth;
            for (int i = 0; i < 6; i++)
            {
                var week = new Week { Days = GetDays(currentDate) };
                weeks.Add(week);
                currentDate = currentDate.AddDays(7);
            }

            return new Month
            {
                FirstDayOfMonth = firstDayOfMonth,
                Weeks = weeks,
                ItemTappedCommand = this.ItemTappedCommand
            };
        }

        private readonly Random _random = new Random();

        private List<DayInfo> GetDays(DateTime firstDay)
        {
            var days = new List<DayInfo>();
            for (int i = 0; i < 7; i++)
            {
                var jobs = new List<JobObject>();

                if (i != 2)
                    for (int j = 0; j < 10; j++)
                    {
                        jobs.Add(new JobObject()
                        {
                            Color = (j & _random.Next(3)) == 1 ? "#42f47d" : "#ff6677",
                            JobId = _random.Next(70),
                            Monteurs = new List<MonteurObject>()
                            {
                                new MonteurObject()
                                {
                                    TeamName = "Tax"
                                }
                            }
                        });
                    }
                days.Add(new DayInfo(firstDay.AddDays(i), jobs));
            }

            return days;
        }

        #endregion
    }

Viewing all articles
Browse latest Browse all 91519

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>