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

Create One Stop Shop UseMauiControls #1157

Merged
merged 21 commits into from
Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Compatibility/Core/src/Android/AppCompat/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ internal static IVisualElementRenderer CreateRenderer(VisualElement element, Con

internal static IVisualElementRenderer CreateRenderer(VisualElement element, AndroidX.Fragment.App.FragmentManager fragmentManager, Context context)
{
IVisualElementRenderer renderer = Registrar.Registered.GetHandlerForObject<IVisualElementRenderer>(element, context) ?? new DefaultRenderer(context);
IVisualElementRenderer renderer = CreateRenderer(element, context);

var managesFragments = renderer as IManageFragments;
managesFragments?.SetFragmentManager(fragmentManager);
Expand Down
6 changes: 6 additions & 0 deletions src/Compatibility/Core/src/Android/Forms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ internal static void SendViewInitialized(this VisualElement self, global::Androi

static bool IsInitializedRenderers;

// Once we get essentials/cg converted to using startup.cs
// we will delete all the renderer code inside this file
internal static void RenderersRegistered()
{
IsInitializedRenderers = true;
}

internal static void RegisterCompatRenderers(
Assembly[] assemblies,
Expand Down
3 changes: 3 additions & 0 deletions src/Compatibility/Core/src/Android/HandlerToRendererShim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)

public void SetElement(VisualElement element)
{
if (element == Element)
return;

var oldElement = Element;
if (oldElement != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
[assembly: ExportRenderer(typeof(FlyoutPage), typeof(FlyoutPageRenderer))]
[assembly: ExportRenderer(typeof(FlyoutPage), typeof(FlyoutPage))]
[assembly: ExportRenderer(typeof(RefreshView), typeof(RefreshViewRenderer))]


Expand Down
151 changes: 151 additions & 0 deletions src/Compatibility/Core/src/AppHostBuilderExtensions.Controls.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#nullable enable
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Maui.Controls.Compatibility;

#if __ANDROID__
using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using Microsoft.Maui.Controls.Compatibility.Platform.Android.AppCompat;
using FrameRenderer = Microsoft.Maui.Controls.Compatibility.Platform.Android.FastRenderers.FrameRenderer;
using LabelRenderer = Microsoft.Maui.Controls.Compatibility.Platform.Android.FastRenderers.LabelRenderer;
using ImageRenderer = Microsoft.Maui.Controls.Compatibility.Platform.Android.FastRenderers.ImageRenderer;
using ButtonRenderer = Microsoft.Maui.Controls.Compatibility.Platform.Android.FastRenderers.ButtonRenderer;
#elif WINDOWS
using Microsoft.Maui.Controls.Compatibility.Platform.UWP;
using BoxRenderer = Microsoft.Maui.Controls.Compatibility.Platform.UWP.BoxViewBorderRenderer;
using CellRenderer = Microsoft.Maui.Controls.Compatibility.Platform.UWP.TextCellRenderer;
using Deserializer = Microsoft.Maui.Controls.Compatibility.Platform.UWP.WindowsSerializer;
using ResourcesProvider = Microsoft.Maui.Controls.Compatibility.Platform.UWP.WindowsResourcesProvider;
#elif __IOS__
using Microsoft.Maui.Controls.Compatibility.Platform.iOS;
using WebViewRenderer = Microsoft.Maui.Controls.Compatibility.Platform.iOS.WkWebViewRenderer;
using NavigationPageRenderer = Microsoft.Maui.Controls.Compatibility.Platform.iOS.NavigationRenderer;
using TabbedPageRenderer = Microsoft.Maui.Controls.Compatibility.Platform.iOS.TabbedRenderer;
using FlyoutPageRenderer = Microsoft.Maui.Controls.Compatibility.Platform.iOS.PhoneFlyoutPageRenderer;
using RadioButtonRenderer = Microsoft.Maui.Controls.Compatibility.Platform.iOS.Platform.DefaultRenderer;
#endif

using Microsoft.Maui.Hosting;
using Microsoft.Maui.Controls.Shapes;

namespace Microsoft.Maui.Controls.Hosting
{
public static class AppHostBuilderExtensions
{
public static IAppHostBuilder UseMauiApp<TApp>(this IAppHostBuilder builder)
where TApp : class, IApplication
{
builder.ConfigureServices((context, collection) =>
{
collection.AddSingleton<IApplication, TApp>();
});

builder.SetupDefaults();
return builder;
}

public static IAppHostBuilder UseMauiApp<TApp>(this IAppHostBuilder builder, Func<IServiceProvider, TApp> implementationFactory)
where TApp : class, IApplication
{
builder.ConfigureServices((context, collection) =>
{
collection.AddSingleton<IApplication>(implementationFactory);
});

builder.SetupDefaults();
return builder;
}

static IAppHostBuilder SetupDefaults(this IAppHostBuilder builder)
{
builder
.ConfigureMauiHandlers(handlers =>
{
handlers.AddMauiControlsHandlers();
DependencyService.SetToInitialized();

#if __ANDROID__ || __IOS__ || WINDOWS || MACCATALYST

Forms.RenderersRegistered();
handlers.TryAddCompatibilityRenderer(typeof(BoxView), typeof(BoxRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Entry), typeof(EntryRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Editor), typeof(EditorRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Label), typeof(LabelRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Image), typeof(ImageRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Button), typeof(ButtonRenderer));
handlers.TryAddCompatibilityRenderer(typeof(ImageButton), typeof(ImageButtonRenderer));
handlers.TryAddCompatibilityRenderer(typeof(TableView), typeof(TableViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(ListView), typeof(ListViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(CollectionView), typeof(CollectionViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(CarouselView), typeof(CarouselViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(IndicatorView), typeof(IndicatorViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Path), typeof(PathRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Ellipse), typeof(EllipseRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Line), typeof(LineRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Polyline), typeof(PolylineRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Polygon), typeof(PolygonRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Rectangle), typeof(RectangleRenderer));
handlers.TryAddCompatibilityRenderer(typeof(RadioButton), typeof(RadioButtonRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Slider), typeof(SliderRenderer));
handlers.TryAddCompatibilityRenderer(typeof(WebView), typeof(WebViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(SearchBar), typeof(SearchBarRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Switch), typeof(SwitchRenderer));
handlers.TryAddCompatibilityRenderer(typeof(SwipeView), typeof(SwipeViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(DatePicker), typeof(DatePickerRenderer));
handlers.TryAddCompatibilityRenderer(typeof(TimePicker), typeof(TimePickerRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Picker), typeof(PickerRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Stepper), typeof(StepperRenderer));
handlers.TryAddCompatibilityRenderer(typeof(ProgressBar), typeof(ProgressBarRenderer));
handlers.TryAddCompatibilityRenderer(typeof(ScrollView), typeof(ScrollViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Frame), typeof(FrameRenderer));
handlers.TryAddCompatibilityRenderer(typeof(CheckBox), typeof(CheckBoxRenderer));
#if !WINDOWS
handlers.TryAddCompatibilityRenderer(typeof(TabbedPage), typeof(TabbedPageRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Shell), typeof(ShellRenderer));
handlers.TryAddCompatibilityRenderer(typeof(OpenGLView), typeof(OpenGLViewRenderer));
#endif
handlers.TryAddCompatibilityRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer));
handlers.TryAddCompatibilityRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Page), typeof(PageRenderer));
handlers.TryAddCompatibilityRenderer(typeof(FlyoutPage), typeof(FlyoutPageRenderer));
handlers.TryAddCompatibilityRenderer(typeof(RefreshView), typeof(RefreshViewRenderer));
handlers.TryAddCompatibilityRenderer(typeof(NativeViewWrapper), typeof(NativeViewWrapperRenderer));
handlers.TryAddCompatibilityRenderer(typeof(Cell), typeof(CellRenderer));
handlers.TryAddCompatibilityRenderer(typeof(ImageCell), typeof(ImageCellRenderer));
handlers.TryAddCompatibilityRenderer(typeof(EntryCell), typeof(EntryCellRenderer));
handlers.TryAddCompatibilityRenderer(typeof(TextCell), typeof(TextCellRenderer));
handlers.TryAddCompatibilityRenderer(typeof(ViewCell), typeof(ViewCellRenderer));
handlers.TryAddCompatibilityRenderer(typeof(SwitchCell), typeof(SwitchCellRenderer));
DependencyService.Register<Xaml.ResourcesLoader>();
DependencyService.Register<NativeBindingService>();
DependencyService.Register<NativeValueConverterService>();
DependencyService.Register<Deserializer>();
DependencyService.Register<ResourcesProvider>();
DependencyService.Register<Xaml.ValueConverterProvider>();
#endif

#if __IOS__ || MACCATALYST
Internals.Registrar.RegisterEffect("Xamarin", "ShadowEffect", typeof(ShadowEffect));
#endif
})
.ConfigureServices(ConfigureNativeServices);


return builder;
}

static void ConfigureNativeServices(HostBuilderContext arg1, IServiceCollection arg2)
{
#if WINDOWS
if (!UI.Xaml.Application.Current.Resources.ContainsKey("MauiControlsPageControlStyle"))
{
var myResourceDictionary = new Microsoft.UI.Xaml.ResourceDictionary();
myResourceDictionary.Source = new Uri("ms-appx:///Microsoft.Maui.Controls/Platform/Windows/Styles/Resources.xbf");
Microsoft.UI.Xaml.Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary);
}
#endif
}
}
}
2 changes: 1 addition & 1 deletion src/Compatibility/Core/src/AppHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void Configure(HostBuilderContext context, IServiceProvider services)
return;
}

_handlers?.AddHandler(controlType, typeof(RendererToHandlerShim));
_handlers?.TryAddHandler(controlType, typeof(RendererToHandlerShim));
});
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/Compatibility/Core/src/Compatibility-net6.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
</ItemGroup>

<ItemGroup>
<Compile Include="AppHostBuilderExtensions.Controls.cs" />
<Compile Include="RendererToHandlerShim.cs" />
<Compile Include="AppHostBuilderExtensions.cs" />
<Compile Include="MauiHandlersCollectionExtensions.cs" />
Expand All @@ -93,5 +94,6 @@

<ItemGroup>
<ProjectReference Include="..\..\..\Controls\src\Core\Controls.Core-net6.csproj" />
<ProjectReference Include="..\..\..\Controls\src\Xaml\Controls.Xaml-net6.csproj" />
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions src/Compatibility/Core/src/Compatibility.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
</ItemGroup>

<ItemGroup>
<Compile Include="AppHostBuilderExtensions.Controls.cs" />
<Compile Include="AppHostBuilderExtensions.cs" />
<Compile Include="MauiHandlersCollectionExtensions.cs" />
<Compile Include="Forms.cs" />
Expand All @@ -75,5 +76,6 @@

<ItemGroup>
<ProjectReference Include="..\..\..\Controls\src\Core\Controls.Core.csproj" />
<ProjectReference Include="..\..\..\Controls\src\Xaml\Controls.Xaml.csproj" />
</ItemGroup>
</Project>
16 changes: 14 additions & 2 deletions src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,23 @@ namespace Microsoft.Maui.Controls.Compatibility
{
public static class MauiHandlersCollectionExtensions
{
public static IMauiHandlersCollection TryAddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection, Type controlType, Type rendererType)
{
// This will eventually get copied to the all the other adds once we get rid of FormsCompatBuilder
Internals.Registrar.Registered.Register(controlType, rendererType);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be using FormsCompatBuilder?

Copy link
Member Author

@PureWeen PureWeen Jun 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had this initially using FormsCompatBuilder and it wasn't working because FormsCompatBuilder only runs through and registers the PendingRenderers if you call UseFormsCompat but I changed all this code so we're no longer calling 'UseFormsCompat' anymore

I don't totally understand the whole use case for FormsCompatBuilder and why it needs the whole PendingRenderers thing though


#if __ANDROID__ || __IOS__ || WINDOWS || MACCATALYST
handlersCollection.TryAddHandler(controlType, typeof(RendererToHandlerShim));
#endif

return handlersCollection;
}

public static IMauiHandlersCollection AddCompatibilityRenderer(this IMauiHandlersCollection handlersCollection, Type controlType, Type rendererType)
{
FormsCompatBuilder.AddRenderer(controlType, rendererType);

#if __ANDROID__ || __IOS__ || WINDOWS
#if __ANDROID__ || __IOS__ || WINDOWS || MACCATALYST
handlersCollection.AddHandler(controlType, typeof(RendererToHandlerShim));
#endif

Expand All @@ -22,7 +34,7 @@ public static IMauiHandlersCollection AddCompatibilityRenderer<TControlType, TMa
{
FormsCompatBuilder.AddRenderer(typeof(TControlType), typeof(TRenderer));

#if __ANDROID__ || __IOS__ || WINDOWS
#if __ANDROID__ || __IOS__ || WINDOWS || MACCATALYST
handlersCollection.AddHandler<TMauiType, RendererToHandlerShim>();
#endif
return handlersCollection;
Expand Down
2 changes: 1 addition & 1 deletion src/Compatibility/Core/src/RendererToHandlerShim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public RendererToHandlerShim() : base(ViewHandler.ViewMapper)
{
}

#if __ANDROID__ || __IOS__ || WINDOWS
#if __ANDROID__ || __IOS__ || WINDOWS || MACCATALYST
internal IVisualElementRenderer VisualElementRenderer { get; private set; }

public static IViewHandler CreateShim(object renderer)
Expand Down
6 changes: 6 additions & 0 deletions src/Compatibility/Core/src/WinUI/Forms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ static void SetupInit(

static bool IsInitializedRenderers;

// Once we get essentials/cg converted to using startup.cs
// we will delete all the renderer code inside this file
internal static void RenderersRegistered()
{
IsInitializedRenderers = true;
}
internal static void RegisterCompatRenderers()
{
if (IsInitializedRenderers)
Expand Down
6 changes: 6 additions & 0 deletions src/Compatibility/Core/src/iOS/Forms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ internal static bool IsiOS14OrNewer
}
}

// Once we get essentials/cg converted to using startup.cs
// we will delete all the renderer code inside this file
internal static void RenderersRegistered()
{
IsInitializedRenderers = true;
}

internal static bool RespondsToSetNeedsUpdateOfHomeIndicatorAutoHidden
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.Maui.Hosting;
using Microsoft.AspNetCore.Components.WebView.Maui;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Controls.Hosting;

namespace Maui.Controls.Sample.SingleProject
{
Expand All @@ -13,7 +14,6 @@ public class Startup : IStartup
public void Configure(IAppHostBuilder appBuilder)
{
appBuilder
.UseFormsCompatibility()
.RegisterBlazorMauiWebView(typeof(Startup).Assembly)
.UseMauiApp<MyApp>();

Expand Down
12 changes: 5 additions & 7 deletions src/Controls/samples/Controls.Sample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ public void Configure(IAppHostBuilder appBuilder)
{
bool useFullDIAndBlazor = UseFullDI || _pageType == PageType.Blazor;

if (UseXamlApp)
appBuilder.UseMauiApp<XamlApp>();
else
appBuilder.UseMauiApp<MyApp>();

appBuilder
.UseFormsCompatibility()
.UseMauiControlsHandlers()
.ConfigureMauiHandlers(handlers =>
{
#if __ANDROID__
Expand All @@ -58,18 +61,13 @@ public void Configure(IAppHostBuilder appBuilder)
#endif
});

if (UseXamlApp)
appBuilder.UseMauiApp<XamlApp>();
else
appBuilder.UseMauiApp<MyApp>();

// Use a "third party" library that brings in a massive amount of controls
appBuilder.UseRed();

#if DEBUG && !WINDOWS
appBuilder.EnableHotReload();
#endif
appBuilder.UseMauiControlsHandlers();

appBuilder
.ConfigureAppConfiguration(config =>
Expand Down
Loading