Updated to Telerik.UI.for.Maui v6.0 and get errors when display some popups

0 Answers 520 Views
Popup
Stephen
Top achievements
Rank 1
Iron
Iron
Stephen asked on 23 Jul 2023, 06:05 PM | edited on 23 Jul 2023, 06:08 PM

I updated the version of the Telerik controls from 5.0.1 to 6.0.0 and some popups have started to throw errors. The odd thing is that not all popups throw this exception...

In my formatted log (using NLog) I see this when I try to open a certain popup. This popup worked just minutes prior to the upgrade as I added some functionality to it. As soon as I upgraded to 6.0, it bombs...

----------------------------------
2023-07-23 10:15:41.4515 ERROR 
  Call site:         MauiProgram.FirstChanceException
  Method name:       MobyClient.MauiProgram.FirstChanceException
  Line:              0
  Exception Type:    System.Runtime.InteropServices.COMException
  Exception Message: No installed components were detected.

  Stack Trace:       at WinRT.DelegateExtensions.DynamicInvokeAbi(Delegate del, Object[] invoke_params)
   at WinRT.DelegateExtensions.DynamicInvokeAbi(Delegate del, Object[] invoke_params)
   at ABI.System.Collections.Generic.IVectorMethods`1.Append(IObjectReference obj, T value)
   at Microsoft.Maui.Handlers.ViewHandler`2.SetupContainer()
   at Microsoft.Maui.Handlers.LabelHandler.SetupContainer()
   at Microsoft.Maui.Handlers.LabelHandler.MapBackground(ILabelHandler handler, ILabel label)
   at Microsoft.Maui.Controls.Element.OnPropertyChanged(String propertyName)
   at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent)
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
   at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
   at Microsoft.Maui.Controls.Setter.Apply(BindableObject target, Boolean fromStyle)
   at Microsoft.Maui.Controls.Style.ApplyCore(BindableObject bindable, Style basedOn)
   at Microsoft.Maui.Controls.Style.Microsoft.Maui.Controls.IStyle.Apply(BindableObject bindable)
   at Microsoft.Maui.Controls.MergedStyle.SetStyle(IStyle implicitStyle, IList`1 classStyles, IStyle style)
   at Microsoft.Maui.Controls.MergedStyle.OnImplicitStyleChanged()
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
   at Microsoft.Maui.Controls.Element.OnResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.VisualElement.OnParentResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.Element.OnResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.VisualElement.OnParentResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.Element.OnResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.VisualElement.OnParentResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.Element.OnResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.VisualElement.OnParentResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.Element.OnResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.VisualElement.OnParentResourcesChanged(IEnumerable`1 values)
   at Microsoft.Maui.Controls.Element.set_Parent(Element value)
   at Telerik.Maui.Controls.PopupBase.IsOpenPropertyChanged(Boolean oldValue, Boolean newValue)
   at Telerik.Maui.Controls.PopupBase.<>c.<.cctor>b__124_0(BindableObject b, Object o, Object n)
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
   at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
   at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
   at Telerik.Maui.Controls.PopupBase.set_IsOpen(Boolean value)
   at MobyClient.ViewModels.InvitationsViewModel.FindSomeone() in C:\Development\MobyNet\Dev\MobyClient\MobyClient\ViewModels\InvitationsViewModel.cs:line 121
   at CommunityToolkit.Mvvm.Input.RelayCommand.Execute(Object parameter)
   at Telerik.Maui.Controls.ButtonToolbarItemView.ExecuteCommand()
   at Telerik.Maui.Controls.ButtonToolbarItemView.OnClicked()
   at Telerik.Maui.Controls.ButtonToolbarItemView.Telerik.Maui.Controls.IToolStripClickableView.OnClicked()
   at Telerik.Maui.Controls.RadToolbar.OnContentTapped(Point touchLocation)
   at Telerik.Maui.Controls.RadToolbar.OnContentTapped(Object sender, ITouchLocation eventArgs)
   at Telerik.Maui.NativeGestureRecognizer.NativeView_Tapped(Object sender, TappedRoutedEventArgs e)
   at WinRT._EventSource_global__Microsoft_UI_Xaml_Input_TappedEventHandler.EventState.<GetEventInvoke>b__1_0(Object sender, TappedRoutedEventArgs e)
   at ABI.Microsoft.UI.Xaml.Input.TappedEventHandler.Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr e)

  Additional Info:   System.Runtime.InteropServices.COMException: No installed components were detected.

----------------------------------

The error message is horrible as it provides no additional context, so I have no idea what is missing!

Up until this morning, I had my NuGet package manager looking here https://api.nuget.org/v3/index.json and selected the new version. This is when the errors started. It was working just minutes prior when I was using 5.0.1. So, I downloaded the msi and installed it. That didn't fix it so I pointed my NuGet Telerik source to the local packages C:\Program Files\Telerik\Telerik_UI_for_Maui_600\Packages, found the 6.0 package and still no success. When I downgrade to 5.1 (not 5.0.1) it works...

I have a popup service that defines the popup that doesn't work as follows:

	public void InitializePopups () {

		if (_isInitialized) return;

		// Find someone popup.
		FindContactsViewModel = new FindContactsViewModel (_logger, _mobyConfigurationManager, this);

		var popupContent = (View) Application.Current.Resources["FindContactsPopup"];

		popupContent.BindingContext = FindContactsViewModel;

		FindSomeonePopup = new RadPopup {
			Content = popupContent,
			Placement = PlacementMode.Center
		};

		// Find someone results popup.
		FindContactsResultsViewModel = new FindContactsResultsViewModel (_logger, this);

		popupContent = (View) Application.Current.Resources["FindContactsResultsPopup"];

		popupContent.BindingContext = FindContactsResultsViewModel;

		FindSomeoneResultsPopup = new RadPopup {
			Content = popupContent,
			Placement = PlacementMode.Center
		};

		_logger.Debug ($"{GetType ().Name} is initialized.");

		_isInitialized = true;
	}

The xaml that I use for these two popups is:

            <!--
                Common Popups
            -->
            <!-- Find Contacts Popup -->
            <telerik:RadBorder
                x:DataType="viewModels:FindContactsViewModel"
                x:Key="FindContactsPopup"
                BackgroundColor="{StaticResource Background_Dark}"
                BorderColor="Lime"
                BorderThickness="1"
                CornerRadius="8"
                HorizontalOptions="Center"
                Padding="10"
                VerticalOptions="Start"
                WidthRequest="400">
                <Grid
                    RowDefinitions="*, Auto"
                    Margin="3">
                    <telerik:RadBorder
                        Grid.Row="0"
                        BackgroundColor="{StaticResource Background_Dark}"
                        BorderColor="White"
                        BorderThickness="1"
                        CornerRadius="8"
                        Padding="5"
                        VerticalOptions="Start">
                        <Grid
                            RowDefinitions="Auto, *"
                            Margin="3">
                            <Label
                                Grid.Row="0"
                                FontSize="16"
                                FontAttributes="Bold"
                                HorizontalOptions="Center"
                                Text="{x:Static strings:LabelResources.LabelFindContactsHeader}"
                                TextColor="White"
                                VerticalOptions="Start" />
                            <Editor
                                Grid.Row="1"
                                AutoSize="TextChanges"
                                BackgroundColor="White"
                                Margin="1,11,1,1"
                                Placeholder="{x:Static strings:LabelResources.PlaceholderEnterAddressesToFind}"
                                PlaceholderColor="Gray"
                                Text="{Binding FindSomeoneList}"
                                TextColor="Black"
                                VerticalOptions="Start" />
                        </Grid>
                    </telerik:RadBorder>
                    <HorizontalStackLayout
                        Grid.Row="1"
                        HorizontalOptions="End"
                        Margin="0,10,0,0"
                        VerticalOptions="End">
                        <telerik:RadButton
                            Command="{Binding ShowFindSomeoneResultsCommand}"
                            FontSize="14"
                            HeightRequest="40"
                            Text="{x:Static strings:LabelResources.LabelFind}"
                            WidthRequest="90" />
                        <telerik:RadButton
                            Command="{Binding CancelFindContactsCommand}"
                            FontSize="14"
                            HeightRequest="40"
                            Margin="8,0,0,0"
                            Text="{x:Static strings:LabelResources.LabelCancel}"
                            WidthRequest="90" />
                    </HorizontalStackLayout>
                </Grid>
            </telerik:RadBorder>
            <!-- Find Contacts Results Popup -->
            <telerik:RadBorder
                x:DataType="viewModels:FindContactsResultsViewModel"
                x:Key="FindContactsResultsPopup"
                BackgroundColor="{StaticResource Background_Dark}"
                BorderColor="Lime"
                BorderThickness="1"
                CornerRadius="8"
                HorizontalOptions="Center"
                Padding="10"
                VerticalOptions="Start"
                WidthRequest="400">
                <Grid
                    RowDefinitions="*, Auto"
                    Margin="3">
                    <telerik:RadBorder
                        Grid.Row="0"
                        BackgroundColor="{StaticResource Background_Dark}"
                        BorderColor="White"
                        BorderThickness="1"
                        CornerRadius="8"
                        Padding="5"
                        VerticalOptions="Start">
                        <Grid
                            RowDefinitions="Auto, *"
                            Margin="3">
                            <Label
                                Grid.Row="0"
                                FontSize="16"
                                FontAttributes="Bold"
                                HorizontalOptions="Center"
                                Text="{x:Static strings:LabelResources.LabelFindContactsResultsHeader}"
                                TextColor="White"
                                VerticalOptions="Start" />
                            <telerik:RadDataGrid
                                x:DataType="viewModels:FindContactsViewModel"
                                x:FieldModifier="Public"
                                x:Name="FindContactsDataGrid"
                                Grid.Row="1"
                                AutoGenerateColumns="False"
                                BackgroundColor="White"
                                CanUserReorderColumns="False"
                                CanUserResizeColumns="True"
                                CurrentCellStyle="{StaticResource CurrentCellStyle}"
                                GridLinesColor="LightGray"
                                GridLinesThickness="1"
                                GridLinesVisibility="Both"
                                GroupHeaderStyle="{StaticResource GroupHeaderStyle}"
                                HeightRequest="400"
                                ItemsSource="{Binding Contacts}"
                                Margin="1,11,1,1"
                                MouseHoverStyle="{StaticResource MouseHoverStyle}"
                                RowBackgroundStyle="{StaticResource RowBackgroundStyle}"
                                RowHeight="30"
                                SelectionMode="None"
                                SelectionStyle="{StaticResource SelectionStyle}"
                                SelectionUnit="Row"
                                ShowColumnFooters="False"
                                ShowGroupFooters="False"
                                ShowGroupHeaderAggregates="False"
                                UserEditMode="None"
                                UserFilterMode="Disabled"
                                UserGroupMode="Disabled"
                                UserSortMode="Multiple">
                                <telerik:RadDataGrid.Columns>
                                    <telerik:DataGridTextColumn
                                        CellContentStyle="{StaticResource CellContentStyle}"
                                        HeaderStyle="{StaticResource ColumHeaderStyle}"
                                        HeaderText="{x:Static strings:LabelResources.LabelContactId}"
                                        PropertyName="ContactId"
                                        SizeMode="Stretch" />
                                    <telerik:DataGridTextColumn
                                        CellContentStyle="{StaticResource CellContentStyle}"
                                        HeaderStyle="{StaticResource ColumHeaderStyle}"
                                        HeaderText="{x:Static strings:LabelResources.LabelMobyUser}"
                                        SizeMode="Auto">
                                        <telerik:DataGridTextColumn.CellContentTemplate>
                                            <DataTemplate>
                                                <Label
                                                    HorizontalOptions="Center"
                                                    Margin="0"
                                                    Padding="8,0,0,0"
                                                    Text="{Binding IsMobyUser, Converter={StaticResource BoolToString}, ConverterParameter='YesNo'}"
                                                    TextColor="Black"
                                                    VerticalOptions="Center" />
                                            </DataTemplate>
                                        </telerik:DataGridTextColumn.CellContentTemplate>
                                    </telerik:DataGridTextColumn>
                                </telerik:RadDataGrid.Columns>
                            </telerik:RadDataGrid>
                        </Grid>
                    </telerik:RadBorder>
                    <HorizontalStackLayout
                        Grid.Row="1"
                        HorizontalOptions="End"
                        Margin="0,10,0,0"
                        VerticalOptions="End">
                        <telerik:RadButton
                            Command="{Binding CloseFindContactsResultsCommand}"
                            FontSize="14"
                            HeightRequest="40"
                            Text="{x:Static strings:LabelResources.LabelClose}"
                            WidthRequest="90" />
                    </HorizontalStackLayout>
                </Grid>
            </telerik:RadBorder>

I have attached two screenshots showing that they do work...

Like I said, when I downgraded to 5.1 it works. The popups worked just minutes prior to the upgrade to 6.0.0. Other popups do work which makes this even more mystifying... These two above do not work and I cannot put my finger on why. I NEED the rich text editor that is in the new package so I need to upgrade pronto!

Looking forward to your response!

Steve

 

Lance | Senior Manager Technical Support
Telerik team
commented on 25 Jul 2023, 12:55 PM

Hi Steve, can you please confirm that you did a complete Clean and Rebuild after updating? This is critical because Visual Studio is intentionally efficient when you compile code... it will not replace DLLs that were cached from the last build. The error here looks a lot like when the project was not built fully after updating.

So let me take you through a set of steps to follow.

  1. Update the project to 6.0.0
  2. Close Visual Studio and navigate to the project folder in File Explorer
  3. Permanently delete the bin and obj folders (don't worry, VS rebuilds these)
  4. Open the solution in VS2022 again
  5. Right-click on the project and choose "Rebuild" (not Build)

This will force VS2022 to actually pull a fresh copy of the DLLs from the NuGet packages instead of using the old ones form the last build. so this time, when you deploy the project, it should be up to date.

Stephen
Top achievements
Rank 1
Iron
Iron
commented on 26 Jul 2023, 03:06 PM

Hi Lance,

I never do just a build... I always do a rebuild as it does an implicit clean and build.

I found out what the issue was. I still think there is some work you guys need to do to get this straightened out, but...

I have a common popup that I have on several of my pages. Instead of duplicating the code that controls these popups, I refactored the code into a popup service. I initialize the service very early in my application's startup and found that the placement target on the popup is the culprit. I was assigning the target to be Application.Current?.MainPage which at that point in the startup, MainPage is null. So, the service has an invalid placement target.

Coming back to the error that is thrown by the Telerik popup code says:

No installed components were detected

which is nowhere near describing the actual exception. This code WORKED in v5.1 so something changed. Again, poor messages in the exceptions wasted hours of my time having to figure out what broke.

So, "No installed components were detected" was a red herring and did nothing to help debug the situation. What I did was back out of the refactored approach and having duplicated code throughout my app which I absolutely detest.

The bottom line is I have moved beyond getting 6.0 installed and "working" but your code has some new bug that someone needs to look into.

Regards, Steve

Lance | Senior Manager Technical Support
Telerik team
commented on 26 Jul 2023, 03:47 PM

Hi Stephen, are you using MAUI's new DependencyService system? You didn't mention this was in a service through .NET 6/7's DI, this changes everything.

Such problems are known in .NET MAUI. It is because when .NET MAUI registers services that try to create concrete instances much too early... hence why your App.Current.MainPage was still null... the MAUI layer still wasn't ready yet, so you can't expect other controls that rely on the Maui application object to be ready either.  So if you have a service that is expecting a view, it will not work and throw a not-so-clear exception like "no components installed",

The easiest way to handle this to do it is to trying using AddSingleton<MyServiceWhichDependsOnViewHandlerReadiness>, I can't explain exactly why this works yet as I haven't compiled it against the .NET MAUI source code.

This is particularly important when using 3rd party controls that require handlers, because our code cannot run until the platform is ready. so if your service gets instantiated by the DI system, the views are null and our handler's platform-specific elements are still null.

To add an extra layer of importance, the RadPopup is not a .NET MAUI construct. It is a custom native platform implementation that provides more feature capability that anything in the .NET MAUI layer can provide (e.g., attaching to the native visual tree root to allow for special popups). This again requires that the handlers have finished loading and there are concrete native views available.

Moving Forward

I will pass this on to the MAUI dev team. What I do know is they actually fixed issues when using AddSingleton, between 5.1.0 and 6.0.0, so you should be fine moving forward with the suggested AddSingleton approach.

If using AddSingleton doesn't work, then I strongly request that you prepare a standalone project that only has your PopupService in it (it only needs a MainPage and throws the exception). Then, open a Bug Report with it attached here => https://feedback.telerik.com/maui.

The repro project is critical in this situation, rather than partial snippets, because it will allow the developers to directly investigate that project against our source code and identify the exact lifecycle issue involved. With it, we can prepare a directly relevant solution for you.

Stephen
Top achievements
Rank 1
Iron
Iron
commented on 26 Jul 2023, 05:59 PM

Lance, I do not mean to sound condescending, but I have been a software engineer for 40 years, a .NET developer for 20 years, and a MAUI developer for almost 2 years. Yes, I use dependency injection to the greatest extent possible. I do believe I know what I am doing. With that said, you still missed the entire point: I strongly feel that the exception being thrown is HIGHLY misleading. Yes, as I said, I realized that things done early in the startup can lead to the conditions you accurately describe. I agree with your feedback. But, "No installed components were detected" is NOT the appropriate error message for this exception! I wasted several hours trying to accurately debug what was going on here. I had no idea if it was my code, MAUI's code, or your code until I isolated the actual condition. A null value is NOT an indicator of components that are not installed. It is because of the null value solely. The error message does not match the condition. That is my point. On top of all of this, it worked in 5.01 and 5.1, but not 5.2 or 6.0 so something changed. Please take note of this and report it to the engineers as there is definitely a bug somewhere in your code...
Lance | Senior Manager Technical Support
Telerik team
commented on 26 Jul 2023, 08:21 PM

Hi Stephen, don't worry, I'm not reading any of your replies with a negative tone or via combative lens, and I sincerely hope I am not coming across that way for you!

First, I should maybe clear up that the RadPopup does not throw that exception message. It comes from .NET MAUI DI inflation, which appears to swallowing our initial exception, this is outside of our control. According to this GitHub issue, the WinUI team is working on making these exception messages more useful => [Windows] Faced no installed components were detected exception · Issue #8997 · dotnet/maui (in that case, you can see it's a different 3rd party control).

In fact, I emphasize with you because I have personally been here with the same exact problem when registering a view. This is something in .NET MAUI that is very hard to debug unless you were already aware of the DI lifecycle that is very specific to .NET MAUI.

What's Next?

I am familiar with exactly where the code is in the RadPopup that checks for the Application.Current.MainPage, this is what I went looking for after your last update. It was modified between 5.1.0 and 6.0.0, to fix an earlier problem with the app instance not being ready yet. This appears to be intentionally designed to prevent problems when the app is null, because we absolutely require the Maui application object to be ready for the handlers to work. I did inform the developer who is responsible and we are currently awaiting for your reply with repro-able code.

Repro

This is why I am humbly asking you to share your exact service code with us. I cannot open a bug report and escalate to the developers without having code to reproduce it, even if I can point to the exact line in the source code.

To help you along those lines, I have built a compete test app, with view, view model and service registrations. find it attached. Please update with your service code and invocation,  so that it causes the exception.

My hope is that we have two options:

  • Possibility 1 - Modify your service class so that it will work
    • In fact, I was able to get it working with a DI service in my starter project! Maybe you can use this to inform you on modification in yours? Please open and explore by starter project attached, by just waiting until the view is ready before attaching the PlacementTarget, I can use the same service anywhere.
    • Additionally, I wait to instantiate the RadPopup until the very first caller asks for it. This will ensure it will never be used too soon. Here's a quick callout from the service's definition:
    • The bottom line is that you cannot ask for a Application.Current.MainPage reference until the app is ready, regardless of where the code is.
  • Possibility 2 - Update RadPopup code to ignore that App.Current is null and delay throwing the error until later. This I cannot say is a even possibility until the developers have reviewed your repro application and understand the consequences of revertign the recently added protections.

Ultimately, without any actionable material to go on, we might be forced to say that RadPopup is not supported in transient DI registrations. There are some controls you cannot get past this fact because the app object is absolutely required due to handler requirements (i.e. native ChartView). For those things that do not support pre-Maui application instantiation, there is a solution using the HandlerChanged event to know when it's ready, but I don't think that's needed here because of what I show in my demo with the dynamic replacement of the target.

If you can reply to me with an updated version of the project that reproduces the exception, I will be happy to escalate it to the developers for direct review against the recent changes.

No answers yet. Maybe you can help?

Tags
Popup
Asked by
Stephen
Top achievements
Rank 1
Iron
Iron
Share this question
or