Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature for Xamarin added ReactiveShell, ReactiveShellContent, Reacti…
…veFlyOut (#2814) * feature for Xamarin added ReactiveShell, ShellViewModel, ReactiveFlyOut ReactiveShell can be used when you wish to use a viewmodel on your base NOTE: Only supports WhenActivated NOT WhenDeactivated due to the Base nature of the Shell component ShellViewModel is a ViewModel based version of ShellContent * Updates to resolve queries refactored tests using Xamarin.Forms.Mocks Rename ShellViewModel to ReactiveShellContent to keep in with other extended elements * Removed ReactiveMasterDetailPage is obsolete * throw new NullReferenceException(nameof(Locator.Current)) if Locator.Current is null
- Loading branch information
1 parent
aa85c40
commit d215b0f
Showing
30 changed files
with
1,330 additions
and
2 deletions.
There are no files selected for viewing
146 changes: 146 additions & 0 deletions
146
src/ReactiveUI.XamForms.Tests/Activation/ActivatingReactivePagesTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for full license information. | ||
|
||
using ReactiveUI.XamForms; | ||
using ReactiveUI.XamForms.Tests.Activation; | ||
using ReactiveUI.XamForms.Tests.Activation.Mocks; | ||
using Splat; | ||
using Xamarin.Forms; | ||
using Xunit; | ||
|
||
namespace ReactiveUI.Tests | ||
{ | ||
/// <summary> | ||
/// Tests for activating views. | ||
/// </summary> | ||
public class ActivatingReactivePagesTests : IClassFixture<ApplicationFixture<App>> | ||
{ | ||
private ApplicationFixture<App> _fixture; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ActivatingReactivePagesTests"/> class. | ||
/// </summary> | ||
/// <param name="fixture">The fixture.</param> | ||
public ActivatingReactivePagesTests(ApplicationFixture<App> fixture) | ||
{ | ||
_fixture = fixture; | ||
Locator.CurrentMutable.Register(() => new ActivationForViewFetcher(), typeof(IActivationForViewFetcher)); | ||
Locator.CurrentMutable.Register<IViewFor<ShellViewModel>>(() => new ShellView()); | ||
Locator.CurrentMutable.Register<IViewFor<ContentPageViewModel>>(() => new ContentPageView()); | ||
Locator.CurrentMutable.Register<IViewFor<TabbedPageViewModel>>(() => new TabbedPageView()); | ||
Locator.CurrentMutable.Register<IViewFor<CarouselPageViewModel>>(() => new CarouselPageView()); | ||
Locator.CurrentMutable.Register<IViewFor<FlyOutPageViewModel>>(() => new FlyoutPageView()); | ||
_fixture.ActivateApp(new App()); | ||
} | ||
|
||
/// <summary> | ||
/// Tests to make sure that views generally activate. | ||
/// </summary> | ||
[Fact] | ||
public void ActivatingReactiveShellTest() | ||
{ | ||
var main = _fixture.AppMock!.MainPage as AppShell; | ||
|
||
Assert.Equal(1, main!.ViewModel!.IsActiveCount); | ||
Assert.Equal(1, main.IsActiveCount); | ||
} | ||
|
||
/// <summary> | ||
/// Tests to make sure that views generally activate. | ||
/// </summary> | ||
[Fact] | ||
public void ActivatingReactiveContentPageTest() | ||
{ | ||
var vm = new ContentPageViewModel(); | ||
var fixture = new ContentPageView | ||
{ | ||
ViewModel = vm | ||
}; | ||
|
||
// Activate | ||
Shell.Current.Navigation.PushAsync(fixture); | ||
Assert.Equal(1, fixture.ViewModel.IsActiveCount); | ||
Assert.Equal(1, fixture.IsActiveCount); | ||
|
||
// Deactivate | ||
Shell.Current.GoToAsync(".."); | ||
fixture.ViewModel = null; | ||
Assert.Equal(0, vm.IsActiveCount); | ||
Assert.Equal(0, fixture.IsActiveCount); | ||
} | ||
|
||
/// <summary> | ||
/// Tests to make sure that views generally activate. | ||
/// </summary> | ||
[Fact] | ||
public void ActivatingReactiveTabbedPageTest() | ||
{ | ||
var vm1 = new TabbedPageViewModel(); | ||
var fixture1 = new TabbedPageView | ||
{ | ||
ViewModel = vm1 | ||
}; | ||
|
||
// Activate | ||
Shell.Current.Navigation.PushAsync(fixture1); | ||
Assert.Equal(1, fixture1.ViewModel.IsActiveCount); | ||
Assert.Equal(1, fixture1.IsActiveCount); | ||
|
||
// Deactivate | ||
Shell.Current.GoToAsync(".."); | ||
fixture1.ViewModel = null; | ||
Assert.Equal(0, vm1.IsActiveCount); | ||
Assert.Equal(0, fixture1.IsActiveCount); | ||
} | ||
|
||
/// <summary> | ||
/// Tests to make sure that views generally activate. | ||
/// </summary> | ||
[Fact] | ||
public void ActivatingReactiveFlyoutPageTest() | ||
{ | ||
var vm3 = new FlyOutPageViewModel(); | ||
var fixture3 = new FlyoutPageView | ||
{ | ||
ViewModel = vm3 | ||
}; | ||
|
||
// Activate | ||
Shell.Current.Navigation.PushAsync(fixture3); | ||
Assert.Equal(1, fixture3.ViewModel!.IsActiveCount); | ||
Assert.Equal(1, fixture3.IsActiveCount); | ||
|
||
// Deactivate | ||
Shell.Current.GoToAsync(".."); | ||
fixture3.ViewModel = null; | ||
Assert.Equal(0, vm3.IsActiveCount); | ||
Assert.Equal(0, fixture3.IsActiveCount); | ||
} | ||
|
||
/// <summary> | ||
/// Tests to make sure that views generally activate. | ||
/// </summary> | ||
[Fact] | ||
public void ActivatingReactiveCarouselPageTest() | ||
{ | ||
var vm4 = new CarouselPageViewModel(); | ||
var fixture4 = new CarouselPageView | ||
{ | ||
ViewModel = vm4 | ||
}; | ||
|
||
// Activate | ||
Shell.Current.Navigation.PushAsync(fixture4); | ||
Assert.Equal(1, fixture4.ViewModel!.IsActiveCount); | ||
Assert.Equal(1, fixture4.IsActiveCount); | ||
|
||
// Deactivate | ||
Shell.Current.GoToAsync(".."); | ||
fixture4.ViewModel = null; | ||
Assert.Equal(0, vm4.IsActiveCount); | ||
Assert.Equal(0, fixture4.IsActiveCount); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<test:ApplicationMock | ||
x:Class="ReactiveUI.XamForms.Tests.Activation.App" | ||
xmlns="http://xamarin.com/schemas/2014/forms" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
xmlns:test="clr-namespace:ReactiveUI.Tests"> | ||
<!-- | ||
Define global resources and styles here, that apply to all pages in your app. | ||
--> | ||
<Application.Resources> | ||
<ResourceDictionary> | ||
<Color x:Key="Primary">#2196F3</Color> | ||
<Style TargetType="Button"> | ||
<Setter Property="TextColor" Value="White" /> | ||
<Setter Property="VisualStateManager.VisualStateGroups"> | ||
<VisualStateGroupList> | ||
<VisualStateGroup x:Name="CommonStates"> | ||
<VisualState x:Name="Normal"> | ||
<VisualState.Setters> | ||
<Setter Property="BackgroundColor" Value="{StaticResource Primary}" /> | ||
</VisualState.Setters> | ||
</VisualState> | ||
<VisualState x:Name="Disabled"> | ||
<VisualState.Setters> | ||
<Setter Property="BackgroundColor" Value="#332196F3" /> | ||
</VisualState.Setters> | ||
</VisualState> | ||
</VisualStateGroup> | ||
</VisualStateGroupList> | ||
</Setter> | ||
</Style> | ||
</ResourceDictionary> | ||
</Application.Resources> | ||
</test:ApplicationMock> |
57 changes: 57 additions & 0 deletions
57
src/ReactiveUI.XamForms.Tests/Activation/Mocks/App.xaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for full license information. | ||
|
||
using Xamarin.Forms; | ||
|
||
namespace ReactiveUI.XamForms.Tests.Activation | ||
{ | ||
/// <summary> | ||
/// The App. | ||
/// </summary> | ||
/// <seealso cref="Xamarin.Forms.Application" /> | ||
public partial class App | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="App" /> class. | ||
/// </summary> | ||
/// <param name="page">The page.</param> | ||
public App() | ||
{ | ||
InitializeComponent(); | ||
|
||
MainPage = new AppShell(); | ||
} | ||
|
||
/// <summary> | ||
/// Application developers override this method to perform actions when the application starts. | ||
/// </summary> | ||
/// <remarks> | ||
/// To be added. | ||
/// </remarks> | ||
protected override void OnStart() | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Application developers override this method to perform actions when the application enters the sleeping state. | ||
/// </summary> | ||
/// <remarks> | ||
/// To be added. | ||
/// </remarks> | ||
protected override void OnSleep() | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Application developers override this method to perform actions when the application resumes from a sleeping state. | ||
/// </summary> | ||
/// <remarks> | ||
/// To be added. | ||
/// </remarks> | ||
protected override void OnResume() | ||
{ | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/ReactiveUI.XamForms.Tests/Activation/Mocks/AppShell.xaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<rxui:ReactiveShell | ||
x:Class="ReactiveUI.XamForms.Tests.Activation.AppShell" | ||
xmlns="http://xamarin.com/schemas/2014/forms" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms" | ||
xmlns:vm="clr-namespace:ReactiveUI.XamForms.Tests.Activation" | ||
Title="Shell.XamForms.Test" | ||
x:TypeArguments="vm:AppShellViewModel"> | ||
|
||
<!-- | ||
The overall app visual hierarchy is defined here, along with navigation. | ||
https://docs.microsoft.com/xamarin/xamarin-forms/app-fundamentals/shell/ | ||
--> | ||
<Shell.Resources> | ||
<ResourceDictionary> | ||
<Style x:Key="BaseStyle" TargetType="Element"> | ||
<Setter Property="Shell.BackgroundColor" Value="{StaticResource Primary}" /> | ||
<Setter Property="Shell.ForegroundColor" Value="White" /> | ||
<Setter Property="Shell.TitleColor" Value="White" /> | ||
<Setter Property="Shell.DisabledColor" Value="#B4FFFFFF" /> | ||
<Setter Property="Shell.UnselectedColor" Value="#95FFFFFF" /> | ||
<Setter Property="Shell.TabBarBackgroundColor" Value="{StaticResource Primary}" /> | ||
<Setter Property="Shell.TabBarForegroundColor" Value="White" /> | ||
<Setter Property="Shell.TabBarUnselectedColor" Value="#95FFFFFF" /> | ||
<Setter Property="Shell.TabBarTitleColor" Value="White" /> | ||
</Style> | ||
<Style BasedOn="{StaticResource BaseStyle}" TargetType="TabBar" /> | ||
<Style BasedOn="{StaticResource BaseStyle}" TargetType="FlyoutItem" /> | ||
</ResourceDictionary> | ||
</Shell.Resources> | ||
|
||
<rxui:ReactiveShellContent Title="Shell" x:TypeArguments="vm:ShellViewModel" /> | ||
<rxui:ReactiveShellContent Title="Content" x:TypeArguments="vm:ContentPageViewModel" /> | ||
<rxui:ReactiveShellContent Title="Tabbed" x:TypeArguments="vm:TabbedPageViewModel" /> | ||
<rxui:ReactiveShellContent Title="Carousel" x:TypeArguments="vm:CarouselPageViewModel" /> | ||
<rxui:ReactiveShellContent Title="FlyOut" x:TypeArguments="vm:FlyOutPageViewModel" /> | ||
</rxui:ReactiveShell> |
35 changes: 35 additions & 0 deletions
35
src/ReactiveUI.XamForms.Tests/Activation/Mocks/AppShell.xaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for full license information. | ||
|
||
using System.Reactive.Disposables; | ||
|
||
namespace ReactiveUI.XamForms.Tests.Activation | ||
{ | ||
/// <summary> | ||
/// App Shell. | ||
/// </summary> | ||
/// <seealso cref="Xamarin.Forms.Shell" /> | ||
public partial class AppShell | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="AppShell"/> class. | ||
/// </summary> | ||
public AppShell() | ||
{ | ||
InitializeComponent(); | ||
ViewModel = new(); | ||
this.WhenActivated(d => | ||
{ | ||
IsActiveCount++; | ||
d(Disposable.Create(() => IsActiveCount--)); | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the active count. | ||
/// </summary> | ||
public int IsActiveCount { get; set; } | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
src/ReactiveUI.XamForms.Tests/Activation/Mocks/AppShellViewModel.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for full license information. | ||
|
||
using System.Reactive.Disposables; | ||
|
||
namespace ReactiveUI.XamForms.Tests.Activation | ||
{ | ||
/// <summary> | ||
/// Activating View Model2. | ||
/// </summary> | ||
/// <seealso cref="ReactiveUI.ReactiveObject" /> | ||
/// <seealso cref="ReactiveUI.IActivatableViewModel" /> | ||
public class AppShellViewModel : ReactiveObject, IActivatableViewModel | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="AppShellViewModel"/> class. | ||
/// </summary> | ||
public AppShellViewModel() | ||
{ | ||
Activator = new ViewModelActivator(); | ||
|
||
this.WhenActivated(d => | ||
{ | ||
IsActiveCount++; | ||
d(Disposable.Create(() => IsActiveCount--)); | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the Activator which will be used by the View when Activation/Deactivation occurs. | ||
/// </summary> | ||
public ViewModelActivator Activator { get; protected set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the active count. | ||
/// </summary> | ||
public int IsActiveCount { get; protected set; } | ||
} | ||
} |
Oops, something went wrong.