diff --git a/Blaxamarin.Framework/Blaxamarin.cs b/Blaxamarin.Framework/Blaxamarin.cs index 85f0dbd..73d73f3 100644 --- a/Blaxamarin.Framework/Blaxamarin.cs +++ b/Blaxamarin.Framework/Blaxamarin.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Xamarin.Forms; namespace Blaxamarin.Framework @@ -11,7 +12,7 @@ namespace Blaxamarin.Framework var serviceCollection = new ServiceCollection(); var serviceProvider = serviceCollection.BuildServiceProvider(); - var renderer = new BlaxamarinRenderer(serviceProvider); + var renderer = new BlaxamarinRenderer(serviceProvider, new LoggerFactory()); var result = renderer.Dispatcher.InvokeAsync(async () => { await renderer.AddComponent(); diff --git a/Blaxamarin.Framework/BlaxamarinRenderer.cs b/Blaxamarin.Framework/BlaxamarinRenderer.cs index 0a287f5..f13a98c 100644 --- a/Blaxamarin.Framework/BlaxamarinRenderer.cs +++ b/Blaxamarin.Framework/BlaxamarinRenderer.cs @@ -1,4 +1,5 @@ using Emblazon; +using Microsoft.Extensions.Logging; using System; using System.Diagnostics; using Xamarin.Forms; @@ -7,8 +8,8 @@ namespace Blaxamarin.Framework { public class BlaxamarinRenderer : EmblazonRenderer { - public BlaxamarinRenderer(IServiceProvider serviceProvider) - : base(serviceProvider) + public BlaxamarinRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) + : base(serviceProvider, loggerFactory) { } diff --git a/BlinForms.Framework/BlinForms.Framework.csproj b/BlinForms.Framework/BlinForms.Framework.csproj index 6651c54..434bc5e 100644 --- a/BlinForms.Framework/BlinForms.Framework.csproj +++ b/BlinForms.Framework/BlinForms.Framework.csproj @@ -11,6 +11,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/BlinForms.Framework/BlinForms.cs b/BlinForms.Framework/BlinForms.cs deleted file mode 100644 index 23bc2a0..0000000 --- a/BlinForms.Framework/BlinForms.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.AspNetCore.Components; -using Microsoft.Extensions.DependencyInjection; -using System.Windows.Forms; - -namespace BlinForms.Framework -{ - public static class BlinForms - { - public static void Run() where T : IComponent - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - - var serviceCollection = new ServiceCollection(); - var serviceProvider = serviceCollection.BuildServiceProvider(); - - var renderer = new BlinFormsRenderer(serviceProvider); - renderer.Dispatcher.InvokeAsync(() => - { - renderer.AddComponent(); - Application.Run(renderer.RootForm); - }); - } - } -} diff --git a/BlinForms.Framework/BlinFormsHostBuilderExtensions.cs b/BlinForms.Framework/BlinFormsHostBuilderExtensions.cs new file mode 100644 index 0000000..8e14b22 --- /dev/null +++ b/BlinForms.Framework/BlinFormsHostBuilderExtensions.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; + +namespace BlinForms.Framework +{ + public static class BlinFormsHostBuilderExtensions + { + /// + /// Registers in the DI container. Call this as part of configuring the + /// host to enable BlinForms. + /// + /// + /// + public static IHostBuilder AddBlinForms(this IHostBuilder hostBuilder) + { + if (hostBuilder is null) + { + throw new ArgumentNullException(nameof(hostBuilder)); + } + + hostBuilder.ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + + return hostBuilder; + } + } +} diff --git a/BlinForms.Framework/BlinFormsHostedService.cs b/BlinForms.Framework/BlinFormsHostedService.cs new file mode 100644 index 0000000..8d8db30 --- /dev/null +++ b/BlinForms.Framework/BlinFormsHostedService.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace BlinForms.Framework +{ + /// + /// An implementation of that controls the lifetime of a BlinForms application. + /// When this service starts, it loads the main form registered by + /// . + /// The service will request that the application stops when the main form is closed. + /// + public class BlinFormsHostedService : IHostedService + { + private readonly IBlinFormsMainFormType _blinFormsMainForm; + private readonly ILoggerFactory _loggerFactory; + private readonly IServiceProvider _serviceProvider; + private readonly IHostApplicationLifetime _hostApplicationLifetime; + + public BlinFormsHostedService(IBlinFormsMainFormType blinFormsMainForm, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IHostApplicationLifetime hostApplicationLifetime) + { + _blinFormsMainForm = blinFormsMainForm; + _loggerFactory = loggerFactory; + _serviceProvider = serviceProvider; + _hostApplicationLifetime = hostApplicationLifetime; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + var renderer = new BlinFormsRenderer(_serviceProvider, _loggerFactory); + await renderer.Dispatcher.InvokeAsync(() => + { + renderer.AddComponent(_blinFormsMainForm.MainFormType); + var rootForm = renderer.RootForm; + rootForm.FormClosed += OnRootFormFormClosed; + Application.Run(rootForm); + }); + } + + private void OnRootFormFormClosed(object sender, FormClosedEventArgs e) + { + // When the main form closes, request for the application to stop + _hostApplicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + } +} diff --git a/BlinForms.Framework/BlinFormsMainFormType.cs b/BlinForms.Framework/BlinFormsMainFormType.cs new file mode 100644 index 0000000..44f2c71 --- /dev/null +++ b/BlinForms.Framework/BlinFormsMainFormType.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Components; +using System; + +namespace BlinForms.Framework +{ + public class BlinFormsMainFormType : IBlinFormsMainFormType + where TComponent : IComponent + { + public BlinFormsMainFormType() + { + MainFormType = typeof(TComponent); + } + + public Type MainFormType { get; } + } +} diff --git a/BlinForms.Framework/BlinFormsRenderer.cs b/BlinForms.Framework/BlinFormsRenderer.cs index 1d192a7..5867750 100644 --- a/BlinForms.Framework/BlinFormsRenderer.cs +++ b/BlinForms.Framework/BlinFormsRenderer.cs @@ -1,4 +1,5 @@ using Emblazon; +using Microsoft.Extensions.Logging; using System; using System.Windows.Forms; @@ -6,8 +7,8 @@ namespace BlinForms.Framework { public class BlinFormsRenderer : EmblazonRenderer { - public BlinFormsRenderer(IServiceProvider serviceProvider) - : base(serviceProvider) + public BlinFormsRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) + : base(serviceProvider, loggerFactory) { } diff --git a/BlinForms.Framework/BlinFormsServiceCollectionExtensions.cs b/BlinForms.Framework/BlinFormsServiceCollectionExtensions.cs new file mode 100644 index 0000000..ed74fc5 --- /dev/null +++ b/BlinForms.Framework/BlinFormsServiceCollectionExtensions.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.DependencyInjection; +using System; + +namespace BlinForms.Framework +{ + public static class BlinFormsServiceCollectionExtensions + { + /// + /// Registers a BlinForms component (typically from a .razor file) as the initial form to load when the + /// application start. + /// + /// + /// + /// + public static IServiceCollection AddBlinFormsMainForm(this IServiceCollection services) + where TComponent : class, IComponent + { + if (services is null) + { + throw new ArgumentNullException(nameof(services)); + } + + services.AddSingleton>(); + + return services; + } + } +} diff --git a/BlinForms.Framework/IBlinFormsMainFormType.cs b/BlinForms.Framework/IBlinFormsMainFormType.cs new file mode 100644 index 0000000..dd12527 --- /dev/null +++ b/BlinForms.Framework/IBlinFormsMainFormType.cs @@ -0,0 +1,9 @@ +using System; + +namespace BlinForms.Framework +{ + public interface IBlinFormsMainFormType + { + Type MainFormType { get; } + } +} diff --git a/BlinFormsSample/AppState.cs b/BlinFormsSample/AppState.cs new file mode 100644 index 0000000..a4ed05f --- /dev/null +++ b/BlinFormsSample/AppState.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; + +namespace BlinFormsSample +{ + public class AppState + { + public List items = new List(); + + public int Counter { get; set; } + + public void ResetAppState() + { + items.AddRange( + new[] + { + new TodoItem { Text = "sell dog", IsDone = true }, + new TodoItem { Text = "buy cat" }, + new TodoItem { Text = "buy cat food" }, + }); + + Counter = 0; + } + + public bool IsEmptyAppState() + { + return + !items.Any() && + Counter == 0; + } + } +} diff --git a/BlinFormsSample/Counter.razor b/BlinFormsSample/Counter.razor index 1ed74b4..ea08bb4 100644 --- a/BlinFormsSample/Counter.razor +++ b/BlinFormsSample/Counter.razor @@ -1,13 +1,13 @@ - +@inject AppState AppState + +