Skip to content

Commit

Permalink
Now lazy views activation is lifecycle aware (OnAppearing/OnDisappear…
Browse files Browse the repository at this point in the history
…ing)
  • Loading branch information
JeremyBP committed Sep 17, 2020
1 parent 879020a commit 98c00e4
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 107 deletions.
2 changes: 1 addition & 1 deletion Nuget/Prism.Forms.LazyView.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Prism.Forms.LazyView</id>
<version>1.2.0</version>
<version>1.3.0</version>
<title>Prism.Forms.LazyView</title>
<authors>Respawnsive,Jeremy Brun-Picard,Andrei Nitescu</authors>
<owners>Respawnsive</owners>
Expand Down
2 changes: 1 addition & 1 deletion Prism.Forms.LazyView/Behaviors/LazyLoadBehaviorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ void OnIsActiveChanged(object sender, EventArgs e)
}
}

protected abstract void SetContent(TVisualElement element, View contentView);
protected abstract void SetContent(TVisualElement element, View view);
}
}
4 changes: 2 additions & 2 deletions Prism.Forms.LazyView/Behaviors/LazyLoadContentPageBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ namespace Prism.Forms.LazyView.Behaviors
{
public class LazyLoadContentPageBehavior : LazyLoadBehaviorBase<ContentPage>
{
protected override void SetContent(ContentPage page, View contentView)
protected override void SetContent(ContentPage contentPage, View view)
{
page.Content = contentView;
contentPage.Content = view;
}
}
}
8 changes: 5 additions & 3 deletions Prism.Forms.LazyView/Behaviors/LazyLoadContentViewBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using Xamarin.Forms;
using Prism.AppModel;
using Xamarin.Forms;

namespace Prism.Forms.LazyView.Behaviors
{
public class LazyLoadContentViewBehavior : LazyLoadBehaviorBase<ContentView>
{
protected override void SetContent(ContentView element, View contentView)
protected override void SetContent(ContentView contentView, View view)
{
element.Content = contentView;
((view as ContentView)?.BindingContext as IPageLifecycleAware)?.OnAppearing();
contentView.Content = view;
}
}
}
29 changes: 27 additions & 2 deletions Prism.Forms.LazyView/LazyContentView.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Prism.AppModel;
using Prism.Forms.LazyView.Behaviors;
using Xamarin.Forms;

Expand All @@ -25,10 +26,22 @@ public bool IsActive
if (_isActive != value)
{
_isActive = value;
IsActiveChanged?.Invoke(this, EventArgs.Empty);
OnActivationChanged();
}
}
}

private void OnActivationChanged()
{
var isActiveChanged = IsActiveChanged;
if(isActiveChanged != null)
isActiveChanged.Invoke(this, EventArgs.Empty);
else if(Content is ContentView contentView && contentView.BindingContext is IPageLifecycleAware bindingContext)
if(_isActive)
bindingContext.OnAppearing();
else
bindingContext.OnDisappearing();
}
}

public class LazyContentView<TLoadingView, TContentView> : ContentView, IActiveAware where TLoadingView : View where TContentView : View
Expand All @@ -53,9 +66,21 @@ public bool IsActive
if (_isActive != value)
{
_isActive = value;
IsActiveChanged?.Invoke(this, EventArgs.Empty);
OnActivationChanged();
}
}
}

private void OnActivationChanged()
{
var isActiveChanged = IsActiveChanged;
if (isActiveChanged != null)
isActiveChanged.Invoke(this, EventArgs.Empty);
else if (Content is ContentView contentView && contentView.BindingContext is IPageLifecycleAware bindingContext)
if (_isActive)
bindingContext.OnAppearing();
else
bindingContext.OnDisappearing();
}
}
}
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ The original code has been adapted to Prism and published on Nuget.

### How to use it?

Install the Prism.Forms.LazyView nuget package and on a TabbedPage (e.g.):
Install the Prism.Forms.LazyView nuget package: [![NuGet](https://img.shields.io/nuget/v/Prism.Forms.LazyView.svg)](https://www.nuget.org/packages/Prism.Forms.LazyView/)

Then for example on a TabbedPage:

* Add some references:

Expand All @@ -33,6 +35,8 @@ YOUR_CONTENT_VIEW should be a Xamarin.Forms ContentView and will be created once

YOUR_LOADING_VIEW should be a Xamarin.Forms ContentView and will be displayed while lazy loading YOUR_CONTENT_VIEW in a background thread

Actually, it should work with any Prism control implementing MultiPageActiveAwareBehavior (e.g. Tabbed and Carousel)
Actually, it should work with any Prism control implementing MultiPageActiveAwareBehavior (e.g. Tabbed and Carousel), but you can make it work from anywhere you're able to toggle the IsActive property (see "EncrustedSlowContentView").

Now toggling IsActive on view side call OnAppearing/OnDisappearing on viewmodel side.

More details on Sample project
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
</ItemGroup>

<ItemGroup>
<Compile Update="Views\EncrustedSlowContentView.xaml.cs">
<DependentUpon>EncrustedSlowContentView.xaml</DependentUpon>
</Compile>
<Compile Update="Views\TabHostPage.xaml.cs">
<DependentUpon>TabHostPage.xaml</DependentUpon>
</Compile>
Expand All @@ -32,6 +35,9 @@
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Views\EncrustedSlowContentView.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Views\LoadingSlowContentView.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Prism.Navigation;

namespace Prism.Forms.LazyView.Sample.ViewModels
{
public class EncrustedSlowContentViewModel : SlowContentViewModel
{
public EncrustedSlowContentViewModel(INavigationService navigationService) : base(navigationService)
{
}

public override void OnAppearing()
{
base.OnAppearing();
}

public override void OnDisappearing()
{
base.OnDisappearing();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="Prism.Forms.LazyView.Sample.Views.EncrustedSlowContentView"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
xmlns:viewModels="clr-namespace:Prism.Forms.LazyView.Sample.ViewModels;assembly=Prism.Forms.LazyView.Sample"
prism:ViewModelLocator.AutowireViewModel="True"
x:DataType="viewModels:EncrustedSlowContentViewModel">
<ContentView.Content>
<StackLayout>
<Label Text="This should call the vm OnAppearing/OnDisappearing methods, when toggling IsActive" />
</StackLayout>
</ContentView.Content>
</ContentView>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Prism.Forms.LazyView.Sample.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EncrustedSlowContentView : ContentView
{
public EncrustedSlowContentView()
{
InitializeComponent();

// Simulating a complex view
// NEVER do this in real code
Task.Delay(TimeSpan.FromSeconds(3)).Wait();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Prism.Forms.LazyView.Sample.Views.LoadingSlowContentView">
<ContentView.Content>
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="Prism.Forms.LazyView.Sample.Views.LoadingSlowContentView"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ContentView.Content>
<Grid>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<ActivityIndicator IsRunning="True" HorizontalOptions="Center"/>
<Label Text="{Binding Counter, StringFormat='Loading View and ViewModel...{0}0%'}" HorizontalOptions="Center"/>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<ActivityIndicator HorizontalOptions="Center" IsRunning="True" />
<Label HorizontalOptions="Center" Text="{Binding Counter, StringFormat='Loading View and ViewModel...{0}0%'}" />
</StackLayout>
</Grid>
</ContentView.Content>
</ContentView.Content>
</ContentView>
60 changes: 40 additions & 20 deletions Sample/Prism.Forms.LazyView.Sample/Views/SlowContentView.xaml
Original file line number Diff line number Diff line change
@@ -1,34 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:Prism.Forms.LazyView.Sample.ViewModels;assembly=Prism.Forms.LazyView.Sample"
x:Class="Prism.Forms.LazyView.Sample.Views.SlowContentView"
Margin="10"
x:DataType="viewModels:SlowContentViewModel">
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="Prism.Forms.LazyView.Sample.Views.SlowContentView"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:lazyView="clr-namespace:Prism.Forms.LazyView;assembly=Prism.Forms.LazyView"
xmlns:viewModels="clr-namespace:Prism.Forms.LazyView.Sample.ViewModels;assembly=Prism.Forms.LazyView.Sample"
xmlns:views="clr-namespace:Prism.Forms.LazyView.Sample.Views;assembly=Prism.Forms.LazyView.Sample"
Margin="10"
x:DataType="viewModels:SlowContentViewModel">
<Grid>
<StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Center">
<Label Text="{Binding Description}"
HorizontalOptions="Center" LineBreakMode="WordWrap" />
<StackLayout
HorizontalOptions="Center"
Orientation="Vertical"
VerticalOptions="Center">
<Label
HorizontalOptions="Center"
LineBreakMode="WordWrap"
Text="{Binding Description}" />
<StackLayout Orientation="Horizontal">
<Label Text="Long process on ViewModel:"/>
<Label Text="{Binding Counter, StringFormat='{0}0%'}"
HorizontalOptions="Center">
<Label Text="Long process on ViewModel:" />
<Label HorizontalOptions="Center" Text="{Binding Counter, StringFormat='{0}0%'}">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding Counter}" Value="0">
<Setter Property="IsVisible" Value="False"/>
<DataTrigger
Binding="{Binding Counter}"
TargetType="Label"
Value="0">
<Setter Property="IsVisible" Value="False" />
</DataTrigger>
</Label.Triggers>
</Label>
<Label Text="Result!"
HorizontalOptions="Center" IsVisible="False">
<Label
HorizontalOptions="Center"
IsVisible="False"
Text="Result!">
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding Counter}" Value="0">
<Setter Property="IsVisible" Value="True"/>
<DataTrigger
Binding="{Binding Counter}"
TargetType="Label"
Value="0">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</Label.Triggers>
</Label>
</StackLayout>
<Button Text="Navigate to Other" Command="{Binding NavigateCommand}"/>
<Button Command="{Binding NavigateCommand}" Text="Navigate to Other" />
<Button Clicked="Button_OnClicked" Text="Toggle incrusted view" />
<lazyView:LazyContentView
x:Name="LazyContentView"
x:DataType="viewModels:EncrustedSlowContentViewModel"
x:TypeArguments="views:LoadingSlowContentView,views:EncrustedSlowContentView" />
</StackLayout>
</Grid>
</ContentView>
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@ public SlowContentView()
// NEVER do this in real code
Task.Delay(TimeSpan.FromSeconds(3)).Wait();
}

private void Button_OnClicked(object sender, EventArgs e)
{
LazyContentView.IsActive = !LazyContentView.IsActive;
}
}
}
57 changes: 23 additions & 34 deletions Sample/Prism.Forms.LazyView.Sample/Views/TabHostPage.xaml
Original file line number Diff line number Diff line change
@@ -1,40 +1,29 @@
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
xmlns:views="clr-namespace:Prism.Forms.LazyView.Sample.Views;assembly=Prism.Forms.LazyView.Sample"
xmlns:lazyView="clr-namespace:Prism.Forms.LazyView;assembly=Prism.Forms.LazyView"
xmlns:behaviors="clr-namespace:Prism.Forms.LazyView.Behaviors;assembly=Prism.Forms.LazyView"
x:Class="Prism.Forms.LazyView.Sample.Views.TabHostPage"
xmlns:viewModels="clr-namespace:Prism.Forms.LazyView.Sample.ViewModels;assembly=Prism.Forms.LazyView.Sample"
x:Name="This"
Title="{Binding Title}"
BarBackgroundColor="LightGray">
<TabbedPage
x:Class="Prism.Forms.LazyView.Sample.Views.TabHostPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
xmlns:behaviors="clr-namespace:Prism.Forms.LazyView.Behaviors;assembly=Prism.Forms.LazyView"
xmlns:lazyView="clr-namespace:Prism.Forms.LazyView;assembly=Prism.Forms.LazyView"
xmlns:prism="http://prismlibrary.com"
xmlns:viewModels="clr-namespace:Prism.Forms.LazyView.Sample.ViewModels;assembly=Prism.Forms.LazyView.Sample"
xmlns:views="clr-namespace:Prism.Forms.LazyView.Sample.Views;assembly=Prism.Forms.LazyView.Sample"
x:Name="This"
Title="{Binding Title}"
android:TabbedPage.ToolbarPlacement="Bottom"
prism:ViewModelLocator.AutowireViewModel="True"
BarBackgroundColor="LightGray">

<!--A page defined from here-->
<ContentPage Title="Builtin">
<Grid>
<StackLayout Orientation="Vertical"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label Text="A page defined from the TabHostPage" />
<Button Text="Select Lazy tab"
Command="{prism:SelectTab SlowContentView}"/>
</StackLayout>
</Grid>
</ContentPage>
<!-- A normal page referenced -->
<views:StandardPage />

<!--A normal page referenced-->
<!--<views:StandardPage/>-->
<views:TopTabHostPage />

<views:TopTabHostPage/>

<!--A page referenced but constructed the lazy way-->
<lazyView:LazyContentPage Title="{Binding Title}"
x:DataType="viewModels:SlowContentViewModel"
x:TypeArguments="views:LoadingSlowContentView,views:SlowContentView"/>
<!-- A page referenced but constructed the lazy way -->
<lazyView:LazyContentPage
Title="{Binding Title}"
x:DataType="viewModels:SlowContentViewModel"
x:TypeArguments="views:LoadingSlowContentView,views:SlowContentView" />

</TabbedPage>
Loading

0 comments on commit 98c00e4

Please sign in to comment.