Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing DateTime of a day in viewmodel to make more control for background changing #111

Open
masterofdaemon opened this issue Feb 7, 2023 · 5 comments
Labels
awaiting-author Awaiting a respose from the author enhancement New feature or request question Further information is requested

Comments

@masterofdaemon
Copy link

masterofdaemon commented Feb 7, 2023

Hello, i have a problem with some logic, how can i pass here DateTime of a day instead static one 9-2-2023 ?

<xc:CalendarView.DayTemplate>
                <DataTemplate x:DataType="{x:Type xcModels:CalendarDay}">
                    <Border
                        Margin="2.5"
                        BackgroundColor="{Binding BindingContext.ObservableParameters[9-2-2023], Source={x:Reference This},

or how i can make it in c#?

new CalendarView{ VerticalOptions = LayoutOptions.Start}
				.Bind(CalendarView.DaysProperty, static(WorkDayViewModel vm) => vm.Calendar.Days)
				.Bind(CalendarView.DaysOfWeekProperty, static(WorkDayViewModel vm) => vm.Calendar.DayNamesOrder)

i can't make children of it and this solution is faster i think

@masterofdaemon masterofdaemon added the enhancement New feature or request label Feb 7, 2023
@masterofdaemon
Copy link
Author

masterofdaemon commented Feb 7, 2023

new CalendarView{ VerticalOptions = LayoutOptions.Start, DayTemplate = new DataTemplate{}
    }

that's all i can get but i don't know how to implement DataTemplate, help me please, with any solution

@ME-MarvinE
Copy link
Owner

ME-MarvinE commented Feb 7, 2023

The DataTemplate you provide for CalendarView.DayTemplate gets passed a BindingContext of the type of day you used in the CalendarView's Days property. The default Calendar uses CalendarDay.

So just like how you would normally bind to your ViewModel's properties, you can bind to all the properties of the CalendarDay instead. The CalendarDay's DateTime property is what you are looking for, so in your example, you would have BackgroundColor="{Binding DateTime}".

If you want to change this value from your ViewModel, just change it in the actual collection you binded the CalendarView's Days property to.

public void Set8thDayToToday()
{
    //Assuming you have binded the 'Days' property to 'MyCalendar.Days' in your CalendarView:
    MyCalendar.Days[7].DateTime = DateTime.Today;
}

However, since the days' properties get changed by the Calendar such as CalendarDay.DateTime when navigating or CalendarDay.IsSelected when the Calendar.SelectedDates collection is modified (the logic for this is overridable in child classes), you'll probably want to attach an event handler to the Calendar's DaysUpdated event and change the values in there. The DaysUpdated event gets called after the Calendar updates the properties of the days in its Days collection.

For example:

ViewModel:

public class MyViewModel
{
    public Calendar<CalendarDay> MyCalendar { get; set; } =  new Calendar();

    public MyViewModel()
    {
        MyCalendar.DaysUpdated += MyCalendar_DaysUpdated();
    }

    public void MyCalendar_DaysUpdated(object sender, EventArgs e)
    {
        Set8thDayToToday();
    }

    public void Set8thDayToToday()
    {
        MyCalendar.Days[7].DateTime = DateTime.Today;
    }
}

View:

<xc:CalendarView Days="{Binding MyCalendar.Days"} DaysOfWeek="{Binding MyCalendar.DayNamesOrder}" NavigatedDate="{Binding MyCalendar.NavigatedDate}">

    <xc:CalendarView.DayTemplate>
        <DataTemplate>
            <!--This will bind to the 'DateTime' property of the CalendarDay-->
            <Label Text="{Binding DateTime}"/>
        </DataTemplate>
    </xc:CalendarView.DayTemplate>

</xc:CalendarView>

I don't know how to create views in C#. You can find many resources on the internet that will explain bindings in C# better than me.

@ME-MarvinE ME-MarvinE added question Further information is requested and removed enhancement New feature or request labels Feb 7, 2023
@masterofdaemon
Copy link
Author

masterofdaemon commented Feb 7, 2023

i need to make work day another color and selected another too :
` WorkDays.Add(new DateTime(2023, 2, 9));

        WorkDays.Add(new DateTime(2023, 2, 10));

        WorkDays.Add(new DateTime(2023, 2, 11));

        WorkDays.Add(new DateTime(2023, 2, 12));

        foreach (var day in Calendar.Days)
        {
            if (WorkDays.Contains(day.DateTime))
            {
                Parameters.Add($"{day.DateTime.Day}-{day.DateTime.Month}-{day.DateTime.Year}", Color.FromArgb("#00f"));
            }
            else
            {
                Parameters.Add($"{day.DateTime.Day}-{day.DateTime.Month}-{day.DateTime.Year}", Color.FromArgb("#f00"));
            }
        }`

@ME-MarvinE
Copy link
Owner

ME-MarvinE commented Feb 7, 2023

You can replicate the default functionality of a day by using a DayView in the CalendarView's DayTemplate property. You will need to bind the IsSelected, IsToday, IsCurrentMonth, and IsInvalid properties of the DayView to the ones in the CalendarDay. You will also need to set the SelectedCommand, TodayCommand, and CurrentMonthCommand to the command you use to select a day.

To change what colours the DayView changes to, there are properties for the TextColor and BackgroundColor for each state the CalendarDay can be in. For example SelectedBackgroundColor will be the colour used when the day is selected, OtherMonthCommand will occurr when the day is not in the current month. All the custom properties for DayView are explained on this page in the wiki.

Currently there is no easy way to override the changes that the DayView makes based on the DayState. That's one of the things I need to work on. For setting the background colour on a work day, here are some work arounds:

  • Use a DataTrigger to set all the [DayState]BackgroundColor properties of the DayView to the colour you want based on a Binding
  • Inherit from DayView and add an IsCustom bindable property and then override the UpdateView method to not do anything if IsCustom is set to true.
  • Create your own view to consume the CalendarDay and use that in the DayTemplate instead of a DayView.

@ME-MarvinE ME-MarvinE added the enhancement New feature or request label Feb 9, 2023
@ME-MarvinE ME-MarvinE changed the title passing DateTime of a day in viewmodel to make more control for background changing Passing DateTime of a day in viewmodel to make more control for background changing Mar 17, 2023
@ME-MarvinE
Copy link
Owner

ME-MarvinE commented Sep 5, 2023

DayViews can now be customised using styles for each DayState instead of individual properties, for example CurrentMonthStyle.

Default functionality can now be replicated by using a markup reference to set the BasedOn property of your style to a style defined in Xamarin.[Forms/Maui].DefaultStyles. More info in the DayView wiki page.

There is now an easy way to override the changes that the DayView makes based on the DayState.DayViews: set the [DayState]Style property to null, for example `DayViewOtherMonthStyle="{x:Null}".

Your "IsWorkDay" property would go in the class that inherits from CalendarDay or implements ICalendarDay and then you would use the above methods to override the default colours while still getting the default look for everything else.

Did this solve your issue?

@ME-MarvinE ME-MarvinE added the awaiting-author Awaiting a respose from the author label Sep 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting-author Awaiting a respose from the author enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants