Skip to content

Commit

Permalink
feat: adding support for DefaultView property
Browse files Browse the repository at this point in the history
  • Loading branch information
dansiegel committed Sep 6, 2024
1 parent ec09b17 commit 90fc678
Show file tree
Hide file tree
Showing 28 changed files with 187 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using Prism.Ioc;

namespace Prism.Navigation.Regions.Behaviors;
Expand Down Expand Up @@ -61,7 +61,7 @@ private void StartPopulatingContent()
var registration = registry.Registrations.FirstOrDefault(x => x.View == type);
if (registration is not null)
{
var view = registry.CreateView(container, registration.Name) as VisualElement;
var view = registry.CreateView(container, registration.Name);
Region.Add(view);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ protected override void Adapt(IRegion region, NavigationView regionTarget)
};
}

protected override IRegion CreateRegion()
protected override IRegion CreateRegion(object regionTarget)
{
return new SingleActiveRegion();
return new SingleActiveRegion(regionTarget);
}
}
2 changes: 1 addition & 1 deletion src/Wpf/Prism.Wpf/Navigation/Regions/AllActiveRegion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Prism.Navigation.Regions
/// <summary>
/// Region that keeps all the views in it as active. Deactivation of views is not allowed.
/// </summary>
public class AllActiveRegion : Region
public class AllActiveRegion(object target) : Region(target)
{
/// <summary>
/// Gets a readonly view of the collection of all the active views in the region. These are all the added views.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ private void StartPopulatingContent()
AddViewIntoRegion(view);
}

if (Region is ITargetAwareRegion targetAware && targetAware.Target is FrameworkElement target
&& target.GetValue(RegionManager.DefaultViewProperty) != null)
{
var defaultView = target.GetValue(RegionManager.DefaultViewProperty);
if (defaultView is string targetName)
Region.Add(targetName);
else if (defaultView is UIElement element)
Region.Add(element);
else if (defaultView is Type type)
{
var container = ContainerLocator.Container;
var view = container.Resolve(type);
Region.Add(view);
}
}

regionViewRegistry.ContentRegistered += OnViewRegistered;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ protected override void Adapt(IRegion region, ContentControl regionTarget)
/// Creates a new instance of <see cref="SingleActiveRegion"/>.
/// </summary>
/// <returns>A new instance of <see cref="SingleActiveRegion"/>.</returns>
protected override IRegion CreateRegion()
protected override IRegion CreateRegion(object regionTarget)
{
return new SingleActiveRegion();
return new SingleActiveRegion(regionTarget);
}
}
}
6 changes: 6 additions & 0 deletions src/Wpf/Prism.Wpf/Navigation/Regions/ITargetAwareRegion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Prism.Navigation.Regions;

public interface ITargetAwareRegion : IRegion
{
object Target { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ protected override void Adapt(IRegion region, ItemsControl regionTarget)
/// Creates a new instance of <see cref="AllActiveRegion"/>.
/// </summary>
/// <returns>A new instance of <see cref="AllActiveRegion"/>.</returns>
protected override IRegion CreateRegion()
protected override IRegion CreateRegion(object regionTarget)
{
return new AllActiveRegion();
return new AllActiveRegion(regionTarget);
}
}
}
11 changes: 9 additions & 2 deletions src/Wpf/Prism.Wpf/Navigation/Regions/Region.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Prism.Navigation.Regions
/// <summary>
/// Implementation of <see cref="IRegion"/> that allows multiple active views.
/// </summary>
public class Region : IRegion
public class Region : ITargetAwareRegion
{
private ObservableCollection<ItemMetadata> _itemMetadataCollection;
private string _name;
Expand All @@ -23,13 +23,20 @@ public class Region : IRegion
/// <summary>
/// Initializes a new instance of <see cref="Region"/>.
/// </summary>
public Region()
/// <param name="target">The target view of the Region</param>
public Region(object target)
{
Behaviors = new RegionBehaviorCollection(this);
Target = target;

_sort = DefaultSortComparison;
}

/// <summary>
/// Gets the target view of the Region.
/// </summary>
public object Target { get; }

/// <summary>
/// Occurs when a property value changes.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Wpf/Prism.Wpf/Navigation/Regions/RegionAdapterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public IRegion Initialize(T regionTarget, string regionName)
if (regionName == null)
throw new ArgumentNullException(nameof(regionName));

IRegion region = CreateRegion();
IRegion region = CreateRegion(regionTarget);
region.Name = regionName;

SetObservableRegionOnHostingControl(region, regionTarget);
Expand Down Expand Up @@ -121,7 +121,7 @@ protected virtual void AttachBehaviors(IRegion region, T regionTarget)
/// that will be used to adapt the object.
/// </summary>
/// <returns>A new instance of <see cref="IRegion"/>.</returns>
protected abstract IRegion CreateRegion();
protected abstract IRegion CreateRegion(object regionTarget);

private static T GetCastedObject(object regionTarget)
{
Expand Down
34 changes: 34 additions & 0 deletions src/Wpf/Prism.Wpf/Navigation/Regions/RegionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,40 @@ public static string GetRegionName(DependencyObject regionTarget)
return regionTarget.GetValue(RegionNameProperty) as string;
}

/// <summary>
/// Sets the DefaultView on the specified region
/// </summary>
public static readonly DependencyProperty DefaultViewProperty =
DependencyProperty.RegisterAttached("DefaultView", typeof(object), typeof(RegionManager), null);

/// <summary>
/// Gets the Default View Instance, Type or Name
/// </summary>
/// <param name="regionTarget">The Region Target View</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static object GetDefaultView(DependencyObject regionTarget)
{
if (regionTarget == null)
throw new ArgumentNullException(nameof(regionTarget));

return regionTarget.GetValue(DefaultViewProperty);
}

/// <summary>
/// Sets the Default Region View Instance, Type or Name.
/// </summary>
/// <param name="regionTarget">The Region Target.</param>
/// <param name="viewNameTypeOrInstance">The view instance, type or name.</param>
/// <exception cref="ArgumentNullException"></exception>
public static void SetDefaultView(DependencyObject regionTarget, object viewNameTypeOrInstance)
{
if (regionTarget == null)
throw new ArgumentNullException(nameof(regionTarget));

regionTarget.SetValue(DefaultViewProperty, viewNameTypeOrInstance);
}

private static readonly DependencyProperty ObservableRegionProperty =
DependencyProperty.RegisterAttached("ObservableRegion", typeof(ObservableObject<IRegion>), typeof(RegionManager), null);

Expand Down
4 changes: 2 additions & 2 deletions src/Wpf/Prism.Wpf/Navigation/Regions/SelectorRegionAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ protected override void AttachBehaviors(IRegion region, Selector regionTarget)
/// Creates a new instance of <see cref="Region"/>.
/// </summary>
/// <returns>A new instance of <see cref="Region"/>.</returns>
protected override IRegion CreateRegion()
protected override IRegion CreateRegion(object regionTarget)
{
return new Region();
return new Region(regionTarget);
}
}
}
2 changes: 1 addition & 1 deletion src/Wpf/Prism.Wpf/Navigation/Regions/SingleActiveRegion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Prism.Navigation.Regions
/// <summary>
/// Region that allows a maximum of one active view at a time.
/// </summary>
public class SingleActiveRegion : Region
public class SingleActiveRegion(object target) : Region(target)
{
/// <summary>
/// Marks the specified view as active.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using Prism.Ioc;
using Prism.IocContainer.Wpf.Tests.Support.Mocks.Views;
using Prism.Navigation.Regions;
Expand Down Expand Up @@ -31,7 +31,7 @@ public void ShouldFindCandidateViewInRegion()

// We cannot access the UnityRegionNavigationContentLoader directly so we need to call its
// GetCandidatesFromRegion method through a navigation request.
IRegion testRegion = new Region();
IRegion testRegion = new Region(new ContentControl());

MockView view = new MockView();
testRegion.Add(view);
Expand All @@ -54,7 +54,7 @@ public void ShouldFindCandidateViewWithFriendlyNameInRegion()

// We cannot access the Container specific RegionNavigationContentLoader directly so we need to call its
// GetCandidatesFromRegion method through a navigation request.
IRegion testRegion = new Region();
IRegion testRegion = new Region(new ContentControl());

var view = _container.Resolve<object>("SomeView") as MockView;
testRegion.Add(view);
Expand Down
4 changes: 2 additions & 2 deletions tests/Wpf/Prism.Wpf.Tests/Regions/AllActiveRegionFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class AllActiveRegionFixture
public void AddingViewsToRegionMarksThemAsActive()
{
ContainerLocator.SetContainerExtension(Mock.Of<IContainerExtension>());
IRegion region = new AllActiveRegion();
IRegion region = new AllActiveRegion(new ItemsControl());
var view = new object();

region.Add(view);
Expand All @@ -25,7 +25,7 @@ public void DeactivateThrows()
{
var ex = Assert.Throws<InvalidOperationException>(() =>
{
IRegion region = new AllActiveRegion();
IRegion region = new AllActiveRegion(new ItemsControl());
var view = new object();
region.Add(view);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public void WhenClearChildViewsPropertyIsNotSet_ThenChildViewsRegionManagerIsNot
{
var regionManager = new MockRegionManager();

var region = new Region();
var region = new Region(new ContentControl());
region.RegionManager = regionManager;

var behavior = new ClearChildViewsRegionBehavior();
Expand All @@ -37,7 +37,7 @@ public void WhenClearChildViewsPropertyIsTrue_ThenChildViewsRegionManagerIsClear
{
var regionManager = new MockRegionManager();

var region = new Region();
var region = new Region(new ContentControl());
region.RegionManager = regionManager;

var behavior = new ClearChildViewsRegionBehavior();
Expand All @@ -61,7 +61,7 @@ public void WhenRegionManagerChangesToNotNullValue_ThenChildViewsRegionManagerIs
{
var regionManager = new MockRegionManager();

var region = new Region();
var region = new Region(new ContentControl());
region.RegionManager = regionManager;

var behavior = new ClearChildViewsRegionBehavior();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public void DoesNotThrowWhenAddingNonActiveAwareDataContexts()
public void WhenParentViewGetsActivatedOrDeactivated_ThenChildViewIsNotUpdated()
{
var scopedRegionManager = new RegionManager();
var scopedRegion = new Region { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
var scopedRegion = new Region(new ContentControl()) { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
scopedRegionManager.Regions.Add(scopedRegion);
var behaviorForScopedRegion = new RegionActiveAwareBehavior { Region = scopedRegion };
behaviorForScopedRegion.Attach();
Expand Down Expand Up @@ -160,7 +160,7 @@ public void WhenParentViewGetsActivatedOrDeactivated_ThenChildViewIsNotUpdated()
public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewIsUpdated()
{
var scopedRegionManager = new RegionManager();
var scopedRegion = new Region { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
var scopedRegion = new Region(new ContentControl()) { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
scopedRegionManager.Regions.Add(scopedRegion);
var behaviorForScopedRegion = new RegionActiveAwareBehavior { Region = scopedRegion };
behaviorForScopedRegion.Attach();
Expand Down Expand Up @@ -189,7 +189,7 @@ public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewIsUpdate
public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewWithAttributeInVMIsUpdated()
{
var scopedRegionManager = new RegionManager();
var scopedRegion = new Region { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
var scopedRegion = new Region(new ContentControl()) { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
scopedRegionManager.Regions.Add(scopedRegion);
var behaviorForScopedRegion = new RegionActiveAwareBehavior { Region = scopedRegion };
behaviorForScopedRegion.Attach();
Expand Down Expand Up @@ -219,7 +219,7 @@ public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewWithAttr
public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewModelThatIsNotAFrameworkElementIsNotUpdated()
{
var scopedRegionManager = new RegionManager();
var scopedRegion = new Region { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
var scopedRegion = new Region(new ContentControl()) { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
scopedRegionManager.Regions.Add(scopedRegion);
var behaviorForScopedRegion = new RegionActiveAwareBehavior { Region = scopedRegion };
behaviorForScopedRegion.Attach();
Expand Down Expand Up @@ -248,7 +248,7 @@ public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewModelTha
public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewNotInActiveViewsIsNotUpdated()
{
var scopedRegionManager = new RegionManager();
var scopedRegion = new Region { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
var scopedRegion = new Region(new ContentControl()) { Name = "MyScopedRegion", RegionManager = scopedRegionManager };
scopedRegionManager.Regions.Add(scopedRegion);
var behaviorForScopedRegion = new RegionActiveAwareBehavior { Region = scopedRegion };
behaviorForScopedRegion.Attach();
Expand Down Expand Up @@ -281,7 +281,7 @@ public void WhenParentViewGetsActivatedOrDeactivated_ThenSyncedChildViewNotInAct
public void WhenParentViewWithoutScopedRegionGetsActivatedOrDeactivated_ThenSyncedChildViewIsNotUpdated()
{
var commonRegionManager = new RegionManager();
var nonScopedRegion = new Region { Name = "MyRegion", RegionManager = commonRegionManager };
var nonScopedRegion = new Region(new ContentControl()) { Name = "MyRegion", RegionManager = commonRegionManager };
commonRegionManager.Regions.Add(nonScopedRegion);
var behaviorForScopedRegion = new RegionActiveAwareBehavior { Region = nonScopedRegion };
behaviorForScopedRegion.Attach();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ public RegionMemberLifetimeBehaviorFixture()

protected virtual void Arrange()
{
this.Region = new Region();
this.Behavior = new RegionMemberLifetimeBehavior();
this.Behavior.Region = this.Region;
this.Behavior.Attach();
Region = new Region(new ContentControl());
Behavior = new RegionMemberLifetimeBehavior();
Behavior.Region = Region;
Behavior.Attach();
}

[Fact]
Expand Down Expand Up @@ -257,10 +257,10 @@ public class RegionMemberLifetimeBehaviorAgainstSingleActiveRegionFixture
{
protected override void Arrange()
{
this.Region = new SingleActiveRegion();
this.Behavior = new RegionMemberLifetimeBehavior();
this.Behavior.Region = this.Region;
this.Behavior.Attach();
Region = new SingleActiveRegion(new ContentControl());
Behavior = new RegionMemberLifetimeBehavior();
Behavior.Region = Region;
Behavior.Attach();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public void ShouldAllowMultipleSelectedItemsForListBox()

private SelectorItemsSourceSyncBehavior CreateBehavior()
{
Region region = new Region();
Region region = new Region(new ContentControl());
Selector selector = new TabControl();

var behavior = new SelectorItemsSourceSyncBehavior();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public TestableContentControlRegionAdapter() : base(null)

private MockPresentationRegion region = new MockPresentationRegion();

protected override IRegion CreateRegion()
protected override IRegion CreateRegion(object regionTarget)
{
return region;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public TestableItemsControlRegionAdapter() : base(null)

private MockPresentationRegion region = new MockPresentationRegion();

protected override IRegion CreateRegion()
protected override IRegion CreateRegion(object regionTarget)
{
return region;
}
Expand Down
Loading

0 comments on commit 90fc678

Please sign in to comment.