Skip to content

Commit

Permalink
cross-plat sharing and region manager implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
dansiegel committed Aug 10, 2020
1 parent b023dd6 commit 34863fa
Show file tree
Hide file tree
Showing 19 changed files with 472 additions and 270 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using Prism.Mvvm;
using Xamarin.Forms;

namespace Prism.Ioc
{
/// <summary>
/// Provides Navigation Registration Extensions for Region Navigation
/// </summary>
public static class RegionNavigationRegistrationExtensions
{
/// <summary>
/// Registers a Page for navigation.
/// </summary>
/// <typeparam name="TView">The Type of Page to register</typeparam>
/// <param name="containerRegistry"><see cref="IContainerRegistry"/> used to register type for Navigation.</param>
/// <param name="name">The unique name to register with the Page</param>
public static void RegisterForNavigation<TView>(this IContainerRegistry containerRegistry, string name = null)
where TView : View
{
var viewType = typeof(TView);

if (string.IsNullOrWhiteSpace(name))
name = viewType.Name;

containerRegistry.RegisterForNavigation(viewType, name);
}

/// <summary>
/// Registers a Page for navigation.
/// </summary>
/// <typeparam name="TView">The Type of Page to register</typeparam>
/// <typeparam name="TViewModel">The ViewModel to use as the BindingContext for the Page</typeparam>
/// <param name="name">The unique name to register with the Page</param>
/// <param name="containerRegistry"></param>
public static void RegisterForNavigation<TView, TViewModel>(this IContainerRegistry containerRegistry, string name = null)
where TView : View
where TViewModel : class
{
containerRegistry.RegisterForNavigationWithViewModel<TViewModel>(typeof(TView), name);
}

private static void RegisterForNavigationWithViewModel<TViewModel>(this IContainerRegistry containerRegistry, Type viewType, string name)
where TViewModel : class
{
if (string.IsNullOrWhiteSpace(name))
name = viewType.Name;

ViewModelLocationProvider.Register(viewType.ToString(), typeof(TViewModel));

containerRegistry.RegisterForNavigation(viewType, name);
}
}
}
20 changes: 15 additions & 5 deletions src/Forms/Prism.Forms.Regions/Ioc/RegionRegistrationExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Prism.Regions;
using Prism.Regions.Adapters;
using Prism.Regions.Behaviors;
Expand All @@ -9,6 +7,9 @@

namespace Prism.Ioc
{
/// <summary>
/// Provides registration and configuration helpers for Region Navigation
/// </summary>
public static class RegionRegistrationExtensions
{
/// <summary>
Expand All @@ -29,17 +30,26 @@ public static IContainerRegistry RegisterRegionServices(this IContainerRegistry
return containerRegistry.RegisterSingleton<IRegionManager, RegionManager>();
}

/// <summary>
/// Configures the Default Behaviors and Adapters for Region Navigation
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static PrismApplicationBase InitializeRegionConfigurations(this PrismApplicationBase app) =>
app.ConfigureDefaultRegionBehaviors()
.ConfigureRegionAdapterMappings();

/// <summary>
/// Configures the <see cref="IRegionBehaviorFactory"/>.
/// This will be the list of default behaviors that will be added to a region.
/// </summary>
public static PrismApplicationBase ConfigureDefaultRegionBehaviors(this PrismApplicationBase app, Action<IRegionBehaviorFactory> configure = null)
{
var regionBehaviors = app.Container.Resolve<IRegionBehaviorFactory>();
//regionBehaviors.AddIfMissing(BindRegionContextToDependencyObjectBehavior.BehaviorKey, typeof(BindRegionContextToDependencyObjectBehavior));
regionBehaviors.AddIfMissing(BindRegionContextToVisualElementBehavior.BehaviorKey, typeof(BindRegionContextToVisualElementBehavior));
regionBehaviors.AddIfMissing(RegionActiveAwareBehavior.BehaviorKey, typeof(RegionActiveAwareBehavior));
regionBehaviors.AddIfMissing(SyncRegionContextWithHostBehavior.BehaviorKey, typeof(SyncRegionContextWithHostBehavior));
//regionBehaviors.AddIfMissing(RegionManagerRegistrationBehavior.BehaviorKey, typeof(RegionManagerRegistrationBehavior));
regionBehaviors.AddIfMissing(RegionManagerRegistrationBehavior.BehaviorKey, typeof(RegionManagerRegistrationBehavior));
regionBehaviors.AddIfMissing(RegionMemberLifetimeBehavior.BehaviorKey, typeof(RegionMemberLifetimeBehavior));
regionBehaviors.AddIfMissing(ClearChildViewsRegionBehavior.BehaviorKey, typeof(ClearChildViewsRegionBehavior));
regionBehaviors.AddIfMissing(AutoPopulateRegionBehavior.BehaviorKey, typeof(AutoPopulateRegionBehavior));
Expand All @@ -66,7 +76,7 @@ public static PrismApplicationBase ConfigureRegionAdapterMappings(this PrismAppl
regionAdapterMappings.RegisterMapping(typeof(ScrollView), container.Resolve<ScrollViewRegionAdapter>());
regionAdapterMappings.RegisterMapping(typeof(ContentView), container.Resolve<ContentViewRegionAdapter>());
regionAdapterMappings.RegisterMapping(typeof(Frame), container.Resolve<ContentViewRegionAdapter>());
// regionAdapterMappings.RegisterMapping(typeof(RefreshView), container.Resolve<ContentViewRegionAdapter>());
regionAdapterMappings.RegisterMapping(typeof(RefreshView), container.Resolve<ContentViewRegionAdapter>());

configure?.Invoke(regionAdapterMappings);
return app;
Expand Down
4 changes: 4 additions & 0 deletions src/Forms/Prism.Forms.Regions/Prism.Forms.Regions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
</ItemGroup>

<ItemGroup>
<Compile Include="..\..\Wpf\Prism.Wpf\Regions\IRegionMemberLifetime.cs" Link="Regions\%(Filename)%(Extension)" />
<Compile Include="..\..\Wpf\Prism.Wpf\Regions\IRegionViewRegistry.cs" Link="Regions\%(Filename)%(Extension)" />
<Compile Include="..\..\Wpf\Prism.Wpf\Regions\RegionViewRegistry.cs" Link="Regions\%(Filename)%(Extension)" />
<Compile Include="..\..\Wpf\Prism.Wpf\Regions\RegionMemberLifetimeAttribute.cs" Link="Regions\%(Filename)%(Extension)" />
<Compile Include="..\..\Wpf\Prism.Wpf\Regions\ViewSortHintAttribute.cs" Link="Regions\%(Filename)%(Extension)" />
<Compile Include="..\..\Wpf\Prism.Wpf\Regions\SyncActiveStateAttribute.cs" Link="Regions\%(Filename)%(Extension)" />
<Compile Include="..\..\Wpf\Prism.Wpf\Regions\*Exception.cs" Link="Regions\%(Filename)%(Extension)" />
Expand Down
27 changes: 27 additions & 0 deletions src/Forms/Prism.Forms.Regions/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/Forms/Prism.Forms.Regions/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,18 @@
<data name="RegionCreationException" xml:space="preserve">
<value>An exception occurred while creating a region with name '{0}'. The exception was: {1}.</value>
</data>
<data name="RegionManagerWithDifferentNameException" xml:space="preserve">
<value>The region being added already has a name of '{0}' and cannot be added to the region manager with a different name ('{1}').</value>
</data>
<data name="RegionNameCannotBeEmptyException" xml:space="preserve">
<value>The region name cannot be null or empty.</value>
</data>
<data name="RegionNameExistsException" xml:space="preserve">
<value>Region with the given name is already registered: {0}</value>
</data>
<data name="RegionNotInRegionManagerException" xml:space="preserve">
<value>The region manager does not contain the {0} region.</value>
</data>
<data name="RegionViewExistsException" xml:space="preserve">
<value>View already exists in region.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void RegisterMapping(Type controlType, IRegionAdapter adapter)
throw new ArgumentNullException(nameof(adapter));

if (mappings.ContainsKey(controlType))
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
Resources.MappingExistsException, controlType.Name));

mappings.Add(controlType, adapter);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using Prism.Properties;
using Prism.Regions.Adapters;
Expand All @@ -21,7 +22,7 @@ public class DelayedRegionCreationBehavior
{
private readonly RegionAdapterMappings _regionAdapterMappings;
private WeakReference _elementWeakReference;
private bool _regionCreated;
private bool _regionCreated = false;

private static ICollection<DelayedRegionCreationBehavior> _instanceTracker = new Collection<DelayedRegionCreationBehavior>();
private object _trackerLock = new object();
Expand Down Expand Up @@ -75,12 +76,14 @@ public void Detach()
UnWireTargetElement();
}

#region NeedToRemove
#if false
#region NeedToRemove

private void WireUpTargetElement() { }
private void UnWireTargetElement() { }

#endregion
#endregion
#endif

/// <summary>
/// Called when the <see cref="IRegionManager"/> is updating it's <see cref="IRegionManager.Regions"/> collection.
Expand All @@ -100,10 +103,9 @@ private void TryCreateRegion()
return;
}

#if IFigureThisOut
// DependencyObject inherits from DispatcherObject which provides CheckAccess...
// TODO: Determine proper Forms replacement for CheckAccess...
if (TargetElement.CheckAccess())
//if (TargetElement.CheckAccess())
{
Detach();

Expand All @@ -114,7 +116,6 @@ private void TryCreateRegion()
_regionCreated = true;
}
}
#endif
}

/// <summary>
Expand Down Expand Up @@ -142,64 +143,56 @@ protected virtual IRegion CreateRegion(VisualElement targetElement, string regio
}
}

#if IFigureThisOut
private void ElementLoaded(object sender, RoutedEventArgs e)
{
UnWireTargetElement();
TryCreateRegion();
}

private void WireUpTargetElement()
{
var element = TargetElement;
if (element != null)
{
element.Loaded += this.ElementLoaded;
return;
}

var fcElement = this.TargetElement as FrameworkContentElement;
if (fcElement != null)
{
fcElement.Loaded += this.ElementLoaded;
return;
}
TargetElement.PropertyChanged += TargetElement_ParentChanged;
Track();
//var element = TargetElement;
//if (element != null)
//{
// element.Loaded += this.ElementLoaded;
// return;
//}

//var fcElement = this.TargetElement as FrameworkContentElement;
//if (fcElement != null)
//{
// fcElement.Loaded += this.ElementLoaded;
// return;
//}

//if the element is a dependency object, and not a FrameworkElement, nothing is holding onto the reference after the DelayedRegionCreationBehavior
//is instantiated inside RegionManager.CreateRegion(VisualElement element). If the GC runs before RegionManager.UpdateRegions is called, the region will
//never get registered because it is gone from the updatingRegionsListeners list inside RegionManager. So we need to hold on to it. This should be rare.
VisualElement depObj = this.TargetElement as VisualElement;
if (depObj != null)
{
Track();
return;
}
}

private void UnWireTargetElement()
{
var element = TargetElement;
if (element != null)
{
element.Loaded -= this.ElementLoaded;
return;
}

var fcElement = this.TargetElement as FrameworkContentElement;
if (fcElement != null)
{
fcElement.Loaded -= this.ElementLoaded;
return;
}
TargetElement.PropertyChanged -= TargetElement_ParentChanged;
Untrack();
//var element = TargetElement;
//if (element != null)
//{
// element.Loaded -= this.ElementLoaded;
// return;
//}

//var fcElement = this.TargetElement as FrameworkContentElement;
//if (fcElement != null)
//{
// fcElement.Loaded -= this.ElementLoaded;
// return;
//}
}

VisualElement depObj = this.TargetElement as VisualElement;
if (depObj != null)
private void TargetElement_ParentChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName == nameof(VisualElement.Parent))
{
Untrack();
return;
UnWireTargetElement();
TryCreateRegion();
}
}
#endif

/// <summary>
/// Add the instance of this class to <see cref="_instanceTracker"/> to keep it alive
Expand Down
Loading

0 comments on commit 34863fa

Please sign in to comment.