ME-MarvinE / XCalendar

A plugin for .NET providing an API for representing a calendar along with fully customisable calendar controls for Xamarin Forms and .NET MAUI
MIT License
299 stars 36 forks source link

XCalendar.Maui 4.4.2 works when debugging, crashes at startup when installed on android phone #136

Closed EugenM88 closed 9 months ago

EugenM88 commented 1 year ago

Greetings!

After successfully implementing this amazing control and trying to test it on my phone (Realme 8 Pro with Android 13) The program crashes at startup after installation.

The program works just fine in the emulator when debugging, but when changing to release and trying to manually install the app into my android phone, the program installs fine, however when starting the program up, the .net maui splashscreen appears and then app instantly crashes without any error.

I have tried using a clean project from scratch, same problem persists. Is there any tip or anything i could do to make it run on a android phone?

Devices and OS Versions: Realme 8 Pro: Android 13: Windows Version: 11 Pro, 22h2 (custom built pc) Visual Studio 2022 17.6.1 .NET 7

Thanks in advance for all your help!

ME-MarvinE commented 1 year ago

May be related to #67.

  1. What device are you using in your emulator?
  2. What happens when you try to run the MAUI app on your Windows Machine (Debug and Release)?
  3. What code did you have in your clean project from scratch?
  4. Are you able to run your app on your Android device in debug mode instead of release mode?
  5. Are you able to run your app if you remove the use of any XCalendar controls such as CalendarView or MonthView?*
  6. Are you able to run your app if you remove XCalendar?
  7. Are you able to run a file new MAUI app without XCalendar on your Android device (Debug and Release)?
  8. Are you able to run a file new MAUI app with XCalendar.MAUI but not using any controls from it on your Android Device (Debug and Release)?
  9. Are you able to run the sample app on your Android device (Debug and Release)?
EugenM88 commented 1 year ago

Greetings, to make this debugging easier, i have uploaded a test project to a zip file on wetransfer. You can find it here by clicking this link

As to reply to your questions 1) The device in the emulator is the default android device (Pixel 5 API 33 i think this is the default) 2) I never tried to run in Windows Machine as i need to change some code behind to be able to do so, i only used the android emulator to debug and a physical Realme 8 Pro device to test when released. 3) The code i had from scratch was just the default .net Maui Code + the xcalendar code, a few more lines in the csproj file to accomodate a key to publish the .apk file, a models folder with a model.cs class inside where the xcalendar has its binded data and thats about it. 4) I have never tried it in debug, i tought you werent able to do so in .net Maui as it wont even install if i try as it says its not compatible with my phone. 5 and 6) Once i add the XCalendar to the project, even after removing it from said project by removing all the lines of codes and uninstalling the nuget package, still, i can no longer run the published apk. 7) Yes as long as i do not ever reference XCalendar i am able to run the released apk (debug is not compatible with my arm device). 8) No. 9) I have never tried it as i couldnt build the sample Xcalendar app.

NOTE: This information might be important, in order to sign the apk, i use the terminal with the following guide: In terminal VS2022

keytool -genkey -v -keystore key.keystore -alias ProjectAlias -keyalg RSA -keysize 2048 -validity 10000 Password: passwordsomething153 FirstName Eugen LastName Systems

In MainProject programming class (example open file explorer go inside project folder and find NewMauiApp1.csproj), add before last line

True key.keystore passwordsomething153 ProjectAlias passwordsomething153

Please dont hesitate to contact me for further details as i am very new to .net MAUI and this is actually my very first .net MAUI project that im trying to build.

Best Regards!

ME-MarvinE commented 1 year ago

I am able to run your project in debug mode but not release mode. In release mode I get these errors: image

They don't seem to be related to XCalendar but I have yet to do actual testing by removing XCalendar from the project etc.

I have no experience with using the terminal to sign the apk. I've only ever signed APK and provided keystore details in Xamarin but in MAUI it seems to be the same: Project (NetMauiApp1) -> Properties -> Android -> Package Signing and then right clicking Project (NetMauiApp1) and clicking "publish" and then selecting the resulting archive and clicking "Distribute" and entering the keystore details there.

I've never seen someone experiencing your answer to Q4. It may provide insight into why your app crashes in release. What is the exact error message that says it isn't compatible with your phone? If it's your app that isn't compatible then it would make sense it doesn't work in release, but if debugging isn't compatible then that needs to be troubleshooted as to why. I just don't see how debugging wouldn't be supported on a standard Android 13 device. I assume you have the developer options enabled and the "USB Debugging" setting enabled. I see the Release package format is set to "Bundle" instead of "Apk" in the project so I don't even know how an APK would be genereated.

For your answer to Q3, could you create a new project and not include the code to do with publishing and see if it works first, then add the publishing details to see if that is causing yor issue.

It seems like you're generating an APK and installing it manually on your Android device, which is where you would get the "App is incompatible" error. The app should automatically be deployed onto your device whether in debug or release and you shouldn't have to manually do anything other than open the resulting app. If you install the app manually on your device then it makes sense why it would work in the emulator but not in your physical device. When you generate your APK how do you actually get it to your device? Could you provide steps if it isn't just: Run in release -> Go to Android device -> run app?

Im unable to understand your answer to Q5 ad Q6

4. I have never tried it in debug, i tought you werent able to do so in .net Maui as it wont even install if i try as it says its not compatible with my phone.
   5 and 6) Once i add the XCalendar to the project, even after removing it from said project by removing all the lines of codes and uninstalling the nuget package, still, i can no longer run the published apk.

5. Yes as long as i do not ever reference XCalendar I am able to run the released apk (debug is not compatible with my arm device).

6. No.

Your answer to Q4 where it says "5 and 6)" seems to contradict your answer to Q5. I understand that you created a new project which worked initially. Then you added XCalendar and then removed it and it never worked afterwards. I've never seen this before either. What happens when you add and remove other nuget packages that add MAUI controls? Can you try at least 2 others one at a time and see if you get the same result? I think I see that Q4 "5 and 6)" refers to Q5 and Q6 and then your answers to Q5, Q6, and Q7 are actually your aswers to Q7, Q8, and Q9.

From what I've seen I think this issue is caused by how you build and deploy your app to your device rather than by XCalendar, but it is weird that installing it and removing it will permanently stop your app from running. Does this happen if you install other packages that add MAUI controls?

EugenM88 commented 1 year ago

Sorry for the confusion with the point numbering there.... For some reason github changes the numbers automatically of each point, go figure.

I can "publish" an apk without using any key or any commands from the terminal but then it wont be compatible with my phone as the apk is not published "properly". It's probably because the android emulator is running in a x86_x64 cpu and my phone is actually arm.

What i wanted to achieve was actually very simple, i want to make an .apk file that i can manually copy to my phone internal storage and then the user installs said apk from its mobile phone internal memory (Not Google Play Store). I do not intend to debug the app with adb, or debug it directly from visual studio, i want to check how the app actually behaves when published and installed in a non dev phone, which is where it actually crashes after xecalendar is referenced.

All tutorials i've found online shows me that i must sign the android apk with the keytool in order for me to actually be able to generate a proper apk that can install and run in any phone.

Is there perhaps something wrong with my process or maybe im missing something?

ME-MarvinE commented 1 year ago

I don't know the difference between ARM and the architecure of your emulator and its implications. What do you mean it's not compatible with your phone? At what point do you get a warning or error when you don't publish the app using your method?

Have you tried the below method for generating a signed apk? I think it's an alternative to using the terminal.

I have no experience with using the terminal to sign the apk. I've only ever signed APK and provided keystore details in Xamarin but in MAUI it seems to be the same: Project (NetMauiApp1) -> Properties -> Android -> Package Signing and then right clicking Project (NetMauiApp1) and clicking "publish" and then selecting the resulting archive and clicking "Distribute" and entering the keystore details there.

What result did you get from this:

it is weird that installing it and removing it will permanently stop your app from running. Does this happen if you install other packages that add MAUI controls?

As far as I'm aware and in my experience you don't need to sign an apk to have it run on devices. I don't know why it doesn't let you install the app on your device. There are some security/developer settings such as "Install from unknown sources" which could prevent the user from installing your app though. I'm out of ideas as to what it could be.

In regards to:

Is there perhaps something wrong with my process or maybe im missing something?

I'm out of ideas and can only suggest to try with other packages or with other sample apps on GitHub to see if your apk-signing process works with them. If they do, then its an issue with XCalendar and I don't know why it would cause crashing after its been removed from the project. Maybe you could try to find someone else with a similar issue with their MAUI app, or raise an issue in the MAUI repo to get help from people with more knowledge of the Android OS and MAUI framework.

I would suggest Syncfusion's Calendar as an alternative while this issue is present.

EugenM88 commented 1 year ago

Hi there! Mr Marvin, I have created a new project to try to load the already generated key as per your instructions and i have attempted my best to find out a way to make it work when installed from the published apk to an android device, so far i have only been successfull in one scenario.

When using the newest release 4.5.1 (PS im very happy to see you still working on this wonderful project), using the following code on view and model MainPage.xaml (XAML)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App1.MainPage"
             xmlns:xc="clr-namespace:XCalendar.Maui.Views;assembly=XCalendar.Maui"
             xmlns:viewmodel="clr-namespace:App1.Models"
             xmlns:xcInterfaces="clr-namespace:XCalendar.Core.Interfaces;assembly=XCalendar.Core"
             x:DataType="viewmodel:MainPageModel">
    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />

            <Label
                Text="Hello, World!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />

            <Label
                Text="Welcome to .NET Multi-platform App UI"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                FontSize="18"
                HorizontalOptions="Center" />

            <Button
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                Clicked="OnCounterClicked"
                HorizontalOptions="Center" />

            <xc:CalendarView
                Background="LightGray"
                x:Name="MainCalendarView"
                BackwardsArrowCommand="{Binding NavigateCalendarCommand}"
                Days="{Binding Calendar.Days}"
                DaysOfWeek="{Binding Calendar.DayNamesOrder}"
                ForwardsArrowCommand="{Binding NavigateCalendarCommand}"
                NavigatedDate="{Binding Calendar.NavigatedDate}"
                Style="{StaticResource DefaultCalendarViewStyle}">

                <xc:CalendarView.ForwardsArrowCommandParameter>
                    <x:Int32>1</x:Int32>
                </xc:CalendarView.ForwardsArrowCommandParameter>

                <xc:CalendarView.BackwardsArrowCommandParameter>
                    <x:Int32>-1</x:Int32>
                </xc:CalendarView.BackwardsArrowCommandParameter>

                <xc:CalendarView.NavigationViewTemplate>
                    <ControlTemplate>
                        <xc:NavigationView
                            BackwardsArrowCommand="{Binding BackwardsArrowCommand, Source={RelativeSource TemplatedParent}}"
                            BackwardsArrowCommandParameter="{Binding BackwardsArrowCommandParameter, Source={RelativeSource TemplatedParent}}"
                            ForwardsArrowCommand="{Binding ForwardsArrowCommand, Source={RelativeSource TemplatedParent}}"
                            ForwardsArrowCommandParameter="{Binding ForwardsArrowCommandParameter, Source={RelativeSource TemplatedParent}}"
                            Style="{StaticResource DefaultNavigationViewStyle}"
                            Text="{Binding Text, Source={RelativeSource TemplatedParent}}"/>
                    </ControlTemplate>
                </xc:CalendarView.NavigationViewTemplate>

                <!--  Not Required, used only for styling.  -->
                <xc:CalendarView.DayTemplate>
                    <DataTemplate x:DataType="{x:Type xcInterfaces:ICalendarDay}">
                        <Border Margin="2.5" BackgroundColor="Transparent">

                            <Border.StrokeShape>
                                <RoundRectangle CornerRadius="100"/>
                            </Border.StrokeShape>

                            <xc:DayView
                                DateTime="{Binding DateTime}"
                                InvalidStyle="{StaticResource DefaultDayViewInvalidStyle}"
                                IsCurrentMonth="{Binding IsCurrentMonth}"
                                IsInvalid="{Binding IsInvalid}"
                                IsSelected="{Binding IsSelected}"
                                IsToday="{Binding IsToday}"
                                OtherMonthStyle="{StaticResource DefaultDayViewOtherMonthStyle}">

                                <xc:DayView.CurrentMonthStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewCurrentMonthStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.CurrentMonthStyle>

                                <xc:DayView.TodayStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewTodayStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.TodayStyle>

                                <xc:DayView.SelectedStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewSelectedStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.SelectedStyle>

                            </xc:DayView>
                        </Border>
                    </DataTemplate>
                </xc:CalendarView.DayTemplate>

            </xc:CalendarView>

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

Code Behind MainPage.xaml.cs

using App1.Models;
using XCalendar.Core.Models;

namespace App1;

public partial class MainPage : ContentPage
{
    int count = 0;
    public MainPageModel modelToUse = new MainPageModel();
    public MainPage()
    {
        BindingContext = modelToUse;
        InitializeComponent();
    }

    public Calendar<CalendarDay> MyCalendar { get; set; } = new Calendar<CalendarDay>();
    private void OnCounterClicked(object sender, EventArgs e)
    {
        count++;

        if (count == 1)
            CounterBtn.Text = $"Clicked {count} time";
        else
            CounterBtn.Text = $"Clicked {count} times";

        SemanticScreenReader.Announce(CounterBtn.Text);
    }
}

And using this code on the ViewModel MainPageModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using XCalendar.Core.Enums;
using XCalendar.Core.Extensions;
using XCalendar.Core.Models;

namespace App1.Models
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        internal MainPage masterWindow = null;

        #region Properties
        public List<string> CommonFunctionalities { get; } = new List<string>()
        {
            "None",
            "Single",
            "Multiple",
            "Range"
        };
        public Calendar<CalendarDay> Calendar { get; set; } = new Calendar<CalendarDay>()
        {
            SelectionType = SelectionType.Single,
            SelectionAction = SelectionAction.Replace
        };
        #endregion

        #region Commands
        public ICommand ShowSelectionTypeDialogCommand { get; set; }
        public ICommand ShowSelectionActionDialogCommand { get; set; }
        public ICommand ShowCommonFunctionalityDialogCommand { get; set; }
        public ICommand NavigateCalendarCommand { get; set; }
        public ICommand ChangeDateSelectionCommand { get; set; }

        #endregion

        #region Constructors
        public MainPageModel()
        {
            ShowSelectionTypeDialogCommand = new Command(ShowSelectionTypeDialog);
            ShowSelectionActionDialogCommand = new Command(ShowSelectionActionDialog);
            ShowCommonFunctionalityDialogCommand = new Command(ShowCommonFunctionalityDialog);
            NavigateCalendarCommand = new Command<int>(NavigateCalendar);
            ChangeDateSelectionCommand = new Command<DateTime>(ChangeDateSelection);
            Calendar.SelectionType = SelectionType.Single;
            Calendar.SelectionAction = SelectionAction.Replace;
        }
        #endregion

        #region Methods
        public async void ShowSelectionTypeDialog()
        {
            //Calendar.SelectionType = await PopupHelper.ShowSelectItemDialogAsync(Calendar.SelectionType, PopupHelper.AllSelectionTypes);
        }
        public async void ShowSelectionActionDialog()
        {
            //Calendar.SelectionAction = await PopupHelper.ShowSelectItemDialogAsync(Calendar.SelectionAction, PopupHelper.AllSelectionActions);
        }
        public async void ShowCommonFunctionalityDialog()
        {
            /*string commonFunctionality = await PopupHelper.ShowSelectItemDialogAsync(CommonFunctionalities[1], CommonFunctionalities);

            switch (commonFunctionality)
            {
                case "None":
                    Calendar.SelectionType = SelectionType.None;
                    break;

                case "Single":
                    Calendar.SelectionType = SelectionType.Single;
                    Calendar.SelectionAction = SelectionAction.Replace;
                    break;

                case "Multiple":
                    Calendar.SelectionType = SelectionType.Single;
                    Calendar.SelectionAction = SelectionAction.Modify;
                    break;

                case "Range":
                    Calendar.SelectionType = SelectionType.Range;
                    Calendar.SelectionAction = SelectionAction.Replace;
                    break;
            }*/
        }
        public void NavigateCalendar(int amount)
        {
            if (Calendar.NavigatedDate.TryAddMonths(amount, out DateTime targetDate))
            {
                Calendar.Navigate(targetDate - Calendar.NavigatedDate);
            }
            else
            {
                Calendar.Navigate(amount > 0 ? TimeSpan.MaxValue : TimeSpan.MinValue);
            }
        }
        public void ChangeDateSelection(DateTime dateTime)
        {
            Calendar?.ChangeDateSelection(dateTime);
        }
        #endregion
    }
}

Using the above code, the project builds fine and works fine in debug mode in android emulator, but still i am unable to run on my android device after installing, as usual the app crashes at the splashscreen.

However, if i change both codes of the view and model to this: MainPage.xaml (XAML)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App1.MainPage"
             xmlns:xc="clr-namespace:XCalendar.Maui.Views;assembly=XCalendar.Maui"
             xmlns:viewmodel="clr-namespace:App1.Models"
             x:DataType="viewmodel:MainPageModel">
    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />

            <Label
                Text="Hello, World!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />

            <Label
                Text="Welcome to .NET Multi-platform App UI"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                FontSize="18"
                HorizontalOptions="Center" />

            <Button
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                Clicked="OnCounterClicked"
                HorizontalOptions="Center" />

            <xc:CalendarView
            BackgroundColor="LightGray"
            BackwardsArrowCommand="{Binding NavigateCalendarCommand}"
            Days="{Binding MyCalendar.Days}"
            DaysOfWeek="{Binding MyCalendar.DayNamesOrder}"
            ForwardsArrowCommand="{Binding NavigateCalendarCommand}"
            NavigatedDate="{Binding MyCalendar.NavigatedDate}">

                <xc:CalendarView.ForwardsArrowCommandParameter>
                    <x:Int32>1</x:Int32>
                </xc:CalendarView.ForwardsArrowCommandParameter>

                <xc:CalendarView.BackwardsArrowCommandParameter>
                    <x:Int32>-1</x:Int32>
                </xc:CalendarView.BackwardsArrowCommandParameter>

            </xc:CalendarView>

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

Code Behind MainPage.xaml.cs (Same code, no point in duplicating)

And using this code on the ViewModel MainPageModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using XCalendar.Core.Enums;
using XCalendar.Core.Models;

namespace App1.Models
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        internal MainPage masterWindow = null;

        public void OnPropertyChanged([CallerMemberName] string propertyName = null) => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        #region Properties
        public Calendar<CalendarDay> MyCalendar { get; set; } = new Calendar<CalendarDay>()
        {
            SelectionType = SelectionType.Single,
            StartOfWeek = DayOfWeek.Monday,
            SelectionAction = SelectionAction.Replace,
            //DayNamesOrder = new XCalendar.Core.Collections.ObservableRangeCollection<DayOfWeek>() { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday },
        };
        #endregion

        #region Commands
        public ICommand ShowSelectionTypeDialogCommand { get; set; }
        public ICommand ShowSelectionActionDialogCommand { get; set; }
        public ICommand ShowCommonFunctionalityDialogCommand { get; set; }
        public ICommand NavigateCalendarCommand { get; set; }
        public ICommand ChangeDateSelectionCommand { get; set; }

        #endregion

        #region Constructors

        #endregion

        #region Methods
        public async void ShowSelectionTypeDialog()
        {
            MyCalendar.SelectionType = SelectionType.Single;
        }
        public async void ShowSelectionActionDialog()
        {
            MyCalendar.SelectionAction = SelectionAction.Add;
        }
        public async void ShowCommonFunctionalityDialog()
        {
            MyCalendar.SelectionType = SelectionType.Single;
            MyCalendar.SelectionAction = SelectionAction.Modify;
        }
        public void ChangeDateSelection(DateTime dateTime)
        {
            MyCalendar?.ChangeDateSelection(dateTime);
        }
        #endregion

        public MainPageModel()
        {
            ShowSelectionTypeDialogCommand = new Command(ShowSelectionTypeDialog);
            ShowSelectionActionDialogCommand = new Command(ShowSelectionActionDialog);
            ShowCommonFunctionalityDialogCommand = new Command(ShowCommonFunctionalityDialog);
            ChangeDateSelectionCommand = new Command<DateTime>(ChangeDateSelection);
        }
    }
}

It builds fine, works fine in emulator and even the published apk installs fine on the phone and displays without crashing! Im not sure how to be able to change the months and arrows colors and select different dates using the new 4.5.1 calendar version with the working code, as of right now the working example doesnt allow the user to interact with the control at all.

PS: Meanwhile, if there is anything else i can do to help you out, please feel free to ask, i will do whatever i can with my very limited experience in .net maui.

EugenM88 commented 1 year ago

In addition to the last post i made a few mins ago...

Im not sure if this is of any interest as im not even sure if it's actually accurate information, but, perhaps .net maui no longer uses relaycommands and probably replaced it with something newer?

Again i have really no experience with .net maui and this is my first ever project with it, so take this specific info with a grain of salt.

ME-MarvinE commented 1 year ago

Will look at this again, great debugging

ME-MarvinE commented 1 year ago

Running first set of code

Issue 1

image

Solution

Remove Style="{StaticResource DefaultCalendarViewStyle}" from

            <xc:CalendarView
                Background="LightGray"
                x:Name="MainCalendarView"
                BackwardsArrowCommand="{Binding NavigateCalendarCommand}"
                Days="{Binding Calendar.Days}"
                DaysOfWeek="{Binding Calendar.DayNamesOrder}"
                ForwardsArrowCommand="{Binding NavigateCalendarCommand}"
                NavigatedDate="{Binding Calendar.NavigatedDate}"
                Style="{StaticResource DefaultCalendarViewStyle}">

Issue 2

image

Solution

Remove Style="{StaticResource DefaultNavigationViewStyle}" from

                <xc:CalendarView.NavigationViewTemplate>
                    <ControlTemplate>
                        <xc:NavigationView
                            BackwardsArrowCommand="{Binding BackwardsArrowCommand, Source={RelativeSource TemplatedParent}}"
                            BackwardsArrowCommandParameter="{Binding BackwardsArrowCommandParameter, Source={RelativeSource TemplatedParent}}"
                            ForwardsArrowCommand="{Binding ForwardsArrowCommand, Source={RelativeSource TemplatedParent}}"
                            ForwardsArrowCommandParameter="{Binding ForwardsArrowCommandParameter, Source={RelativeSource TemplatedParent}}"
                            Style="{StaticResource DefaultNavigationViewStyle}"
                            Text="{Binding Text, Source={RelativeSource TemplatedParent}}"/>
                    </ControlTemplate>
                </xc:CalendarView.NavigationViewTemplate>

Issue 3

The StaticResources "DefaultDayViewCurrentMonthStyle", "DefaultDayViewTodayStyle", and "DefaultDayViewSelectedStyle" are used in the following code but are not defined:

                                <xc:DayView.CurrentMonthStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewCurrentMonthStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.CurrentMonthStyle>

                                <xc:DayView.TodayStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewTodayStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.TodayStyle>

                                <xc:DayView.SelectedStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewSelectedStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.SelectedStyle>

Solution

Either don't set "BasedOn", or if you want to use the default look of the DayView, replace them with the values in the XCalendar.Maui.DefaultStyles class. For example:

                                <xc:DayView.CurrentMonthStyle>
                                    <Style BasedOn="{x:Static xcStyles:DefaultStyles.DefaultDayViewCurrentMonthStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.CurrentMonthStyle>

Where xcStyles is defined earlier in the view: xmlns:xcStyles="clr-namespace:XCalendar.Maui.Styles;assembly=XCalendar.Maui"

Looking at second set of code:

Issues from your first set of code also apply and will not be ammended in the solutions provided.

Issue 1

It builds fine, works fine in emulator and even the published apk installs fine on the phone and displays without crashing! Im not sure how to be able to change the months and arrows colors and select different dates using the new 4.5.1 calendar version with the working code, as of right now the working example doesnt allow the user to interact with the control at all.

You have defined the DateSelectionCommand but you have not assigned it to the days in your Calendar in XAML like you did in your first example. The day is being tapped but non of the states know that you want to use that command:

                                <xc:DayView.CurrentMonthStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewCurrentMonthStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.CurrentMonthStyle>

                                <xc:DayView.TodayStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewTodayStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.TodayStyle>

                                <xc:DayView.SelectedStyle>
                                    <Style BasedOn="{StaticResource DefaultDayViewSelectedStyle}" TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.SelectedStyle>

Solution

The following code sets the command to use when a day is tapped and is in the CurrentMonth DayState. The page is given x:Name="This" so the page's BindingContext can be accessed inside the DataTemplate.

                                <xc:DayView.CurrentMonthStyle>
                                    <Style TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.CurrentMonthStyle>

It really is valuable testing with a debugger first to see the errors that cause your app to crash. After that you can delete the app and test without the debugger like you do currently. With XAML there can be many runtime errors so I think its essential that you find out why you're not able to run apps in debug mode on your phone, especially if you're want to use more complex XAML or nuget packages. Are you able to run in debug mode in your emulator instead?

I don't know why it worked fine in your emulator as the app still should have crashed/thrown an exception because of the afformentioned issues.

Thanks for doing tests and posting what did and didn't work. Made it much easier to spot the difference.

EugenM88 commented 1 year ago

Hello, sorry for the delay i have been really busy these days and couldnt test your answear untill today.

Thank you very much for your reply, great news! It semms to be working just fine now, it builds ok and no longer crashes on my phone when manually deployed and installed from an apk, however now im confused on how to get the last part working, namely i dont know where to put this code:

<xc:DayView.CurrentMonthStyle>
                                    <Style TargetType="{x:Type xc:DayView}">
                                        <Setter Property="Command" Value="{Binding BindingContext.ChangeDateSelectionCommand, Source={x:Reference This}}"/>
                                        <Setter Property="CommandParameter" Value="{Binding DateTime}"/>
                                    </Style>
                                </xc:DayView.CurrentMonthStyle>

Is there a chance you could help me out make this work on 4.5.1, example: to be able to change months and click on specific days? I dont know why but im struggling really hard with the documentation, even though it should be as simple as a copy and paste.

Once more thank you for your time!

ME-MarvinE commented 1 year ago

Stuff from the sample app is almost copy paste but at least a little knowledge is required to recognise what resources that were used need to be removed or replicated in your app like Styles or x:Name or nuget packages. Things can also be done in many ways, and the way I have done it may not always suite your needs.

Anyway, if you want to move the month and be able to select days, I recommend looking at the "Date Selection" example in the sample app.

The <xc:DayView.CurrentMonthStyle> would go in the DayView that you put inside the DataTemplate that you put inside the <xc:CalendarView.DayTemplate>. This usage is present in many of the examples in the sample app.