Skip to main content
deleted 20 characters in body; edited title
Source Link
Mathieu Guindon
  • 75.6k
  • 18
  • 195
  • 469

Optimize user Custom CalendarPicker control

Thanks in advance.

Optimize user control

Thanks in advance.

Custom CalendarPicker control

Source Link

Optimize user control

I have a calendar view that is slow in uploading. The part that slows down the calendarview should be in the CalendarPageViewModel.cs. But I do not know how to improve it because it's a loop for.

Whole project Calendar View.

CalendarPicker.xaml:

<UserControl
x:Class="CalendarView.CalendarPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CalendarView"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="Page_Loaded"
Height="500"
Width="350">

<UserControl.DataContext>
    <local:CalendarPageViewModel x:Name="ViewModel"/>
</UserControl.DataContext>

<Grid>
    <Grid Background="#FF106F97">
        <Grid Width="350" Height="500" HorizontalAlignment="Center" VerticalAlignment="Bottom">
            <Grid.RowDefinitions>
                <RowDefinition Height="50"/>
                <RowDefinition Height="50"/>
                <RowDefinition Height="50"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Button x:Name="btnToday" Click="btnToday_Click" FontSize="20" Foreground="White" VerticalAlignment="Stretch" Style="{StaticResource ButtonStyleToday}" Padding="4" HorizontalAlignment="Stretch"/>
            <TextBlock x:Name="txtSelectedDay" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="12,0,0,0" FontSize="20" Foreground="White"/>
            <Button x:Name="btnMonthYear" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="25" Foreground="White"  Margin="12,0,0,0" Style="{StaticResource ButtonStyleTrasparent}" Padding="0,4,8,4"/>
            <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Height="50" VerticalAlignment="Center">
                <Button x:Name="btnDecYearMonthDay" Click="btnDecYearMonthDay_Click" Content="&#xE010;" FontFamily="Segoe MDL2 Assets" VerticalAlignment="Stretch" Width="50" FontSize="30" Padding="0" BorderBrush="White" Foreground="White" BorderThickness="0" Style="{StaticResource ButtonStyleTrasparent}"/>
                <Button x:Name="btnIncYearMonthDay" Click="btnIncYearMonthDay_Click" Content="&#xE011;" FontFamily="Segoe MDL2 Assets" VerticalAlignment="Stretch" Width="50" FontSize="30" Padding="0" BorderBrush="White" Foreground="White" BorderThickness="0" Style="{StaticResource ButtonStyleTrasparent}"/>
            </StackPanel>
            <Grid x:Name="BaseGridDays" Visibility="Visible" Grid.Row="3" RenderTransformOrigin="0.5,0.5">
                <Grid.RenderTransform>
                    <CompositeTransform/>
                </Grid.RenderTransform>
                <Grid x:Name="GridHeadingDay" Height="50" VerticalAlignment="Top">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Text="lu" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="25"/>
                    <TextBlock Grid.Column="1" Text="ma" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="25"/>
                    <TextBlock Grid.Column="2" Text="me" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="25"/>
                    <TextBlock Grid.Column="3" Text="gi" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="25"/>
                    <TextBlock Grid.Column="4" Text="ve" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="25"/>
                    <TextBlock Grid.Column="5" Text="sa" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="25"/>
                    <TextBlock Grid.Column="6" Text="do" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontSize="25"/>
                </Grid>
                <Canvas x:Name="CanvasRootDays" Height="300" VerticalAlignment="Bottom">
                    <GridView x:Name="GridDays" ItemsSource="{Binding ItemsDay}" IsItemClickEnabled="True" ItemClick="GridDays_ItemClick" Height="300" Width="350" Padding="0" IsSwipeEnabled="False" IsTabStop="False" IsSynchronizedWithCurrentItem="False" ItemContainerStyle="{StaticResource GridViewItemStyle}" Style="{StaticResource GridViewStyleAnniMesiGiorni}" ScrollViewer.VerticalScrollBarVisibility="Hidden">
                        <GridView.ItemTemplate>
                            <DataTemplate x:DataType="local:CalendarDay">
                                <Grid Width="50" Height="50" Background="{x:Bind ToDayColor}">
                                    <TextBlock Text="{x:Bind ProgressiveDay, Mode=OneWay}" Foreground="{x:Bind daysColor, Mode=OneWay}" FontSize="15" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                </Grid>
                            </DataTemplate>
                        </GridView.ItemTemplate>
                    </GridView>
                </Canvas>
            </Grid>
        </Grid>
    </Grid>
</Grid>

CalendarPicker.xaml.cs:

public sealed partial class CalendarPicker : UserControl
{
    DispatcherTimer timerVisDays = new DispatcherTimer();
    DispatcherTimer timerTimeNow = new DispatcherTimer();
    int FirstDay;

    public CalendarPicker()
    {
        InitializeComponent();
        timerVisDays.Interval = new TimeSpan(0, 0, 0, 0, 30);
        timerVisDays.Tick += timerShowDays_tick;
        timerVisDays.Start();
    }

    private void GridDays_ItemClick(object sender, ItemClickEventArgs e)
    {
        var item = e.ClickedItem as CalendarDay;
        var index = (ViewModel.ItemsDay).IndexOf(item);
        string dayString = FindStringWeek(Convert.ToUInt16(ViewModel.listDateDay[index - 1].DayOfWeek));
        int day = ViewModel.listDateDay[index].Day;
        string month = FindStringMonth(ViewModel.listDateDay[index].Month);
        int year = ViewModel.listDateDay[index].Year;
        txtSelectedDay.Text = dayString + "  " + day.ToString() + "  " + month + "  " + year.ToString();
    }

    private void timerShowDays_tick(object sender, object e)
    {
        ScrollViewer listScrollViewerDays = GetScrollViewer(GridDays);
        FirstDay = (Convert.ToUInt16(Math.Truncate(listScrollViewerDays.VerticalOffset / 50)) * 7);
        int numberOfDates;
        double remnant = (listScrollViewerDays.VerticalOffset / 50) - (Math.Truncate(listScrollViewerDays.VerticalOffset / 50));
        if (remnant == 0)
        {
            numberOfDates = 42;
        }
        else
        {
            numberOfDates = 49;
        }
        int nDaysMonthFirstDate = FindNumberOfDays(ViewModel.listDateDay[FirstDay].Month);
        int firstDayPresent = ViewModel.listDateDay[FirstDay].Day;
        int nDaysPresentFirstDate = nDaysMonthFirstDate - (firstDayPresent - 1);
        int nDaysPresentSecondDate = numberOfDates - nDaysPresentFirstDate;
        if (nDaysPresentFirstDate > nDaysPresentSecondDate)
        {
            for (int a = FirstDay; a <= FirstDay + (numberOfDates - 1); a++)
            {
                if (a <= ViewModel.ItemsDay.Count - 1)
                {
                    if (ViewModel.listDateDay[a].Month != ViewModel.listDateDay[FirstDay].Month)
                    {
                        ViewModel.ItemsDay[a].daysColor = new SolidColorBrush(Color.FromArgb(255, 160, 160, 160));
                    }
                }
            }
        }
        else
        {
            for (int a = FirstDay; a <= FirstDay + (numberOfDates - 1); a++)
            {
                if (a <= ViewModel.ItemsDay.Count - 1)
                {
                    if (ViewModel.listDateDay[a].Month != ViewModel.listDateDay[FirstDay].AddMonths(1).Month)
                    {
                        ViewModel.ItemsDay[a].daysColor = new SolidColorBrush(Color.FromArgb(255, 160, 160, 160));
                    }
                }
            }
        }
        timerVisDays.Stop();
    }

    private string FindStringWeek(int gs)
    {
        if (true == (gs == 0))
        {
            return "monday";
        }
        else if (true == (gs == 1))
        {
            return "tuesday";
        }
        else if (true == (gs == 2))
        {
            return "wednesday";
        }
        else if (true == (gs == 3))
        {
            return "thursday";
        }
        else if (true == (gs == 4))
        {
            return "friday";
        }
        else if (true == (gs == 5))
        {
            return "saturday";
        }
        else if (true == (gs == 6))
        {
            return "sunday";
        }
        else
        {
            return "";
        }
    }

    private string FindStringMonth(int gs)
    {
        if (true == (gs == 1))
        {
            return "ganuary";
        }
        else if (true == (gs == 2))
        {
            return "february";
        }
        else if (true == (gs == 3))
        {
            return "march";
        }
        else if (true == (gs == 4))
        {
            return "april";
        }
        else if (true == (gs == 5))
        {
            return "may";
        }
        else if (true == (gs == 6))
        {
            return "june";
        }
        else if (true == (gs == 7))
        {
            return "july";
        }
        else if (true == (gs == 8))
        {
            return "august";
        }
        else if (true == (gs == 9))
        {
            return "september";
        }
        else if (true == (gs == 10))
        {
            return "october";
        }
        else if (true == (gs == 11))
        {
            return "november";
        }
        else if (true == (gs == 12))
        {
            return "december";
        }
        else
        {
            return "";
        }
    }

    private int FindNumberOfDays(int gs)
    {
        if (true == (gs == 1))
        {
            return 31;
        }
        else if (true == (gs == 2))
        {
            return 29;
        }
        else if (true == (gs == 3))
        {
            return 31;
        }
        else if (true == (gs == 4))
        {
            return 30;
        }
        else if (true == (gs == 5))
        {
            return 31;
        }
        else if (true == (gs == 6))
        {
            return 30;
        }
        else if (true == (gs == 7))
        {
            return 31;
        }
        else if (true == (gs == 8))
        {
            return 31;
        }
        else if (true == (gs == 9))
        {
            return 30;
        }
        else if (true == (gs == 10))
        {
            return 31;
        }
        else if (true == (gs == 11))
        {
            return 30;
        }
        else if (true == (gs == 12))
        {
            return 31;
        }
        else
        {
            return 0;
        }
    }

    public ScrollViewer GetScrollViewer(DependencyObject o)
    {
        if (o is ScrollViewer)
        {
            return o as ScrollViewer;
        }

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
        {
            var child = VisualTreeHelper.GetChild(o, i);
            var result = GetScrollViewer(child);
            if (result == null)
            {
                continue;
            }
            else
            {
                return result;
            }
        }
        return null;
    }

    private async void Page_Loaded(object sender, RoutedEventArgs e)
    {
        ScrollViewer listScrollViewerDays = GetScrollViewer(GridDays);
        GridDays.SelectedItem = GridDays.Items[ViewModel.indexDDay];
        ViewModel.ItemsDay[ViewModel.indexDDay].ToDayColor = new SolidColorBrush(Color.FromArgb(255, 17, 95, 155));
        await Task.Delay(100);
        GridDays.ScrollIntoView(GridDays.Items[ViewModel.indexToDay], ScrollIntoViewAlignment.Leading);
        listScrollViewerDays.ViewChanged += DisplayDays;
        btnToday.Content = FindStringWeek(Convert.ToInt32(DateTime.Now.DayOfWeek)) + " " + DateTime.Now.Day.ToString() + " " + FindStringMonth(DateTime.Now.Month) + " " + DateTime.Now.Year.ToString();
    }

    private void DisplayDays(object sender, ScrollViewerViewChangedEventArgs e)
    {
        timerVisDays.Stop();
        timerVisDays.Start();

        ScrollViewer listScrollViewer = GetScrollViewer(GridDays);
        FirstDay = (Convert.ToUInt16(Math.Truncate(listScrollViewer.VerticalOffset / 50)) * 7);
        int numberOfDates;
        string currentMonth = "";
        string currentYear = "";
        int indexCorrentMonth;
        double remnant = (listScrollViewer.VerticalOffset / 50) - (Math.Truncate(listScrollViewer.VerticalOffset / 50));
        if (remnant == 0)
        {
            numberOfDates = 42;
        }
        else
        {
            numberOfDates = 49;
        }
        int nDaysMonthFirstDate = FindNumberOfDays(ViewModel.listDateDay[FirstDay].Month);
        int firstDayPresent = ViewModel.listDateDay[FirstDay].Day;
        int nDaysPresentFirstDate = nDaysMonthFirstDate - (firstDayPresent - 1);
        int nDaysPresentSecondDate = numberOfDates - (nDaysPresentFirstDate);
        if (nDaysPresentFirstDate > nDaysPresentSecondDate)
        {
            currentMonth = FindStringMonth(ViewModel.listDateDay[FirstDay].Month);
            currentYear = ViewModel.listDateDay[FirstDay].Year.ToString();
            indexCorrentMonth = FirstDay;
        }
        else
        {
            int numMonth = ViewModel.listDateDay[FirstDay].AddMonths(1).Month;
            currentYear = ViewModel.listDateDay[FirstDay].AddMonths(1).Year.ToString();
            currentMonth = FindStringMonth(numMonth);

        }
        btnMonthYear.Content = currentMonth + " " + currentYear;
        for (int a = FirstDay; a <= FirstDay + numberOfDates; a++)
        {
            try
            {
                ViewModel.ItemsDay[a].daysColor = new SolidColorBrush(Colors.White);
            }
            catch { }
        }
    }

    private async void IncreasesMonth()
    {
        ScrollViewer listScrollViewer = GetScrollViewer(GridDays);
        FirstDay = (Convert.ToUInt16(Math.Truncate(listScrollViewer.VerticalOffset / 50)) * 7);
        int numberOfDates;
        bool firstdayfound = false;
        DateTime indexSucceedingMonth;
        double remnant = (listScrollViewer.VerticalOffset / 50) - (Math.Truncate(listScrollViewer.VerticalOffset / 50));
        if (remnant == 0)
        {
            numberOfDates = 42;
        }
        else
        {
            numberOfDates = 49;
        }
        int nDaysMonthFirstDate = FindNumberOfDays(ViewModel.listDateDay[FirstDay].Month);
        int firstDayPresent = ViewModel.listDateDay[FirstDay].Day;
        int nDaysPresentFirstDate = nDaysMonthFirstDate - (firstDayPresent - 1);
        int nDaysPresentSecondDate = numberOfDates - (nDaysPresentFirstDate);
        if (nDaysPresentFirstDate > nDaysPresentSecondDate)
        {
            indexSucceedingMonth = new DateTime(ViewModel.listDateDay[FirstDay].Year, ViewModel.listDateDay[FirstDay].AddMonths(1).Month, 1, 0, 0, 0);
            while (firstdayfound == false)
            {
                if (ViewModel.listDateDay[FirstDay] == indexSucceedingMonth)
                {
                    firstdayfound = true;
                }
                FirstDay += 1;
            }
        }
        else
        {
            DateTime IncreasedDate = ViewModel.listDateDay[FirstDay].AddMonths(2);
            indexSucceedingMonth = new DateTime(IncreasedDate.Year, IncreasedDate.Month, 1, 0, 0, 0);
            while (firstdayfound == false)
            {
                if (ViewModel.listDateDay[FirstDay] == indexSucceedingMonth)
                {
                    firstdayfound = true;
                }
                FirstDay += 1;
            }
        }

        var item = GridDays.ContainerFromIndex(FirstDay - 1) as GridViewItem;
        var gt = item.TransformToVisual(CanvasRootDays);
        double offestCanvas = gt.TransformPoint(new Point(0, 0)).Y;
        listScrollViewer.ChangeView(null, listScrollViewer.VerticalOffset + offestCanvas, null, false);

        await Task.Delay(300);
    }

    private async void DecreaseMonth()
    {
        ScrollViewer listScrollViewer = GetScrollViewer(GridDays);
        FirstDay = (Convert.ToUInt16(Math.Truncate(listScrollViewer.VerticalOffset / 50)) * 7);
        int numberOfDates;
        bool firstdayfound = false;
        DateTime indexSucceedingMonth;
        double avanzo = (listScrollViewer.VerticalOffset / 50) - (Math.Truncate(listScrollViewer.VerticalOffset / 50));
        if (avanzo == 0)
        {
            numberOfDates = 42;
        }
        else
        {
            numberOfDates = 49;
        }
        int nDaysMonthFirstDate = FindNumberOfDays(ViewModel.listDateDay[FirstDay].Month);
        int firstDayPresent = ViewModel.listDateDay[FirstDay].Day;
        int nDaysPresentFirstDate = nDaysMonthFirstDate - (firstDayPresent - 1);
        int nDaysPresentSecondDate = numberOfDates - (nDaysPresentFirstDate);
        if (nDaysPresentFirstDate > nDaysPresentSecondDate)
        {
            DateTime IncreasedDate = ViewModel.listDateDay[FirstDay].AddMonths(-1);
            indexSucceedingMonth = new DateTime(IncreasedDate.Year, IncreasedDate.Month, 1, 0, 0, 0);
            while (firstdayfound == false)
            {
                if (ViewModel.listDateDay[FirstDay] == indexSucceedingMonth)
                {
                    firstdayfound = true;
                }
                FirstDay -= 1;
            }
        }
        else
        {
            DateTime IncreasedDate = ViewModel.listDateDay[FirstDay];
            indexSucceedingMonth = new DateTime(IncreasedDate.Year, IncreasedDate.Month, 1, 0, 0, 0);
            while (firstdayfound == false)
            {
                if (ViewModel.listDateDay[FirstDay] == indexSucceedingMonth)
                {
                    firstdayfound = true;
                }
                FirstDay -= 1;
            }
        }

        var item = GridDays.ContainerFromIndex(FirstDay + 1) as GridViewItem;
        var gt = item.TransformToVisual(CanvasRootDays);
        double offestCanvas = gt.TransformPoint(new Point(0, 0)).Y;
        listScrollViewer.ChangeView(null, listScrollViewer.VerticalOffset - (offestCanvas * -1), null, false);

        await Task.Delay(300);
    }

    private void btnDecYearMonthDay_Click(object sender, RoutedEventArgs e)
    {

          DecreaseMonth();
    }

    private void btnIncYearMonthDay_Click(object sender, RoutedEventArgs e)
    {

         IncreasesMonth();

    }

    private void btnToday_Click(object sender, RoutedEventArgs e)
    {
        GridDays.SelectedItem = GridDays.Items[ViewModel.indexDDay];
        GridDays.ScrollIntoView(GridDays.Items[ViewModel.indexToDay], ScrollIntoViewAlignment.Leading);
    }
}

CalendarPageViewModel.cs:

class CalendarPageViewModel : ViewModelBase
{
    private ObservableCollection<CalendarDay> _itemsDay;
    private ObservableCollection<DateTime> _listaDateDay = new ObservableCollection<DateTime>();
    private ObservableCollection<DateTime> _listaDateMonth = new ObservableCollection<DateTime>();
    private ObservableCollection<DateTime> _listaDateYear = new ObservableCollection<DateTime>();
    public ObservableCollection<CalendarDay> ItemsDay
    {
        get
        {
            return _itemsDay;
        }
        set
        {
            _itemsDay = value;
            OnPropertyChanged();
        }
    }
    public ObservableCollection<DateTime> listDateDay
    {
        get
        {
            return _listaDateDay;
        }
        set
        {
            _listaDateDay = value;
            OnPropertyChanged();
        }
    }
    public ObservableCollection<DateTime> listDateMonth
    {
        get
        {
            return _listaDateMonth;
        }
        set
        {
            _listaDateMonth = value;
            OnPropertyChanged();
        }
    }
    public ObservableCollection<DateTime> listDateYear
    {
        get
        {
            return _listaDateYear;
        }
        set
        {
            _listaDateYear = value;
            OnPropertyChanged();
        }
    }
    public int indexToDay { get; set; }
    public int indexDDay { get; set; }
    public CalendarPageViewModel()
    {
        var listDay = new ObservableCollection<CalendarDay>();
        DateTime monthToDay = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1, 0, 0, 0);
        DateTime monthToDayM = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0);
        DateTime yearsToDay = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0);
        DateTime dayOfToday = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
        DateTime progressiveDay = new DateTime(1900, 1, 1);
        listDateDay.Add(progressiveDay);
        listDateMonth.Add(new DateTime(progressiveDay.Year, 1, 1, 0, 0, 0));
        listDateYear.Add(new DateTime(progressiveDay.Year, 1, 1, 0, 0, 0));
        for (var i = 0; i < 72000; i++)
        {
            listDay.Add(new CalendarDay { ProgressiveDay = progressiveDay.Day.ToString() });
           
            progressiveDay = progressiveDay.AddDays(1);
            listDateDay.Add(progressiveDay);
        }
        for (int a = 0; a <= listDateDay.Count - 1; a++)
        {
            if (listDateDay[a] == monthToDay)
            {
                indexToDay = a;
            }
            else if (listDateDay[a] == dayOfToday)
            {
                indexDDay = a;
            }
        }
        _itemsDay = listDay;
    }
}

Thanks in advance.