Skip to content
Merged
10 changes: 4 additions & 6 deletions src/Compatibility/ControlGallery/src/Core/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,11 @@ public App()

//TestMainPageSwitches();

if (Device.RuntimePlatform != Device.iOS)
SetMainPage(new ImageSourcesGallery());
}
SetMainPage(CreateDefaultMainPage());

protected override IWindow CreateWindow(IActivationState activationState)
{
return new Window(CreateDefaultMainPage());
//TestMainPageSwitches();

//SetMainPage(new ImageSourcesGallery());
}

protected override void OnStart()
Expand Down
7 changes: 2 additions & 5 deletions src/Controls/samples/Controls.Sample/XamlApp.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@ public XamlApp(IServiceProvider services, ITextService textService)

Debug.WriteLine($"The .NET Purple color is {Resources["DotNetPurple"]}");
Debug.WriteLine($"The injected text service had a message: '{textService.GetText()}'");

MainPage = Services.GetRequiredService<Page>();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use MainPage for single page apps.

}

public IServiceProvider Services { get; }

protected override IWindow CreateWindow(IActivationState activationState)
{
return Services.GetRequiredService<IWindow>();
}
}
}
78 changes: 28 additions & 50 deletions src/Controls/src/Core/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,82 +63,60 @@ public IAppLinks AppLinks

public static Application Current { get; set; }

// TODO MAUI. What should this be?
public Page MainPage
{
get
{
if (Windows.Count == 0)
return null;

return Windows[0].View as Page;
return Windows[0].Page;
}
set
{
if (value == null)
throw new ArgumentNullException("value");
throw new ArgumentNullException(nameof(value));

if (MainPage == value)
return;

OnPropertyChanging();

var previousPage = MainPage;

if (previousPage != null)
previousPage.Parent = null;

if (Windows.Count == 0)
{
OnPropertyChanging();
// there are no windows, so add a new window

AddWindow(new Window(value));
OnPropertyChanged();
}
else
{
var mainPage = MainPage;

if (mainPage == value)
return;

OnPropertyChanging();
if (mainPage != null)
mainPage.Parent = null;

Windows[0].View = (IView)value;
// find the best window and replace the page

var theWindow = Windows[0];
foreach (var window in Windows)
{
if (window.Page == previousPage)
{
theWindow = window;
break;
}
}

theWindow.Page = value;
}

if (mainPage != null)
mainPage.NavigationProxy.Inner = NavigationProxy;
if (previousPage != null)
previousPage.NavigationProxy.Inner = NavigationProxy;

OnPropertyChanged();
}
OnPropertyChanged();
}
}

//public Page MainPage
//{
// get { return _mainPage; }
// set
// {
// if (value == null)
// throw new ArgumentNullException("value");

// if (_mainPage == value)
// return;

// OnPropertyChanging();
// if (_mainPage != null)
// {
// InternalChildren.Remove(_mainPage);
// _mainPage.Parent = null;
// }

// _mainPage = value;

// if (_mainPage != null)
// {
// _mainPage.Parent = this;
// _mainPage.NavigationProxy.Inner = NavigationProxy;
// InternalChildren.Add(_mainPage);
// }

// OnPropertyChanged();
// }
//}

public IDictionary<string, object> Properties
{
get
Expand Down
21 changes: 14 additions & 7 deletions src/Controls/src/Core/HandlerImpl/Application.Impl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ namespace Microsoft.Maui.Controls
{
public partial class Application : IApplication
{
List<IWindow> _windows = new List<IWindow>();
public IReadOnlyList<IWindow> Windows => _windows.AsReadOnly();
readonly List<Window> _windows = new();

IReadOnlyList<IWindow> IApplication.Windows => Windows;

public IReadOnlyList<Window> Windows => _windows.AsReadOnly();

IWindow IApplication.CreateWindow(IActivationState activationState)
{
IWindow window = CreateWindow(activationState);
var window = CreateWindow(activationState);

AddWindow(window);
if (!_windows.Contains(window))
AddWindow(window);

return window;
}

void AddWindow(IWindow window)
void AddWindow(Window window)
{
_windows.Add(window);

Expand All @@ -32,9 +36,12 @@ void AddWindow(IWindow window)
ne.NavigationProxy.Inner = NavigationProxy;
}

protected virtual IWindow CreateWindow(IActivationState activationState)
protected virtual Window CreateWindow(IActivationState activationState)
{
throw new NotImplementedException();
if (Windows.Count > 0)
return Windows[0];

throw new NotImplementedException($"Either set {nameof(MainPage)} or override {nameof(Application.CreateWindow)}.");
}
}
}
152 changes: 152 additions & 0 deletions src/Controls/tests/Core.UnitTests/ApplicationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
using System;
using NUnit.Framework;

namespace Microsoft.Maui.Controls.Core.UnitTests
{
[TestFixture]
public class ApplicationTests : BaseTestFixture
{
[Test]
public void NewApplicationHasNoWindowsNorPage()
{
var app = new Application();

Assert.Null(app.MainPage);
Assert.IsEmpty(app.Windows);
}

[Test]
public void SettingMainPageSetsMainPageAndWindow()
{
var app = new Application();
var page = new ContentPage();

app.MainPage = page;

Assert.AreEqual(page, app.MainPage);
Assert.AreEqual(1, app.Windows.Count);
Assert.AreEqual(page, app.Windows[0].Page);
}

[Test]
public void CreateWindowUsesMainPage()
{
var app = new Application();
var iapp = app as IApplication;
var page = new ContentPage();

app.MainPage = page;

var window = iapp.CreateWindow(null);

Assert.AreEqual(page, app.MainPage);
Assert.IsNotEmpty(app.Windows);
Assert.AreEqual(1, app.Windows.Count);
Assert.AreEqual(window, app.Windows[0]);
Assert.AreEqual(page, app.Windows[0].Page);
}

[Test]
public void SettingMainPageUpdatesWindow()
{
var app = new Application();
var iapp = app as IApplication;
var page = new ContentPage();

app.MainPage = page;
var window = iapp.CreateWindow(null);

var page2 = new ContentPage();
app.MainPage = page2;

Assert.AreEqual(page2, app.MainPage);
Assert.IsNotEmpty(app.Windows);
Assert.AreEqual(1, app.Windows.Count);
Assert.AreEqual(window, app.Windows[0]);
Assert.AreEqual(page2, app.Windows[0].Page);
}

[Test]
public void NotSettingMainPageThrows()
{
var app = new Application();
var iapp = app as IApplication;

Assert.Throws<NotImplementedException>(() => iapp.CreateWindow(null));
}

[Test]
public void CanUseExistingWindow()
{
var window = new Window();

var app = new StubApp { MainWindow = window };
var iapp = app as IApplication;

var win = iapp.CreateWindow(null);

Assert.AreEqual(window, win);
Assert.Null(app.MainPage);
}

[Test]
public void CanUseExistingWindowWithPage()
{
var window = new Window { Page = new ContentPage() };

var app = new StubApp { MainWindow = window };
var iapp = app as IApplication;

var win = iapp.CreateWindow(null);

Assert.AreEqual(window, win);
Assert.AreEqual(window.Page, app.MainPage);
}

[Test]
public void SettingMainPageOverwritesExistingPage()
{
var window = new Window { Page = new ContentPage() };

var app = new StubApp { MainWindow = window };
var iapp = app as IApplication;

var win = iapp.CreateWindow(null);

var page2 = new ContentPage();
app.MainPage = page2;

Assert.AreEqual(window, win);
Assert.AreEqual(page2, app.MainPage);
Assert.AreEqual(window.Page, app.MainPage);
}

[Test]
public void SettingWindowPageOverwritesMainPage()
{
var window = new Window { Page = new ContentPage() };

var app = new StubApp { MainWindow = window };
var iapp = app as IApplication;

var win = iapp.CreateWindow(null);

var page2 = new ContentPage();
window.Page = page2;

Assert.AreEqual(window, win);
Assert.AreEqual(page2, app.MainPage);
Assert.AreEqual(window.Page, app.MainPage);
}

class StubApp : Application
{
public Window MainWindow { get; set; }

protected override Window CreateWindow(IActivationState activationState)
{
return MainWindow;
}
}
}
}
2 changes: 1 addition & 1 deletion src/Controls/tests/Core.UnitTests/WindowsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public class TestApp : Application
public TestWindow CreateWindow() =>
(TestWindow)(this as IApplication).CreateWindow(null);

protected override IWindow CreateWindow(IActivationState activationState)
protected override Window CreateWindow(IActivationState activationState)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Windows property is now a list of Control's Window as that is probably what we want at this level.

{
return new TestWindow(new ContentPage());
}
Expand Down
7 changes: 7 additions & 0 deletions src/Core/src/LifecycleEvents/Android/AndroidLifecycle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ namespace Microsoft.Maui.LifecycleEvents
{
public static class AndroidLifecycle
{
// Events called by the Application
public delegate void OnApplicationCreating(Application application);
public delegate void OnApplicationCreate(Application application);
public delegate void OnApplicationLowMemory(Application application);
public delegate void OnApplicationTrimMemory(Application application, TrimMemory level);
public delegate void OnApplicationConfigurationChanged(Application application, Configuration newConfig);
Comment on lines +11 to +16
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some new application events.


// Events called by the ActivityLifecycleCallbacks
public delegate void OnCreate(Activity activity, Bundle? savedInstanceState);
public delegate void OnStart(Activity activity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
{
public static class AndroidLifecycleBuilderExtensions
{
public static IAndroidLifecycleBuilder OnApplicationCreating(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnApplicationCreating del) => lifecycle.OnEvent(del);
public static IAndroidLifecycleBuilder OnApplicationCreate(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnApplicationCreate del) => lifecycle.OnEvent(del);
public static IAndroidLifecycleBuilder OnApplicationLowMemory(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnApplicationLowMemory del) => lifecycle.OnEvent(del);
public static IAndroidLifecycleBuilder OnApplicationTrimMemory(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnApplicationTrimMemory del) => lifecycle.OnEvent(del);
public static IAndroidLifecycleBuilder OnApplicationConfigurationChanged(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnApplicationConfigurationChanged del) => lifecycle.OnEvent(del);

public static IAndroidLifecycleBuilder OnActivityResult(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnActivityResult del) => lifecycle.OnEvent(del);
public static IAndroidLifecycleBuilder OnBackPressed(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnBackPressed del) => lifecycle.OnEvent(del);
public static IAndroidLifecycleBuilder OnConfigurationChanged(this IAndroidLifecycleBuilder lifecycle, AndroidLifecycle.OnConfigurationChanged del) => lifecycle.OnEvent(del);
Expand Down
Loading