CommunityToolkit / Maui

The .NET MAUI Community Toolkit is a community-created library that contains .NET MAUI Extensions, Advanced UI/UX Controls, and Behaviors to help make your life as a .NET MAUI developer easier
https://learn.microsoft.com/dotnet/communitytoolkit/maui
MIT License
2.27k stars 401 forks source link

[BUG] No parameterless constructor defined for type 'CommunityToolkit.Maui.Views.MediaElement' #2303

Closed khambley closed 2 weeks ago

khambley commented 2 weeks ago

Is there an existing issue for this?

Did you read the "Reporting a bug" section on Contributing file?

Current Behavior

I have a .NET MAUI project that uses two Media Elements on a Splash Screen Page inside a Grid. Ever since I upgraded to 4.1.1 and then to 4.1.2 I've been getting the following error and the app crashes on iOS: Microsoft.Maui.Controls.Xaml.XamlParseException: Position 11:14. No parameterless constructor defined for type 'CommunityToolkit.Maui.Views.MediaElement'. ---> System.MissingMethodException: No parameterless constructor defined for type 'CommunityToolkit.Maui.Views.MediaElement'. at at System.RuntimeType.CreateInstanceMono(Boolean , Boolean ) at at System.RuntimeType.CreateInstanceDefaultCtor(Boolean , Boolean ) at at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions) at at System.Activator.CreateInstance(Type type, Boolean nonPublic) at at System.Activator.CreateInstance(Type type) at at Microsoft.Maui.Controls.Xaml.CreateValuesVisitor.Visit(ElementNode node, INode parentNode) --- End of inner exception stack trace --- at at Microsoft.Maui.Controls.Xaml.CreateValuesVisitor.Visit(ElementNode node, INode parentNode) at at Microsoft.Maui.Controls.Xaml.ElementNode.Accept(IXamlNodeVisitor visitor, INode parentNode) at at Microsoft.Maui.Controls.Xaml.ElementNode.Accept(IXamlNodeVisitor visitor, INode parentNode) at at Microsoft.Maui.Controls.Xaml.RootNode.Accept(IXamlNodeVisitor visitor, INode parentNode) at at Microsoft.Maui.Controls.Xaml.XamlLoader.Visit(RootNode rootnode, HydrationContext visitorContext, Boolean useDesignProperties) at at Microsoft.Maui.Controls.Xaml.XamlLoader.Load(Object view, String xaml, Assembly rootAssembly, Boolean useDesignProperties) at at Microsoft.Maui.Controls.Xaml.XamlLoader.Load(Object view, String xaml, Boolean useDesignProperties) at at Microsoft.Maui.Controls.Xaml.XamlLoader.Load(Object view, Type callingType) at at Microsoft.Maui.Controls.Xaml.Extensions.LoadFromXaml[SplashScreenPage](SplashScreenPage view, Type callingType) at EconomyNow.Views.XAML.SplashScreenPage.InitializeComponent() in /Users/f1kxh05/Projects/EconomyNow/MAUI/obj/Debug/net8.0-ios/ios-arm64/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/Views_XAML_SplashScreenPage.xaml.sg.cs:38 at EconomyNow.Views.XAML.SplashScreenPage..ctor() in /Users/f1kxh05/Projects/EconomyNow/MAUI/Views/XAML/SplashScreenPage.xaml.cs:10 at EconomyNow.App..ctor() in /Users/f1kxh05/Projects/EconomyNow/MAUI/App.xaml.cs:18 at at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Constructor(Object obj, IntPtr* args) at at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object , BindingFlags ) at at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags , Binder , Object[] , CultureInfo ) at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite , RuntimeResolverContext ) at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite , RuntimeResolverContext ) at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite , RuntimeResolverContext ) at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, RuntimeResolverContext argument) at at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite , ServiceProviderEngineScope ) at at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier serviceIdentifier) at at System.Collections.Concurrent.ConcurrentDictionary2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceIdentifier, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.Extensions.DependencyInjection.ServiceProvider.ServiceAccessor, Microsoft.Extensions.DependencyInjection, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].GetOrAdd(ServiceIdentifier , Func2 ) at at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier , ServiceProviderEngineScope ) at at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type ) at at Microsoft.Maui.MauiContext.WrappedServiceProvider.GetService(Type serviceType) at at Microsoft.Maui.MauiContext.WrappedServiceProvider.GetService(Type serviceType) at at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider , Type ) at at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[IApplication](IServiceProvider ) at at Microsoft.Maui.MauiUIApplicationDelegate.FinishedLaunching(UIApplication application, NSDictionary launchOptions) at UIKit.UIApplication.UIApplicationMain(Int32 , String[] , IntPtr , IntPtr ) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:61 at UIKit.UIApplication.Main(String[] , Type , Type ) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:96 at EconomyNow.Program.Main(String[] args) in /Users/f1kxh05/Projects/EconomyNow/MAUI/Platforms/iOS/Program.cs:13

My XAML page

<?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"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="EconomyNow.Views.XAML.SplashScreenPage"
             Unloaded="ContentPage_Unloaded">
    <Grid>
        <toolkit:MediaElement x:Name="mediaElement"
                                ShouldAutoPlay="True"
                                MediaEnded="OnMediaEnded"
                                VerticalOptions="Fill"
                                HorizontalOptions="Fill"
                                Scale="1.5" />

        <toolkit:MediaElement x:Name="mediaElement2"
                                ShouldAutoPlay="False"
                                ShouldShowPlaybackControls="True"
                                MediaEnded="mediaElement2_MediaEnded" />

        <Button x:Name="getStartedButton"
            Text="Get Started"
            BackgroundColor="#428bca"
            TextColor="White"
            WidthRequest="200"
            VerticalOptions="End"
            HorizontalOptions="Center"
            Clicked="Handle_Clicked" ></Button>

        <ActivityIndicator x:Name="spinner"
                            Color="White"
                            VerticalOptions="End"
                            HorizontalOptions="Center" />

    </Grid>

My code-behind

using System.Collections.ObjectModel;
using CommunityToolkit.Maui.Views;

namespace EconomyNow.Views.XAML;

public partial class SplashScreenPage : ContentPage
{
    public SplashScreenPage()
    {
        InitializeComponent();
        //BindingContext = new CarouselViewModel();
        mediaElement2.IsVisible = false;
        getStartedButton.IsVisible = false;

        PlaySplashVideo();

        if (VersionTracking.Default.IsFirstLaunchEver)
        {
            PlayOnboardingVideo();
        }       
        spinner.IsRunning = false;
        spinner.IsVisible = false;

    }

    private void PlaySplashVideo()
    {
        mediaElement.Source = MediaSource.FromResource("Videos/splashanimation.mp4");
    }

    private void PlayOnboardingVideo()
    {
        mediaElement2.Source = MediaSource.FromResource("Videos/onboardingvideo1.mp4");
    }

    void ContentPage_Unloaded(System.Object sender, System.EventArgs e)
    {
        // Stop and cleanup MediaElement when we navigate away
        //mediaElement.Handler?.DisconnectHandler();
    }

    private async void OnMediaEnded(object sender, EventArgs e)
    {
        if (VersionTracking.Default.IsFirstLaunchEver)
        {
            mediaElement.IsVisible = false;
            mediaElement2.Play();
            mediaElement2.IsVisible = true;
            getStartedButton.IsVisible = true;
        }
        else
        {
            Application.Current.MainPage = new AppShell();
        }

    }

    void mediaElement2_MediaEnded(System.Object sender, System.EventArgs e)
    {
        //Application.Current.MainPage = new AppShell();
    }
    void Handle_Clicked(object sender, System.EventArgs e)
    {
        spinner.IsRunning = true;
        spinner.IsVisible = true;

        //Application.Current.MainPage = new AppShell();
        Application.Current.MainPage = new PushNotificationsPage();
        spinner.IsRunning = false;
        spinner.IsVisible = false;

        //if (Device.RuntimePlatform == Device.iOS)
        //{
        //    Application.Current.MainPage = new PushNotificationsPage();
        //}
    }
}

Expected Behavior

App should load the Splash Screen media elements, no crashes

Steps To Reproduce

Add media elements to XAML page, add Source to each media element, call in code-behind.

Link to public reproduction project repository

https://github.com/khambley/maui-media-element-bug-demo

Environment

Anything else?

No response

brminnick commented 2 weeks ago

Please update your local environment to use the latest required versions:

global.json


{
  "sdk": {
    "version": "8.0.403", 
    "rollForward": "latestMajor",
    "allowPrerelease": false
  }
}
khambley commented 2 weeks ago

I followed all the steps above and it worked! Thank you! One question, will I have to update the global.json file every time a major version is released? or will it know to grab any version after 8.0.403?

khambley commented 2 weeks ago

It will not build on Mac OS Sonoma 14.7 and the simulators are not available in VS / VS Code. "Lower the deployment target to see older simulators or check your Apple SDK path" It built and worked on a physical device on Mac OS Sonoma 14.5