diff --git a/src/Maui/Prism.Maui/Ioc/RegionNavigationRegistrationExtensions.cs b/src/Maui/Prism.Maui/Ioc/RegionNavigationRegistrationExtensions.cs index 0adaaa1de7..800affcd52 100644 --- a/src/Maui/Prism.Maui/Ioc/RegionNavigationRegistrationExtensions.cs +++ b/src/Maui/Prism.Maui/Ioc/RegionNavigationRegistrationExtensions.cs @@ -1,5 +1,4 @@ using System.Diagnostics.CodeAnalysis; -using Microsoft.Maui.Controls.Compatibility; using Prism.Mvvm; using Prism.Navigation.Regions; using Prism.Navigation.Regions.Adapters; @@ -115,7 +114,8 @@ internal static IContainerRegistry RegisterRegionServices(this IContainerRegistr // TODO: CollectionView is buggy with only last View showing despite multiple Active Views // BUG: iOS Crash with CollectionView https://github.com/xamarin/Xamarin.Forms/issues/9970 //regionAdapterMappings.RegisterDefaultMapping(); - regionAdapterMappings.RegisterDefaultMapping, LayoutViewRegionAdapter>(); + regionAdapterMappings.RegisterDefaultMapping, LayoutViewRegionAdapter>(); + regionAdapterMappings.RegisterDefaultMapping(); regionAdapterMappings.RegisterDefaultMapping(); regionAdapterMappings.RegisterDefaultMapping(); return regionAdapterMappings; diff --git a/src/Maui/Prism.Maui/Navigation/Regions/Adapters/LayoutRegionAdapter.cs b/src/Maui/Prism.Maui/Navigation/Regions/Adapters/LayoutRegionAdapter.cs new file mode 100644 index 0000000000..8b4008c500 --- /dev/null +++ b/src/Maui/Prism.Maui/Navigation/Regions/Adapters/LayoutRegionAdapter.cs @@ -0,0 +1,50 @@ +using Prism.Properties; + +namespace Prism.Navigation.Regions.Adapters; + +/// +/// Adapter that creates a new and monitors its +/// active view to set it on the adapted . +/// +public class LayoutRegionAdapter : RegionAdapterBase +{ + /// + /// Initializes a new instance of . + /// + /// The factory used to create the region behaviors to attach to the created regions. + public LayoutRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) + : base(regionBehaviorFactory) + { + } + + /// + /// Adapts a to an . + /// + /// The new region being used. + /// The object to adapt. + protected override void Adapt(IRegion region, Layout regionTarget) + { + if (region == null) + throw new ArgumentNullException(nameof(region)); + + if (regionTarget == null) + throw new ArgumentNullException(nameof(regionTarget)); + + bool itemsSourceIsSet = regionTarget.Children?.Any() ?? false || regionTarget.IsSet(BindableLayout.ItemsSourceProperty); + + if (itemsSourceIsSet) + { + throw new InvalidOperationException(Resources.LayoutViewHasChildrenException); + } + + BindableLayout.SetItemsSource(regionTarget, region.Views); + BindableLayout.SetItemTemplate(regionTarget, new RegionItemsSourceTemplate()); + } + + /// + /// Creates a new instance of . + /// + /// A new instance of . + protected override IRegion CreateRegion(IContainerProvider container) => + container.Resolve(); +} diff --git a/src/Maui/Prism.Maui/Navigation/Regions/Adapters/LayoutViewRegionAdapter.cs b/src/Maui/Prism.Maui/Navigation/Regions/Adapters/LayoutViewRegionAdapter.cs index 07f48a0f93..9d2c591b7f 100644 --- a/src/Maui/Prism.Maui/Navigation/Regions/Adapters/LayoutViewRegionAdapter.cs +++ b/src/Maui/Prism.Maui/Navigation/Regions/Adapters/LayoutViewRegionAdapter.cs @@ -1,5 +1,4 @@ -using Microsoft.Maui.Controls.Compatibility; -using Prism.Ioc; +using Microsoft.Maui.Controls.Compatibility; using Prism.Properties; namespace Prism.Navigation.Regions.Adapters; diff --git a/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Regions/RegionFixture.cs b/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Regions/RegionFixture.cs index fe910d4e00..461fae6fd1 100644 --- a/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Regions/RegionFixture.cs +++ b/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Regions/RegionFixture.cs @@ -1,4 +1,4 @@ -using Prism.DryIoc.Maui.Tests.Mocks.ViewModels; +using Prism.DryIoc.Maui.Tests.Mocks.ViewModels; using Prism.DryIoc.Maui.Tests.Mocks.Views; using Prism.Navigation.Xaml; @@ -53,6 +53,33 @@ public void FrameRegion_CreatedBy_RegisterViewWithRegion() Assert.IsType(page.FrameRegion.Content.BindingContext); } + [Fact] + public void Issue3159_LayoutRegion_CreatedBy_RegisterViewWithRegion() + { + var mauiApp = CreateBuilder(prism => + prism.RegisterTypes(container => + { + container.RegisterForNavigation(); + container.RegisterForRegionNavigation(); + }) + .OnInitialized(container => + { + var regionManager = container.Resolve(); + regionManager.RegisterViewWithRegion("LayoutRegion", "MockRegionViewA"); + }) + .CreateWindow("MockContentRegionPage")) + .Build(); + var window = GetWindow(mauiApp); + + Assert.IsType(window.Page); + var page = window.Page as MockContentRegionPage; + + Assert.NotNull(page.LayoutRegion.Children); + Assert.NotEmpty(page.LayoutRegion.Children); + Assert.IsType(page.LayoutRegion.Children.First()); + Assert.IsType(((ContentView)page.LayoutRegion.First()).Content.BindingContext); + } + [Fact] public void RegionsShareContainer_WithPage() { @@ -76,7 +103,7 @@ public void RegionsShareContainer_WithPage() var regionManager = mauiApp.Services.GetRequiredService(); var regions = regionManager.Regions.Cast(); - Assert.Equal(2, regions.Count()); + Assert.Equal(3, regions.Count()); foreach (var region in regions) { Assert.Same(page.GetContainerProvider(), region.Container); @@ -110,7 +137,7 @@ public void RegionViewModel_HasPageAccessor_WithCorrectPage() } [Fact] - public void RegionManager_HasTwoRegions() + public void RegionManager_HasRegionsAmount() { var mauiApp = CreateBuilder(prism => prism.RegisterTypes(container => @@ -122,7 +149,7 @@ public void RegionManager_HasTwoRegions() var window = GetWindow(mauiApp); var regionManager = mauiApp.Services.GetRequiredService(); - Assert.Equal(2, regionManager.Regions.Count()); + Assert.Equal(3, regionManager.Regions.Count()); } [Fact] diff --git a/tests/Maui/Prism.DryIoc.Maui.Tests/Mocks/Views/MockContentRegionPage.cs b/tests/Maui/Prism.DryIoc.Maui.Tests/Mocks/Views/MockContentRegionPage.cs index 5d4b495d78..7a21ace925 100644 --- a/tests/Maui/Prism.DryIoc.Maui.Tests/Mocks/Views/MockContentRegionPage.cs +++ b/tests/Maui/Prism.DryIoc.Maui.Tests/Mocks/Views/MockContentRegionPage.cs @@ -1,4 +1,4 @@ -namespace Prism.DryIoc.Maui.Tests.Mocks.Views; +namespace Prism.DryIoc.Maui.Tests.Mocks.Views; public class MockContentRegionPage : ContentPage { @@ -10,14 +10,20 @@ public MockContentRegionPage() FrameRegion = new Frame(); FrameRegion.SetValue(Prism.Navigation.Regions.Xaml.RegionManager.RegionNameProperty, nameof(FrameRegion)); + LayoutRegion = new StackLayout(); + LayoutRegion.SetValue(Prism.Navigation.Regions.Xaml.RegionManager.RegionNameProperty, nameof(LayoutRegion)); + Content = new StackLayout { ContentRegion, - FrameRegion + FrameRegion, + LayoutRegion }; } public ContentView ContentRegion { get; } public Frame FrameRegion { get; } + + public Layout LayoutRegion { get; } }