Make custom widgets independent of any WinUI framework concerns. Although one can add WinUI concerns to ther widget if they want to build a fully customized widget. In theory, it may also be possible to host a widget of WPF, Avalonia, or Blazor.

This commit is contained in:
TheXamlGuy
2024-01-06 09:57:23 +00:00
parent 3e88950669
commit 4a27534e39
41 changed files with 218 additions and 205 deletions
@@ -2,23 +2,25 @@
using Hyperbar.Options;
using Hyperbar.Templates;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Text.Json;
namespace Hyperbar;
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddWritableConfiguration<TConfiguration>(this IServiceCollection services,
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
string path = "Settings.json")
where TConfiguration :
class, new()
{
return services.AddWritableConfiguration<TConfiguration>(typeof(TConfiguration).Name, path);
return services.AddConfiguration<TConfiguration>(typeof(TConfiguration).Name, path);
}
public static IServiceCollection AddWritableConfiguration<TConfiguration>(this IServiceCollection services,
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
string section,
string path = "Settings.json",
Action<JsonSerializerOptions>? serializerDelegate = null)
@@ -55,23 +57,24 @@ public static class IServiceCollectionExtensions
return services;
}
public static IServiceCollection AddCommandTemplate<TCommand, TCommandTemplate>(this IServiceCollection services)
where TCommand :
ICommandWidgetViewModel
public static IServiceCollection AddWidgetTemplate<TWidgetContent>(this IServiceCollection services)
where TWidgetContent :
IWidgetViewModel
{
Type dataType = typeof(TCommand);
Type templateType = typeof(TCommandTemplate);
Type contentType = typeof(TWidgetContent);
Type templateType = typeof(IWidgetView);
string key = dataType.Name;
string key = contentType.Name;
services.AddTransient(typeof(ICommandWidgetViewModel), dataType);
services.AddTransient(templateType);
services.AddKeyedTransient(typeof(ICommandWidgetViewModel), key, dataType);
services.AddKeyedTransient(templateType, key);
services.AddTransient(typeof(IWidgetViewModel), contentType);
services.TryAddTransient(provider => provider.GetService<IWidgetView>()!);
services.AddKeyedTransient(typeof(IWidgetViewModel), key, contentType);
services.TryAddKeyedTransient(templateType, key);
services.AddTransient<IDataTemplateDescriptor>(provider => new DataTemplateDescriptor
services.AddTransient<IContentTemplateDescriptor>(provider => new ContentTemplateDescriptor
{
DataType = dataType,
ContentType = contentType,
TemplateType = templateType,
Key = key
});
@@ -79,20 +82,48 @@ public static class IServiceCollectionExtensions
return services;
}
public static IServiceCollection AddDataTemplate<TData, TTemplate>(this IServiceCollection services,
public static IServiceCollection AddWidgetTemplate<TWidgetContent, TWidgetTemplate>(this IServiceCollection services)
where TWidgetContent :
IWidgetViewModel
{
Type contentType = typeof(TWidgetContent);
Type templateType = typeof(TWidgetTemplate);
string key = contentType.Name;
services.AddTransient(typeof(IWidgetViewModel), contentType);
services.TryAddTransient(templateType);
services.AddKeyedTransient(typeof(IWidgetViewModel), key, contentType);
services.TryAddKeyedTransient(templateType, key);
services.AddTransient<IContentTemplateDescriptor>(provider => new ContentTemplateDescriptor
{
ContentType = contentType,
TemplateType = templateType,
Key = key
});
return services;
}
public static IServiceCollection AddContentTemplate<TContent, TTemplate>(this IServiceCollection services,
object? key = null)
{
Type dataType = typeof(TData);
Type contentType = typeof(TContent);
Type templateType = typeof(TTemplate);
key ??= dataType.Name;
key ??= contentType.Name;
services.AddKeyedTransient(dataType, key);
services.AddTransient(contentType);
services.TryAddTransient(templateType);
services.AddKeyedTransient(contentType, key);
services.AddKeyedTransient(templateType, key);
services.AddTransient<IDataTemplateDescriptor>(provider => new DataTemplateDescriptor
services.AddTransient<IContentTemplateDescriptor>(provider => new ContentTemplateDescriptor
{
DataType = dataType,
ContentType = contentType,
TemplateType = templateType,
Key = key
});
+6
View File
@@ -0,0 +1,6 @@
namespace Hyperbar;
public interface IWidgetView
{
}
-3
View File
@@ -3,11 +3,8 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseRidGraph>true</UseRidGraph>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="JsonPatch.Net" Version="2.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>
@@ -1,7 +0,0 @@
namespace Hyperbar.Lifecycles;
public interface ICommandWidgetViewModel
{
}
@@ -2,7 +2,7 @@
namespace Hyperbar.Lifecycles;
public interface ICommandWidgetBuilder
public interface IWidgetBuilder
{
void Create(IServiceCollection services);
}
@@ -0,0 +1,6 @@
namespace Hyperbar.Lifecycles;
public interface IWidgetComponentViewModel
{
}
@@ -1,6 +1,6 @@
namespace Hyperbar.Lifecycles;
public interface ICommandWidgetContext
public interface IWidgetContext
{
IServiceProvider ServiceProvider { get; }
}
+6
View File
@@ -0,0 +1,6 @@
namespace Hyperbar.Lifecycles;
public interface IWidgetViewModel
{
}
@@ -2,14 +2,20 @@
namespace Hyperbar.Lifecycles;
public class ObservableCollectionViewModel :
ObservableCollection<object>
public class ObservableCollectionViewModel<TItem> :
ObservableCollection<TItem>
{
public void AddRange(IEnumerable<object> collection)
public void AddRange(IEnumerable<TItem> collection)
{
foreach (var item in collection)
foreach (TItem? item in collection)
{
Add(item);
}
}
}
public class ObservableCollectionViewModel :
ObservableCollectionViewModel<object>
{
}
@@ -0,0 +1,6 @@
namespace Hyperbar.Lifecycles;
public class WidgetButtonViewModel
{
}
@@ -1,7 +1,7 @@
namespace Hyperbar.Lifecycles;
public class CommandWidgetContext(IServiceProvider serviceProvider) :
ICommandWidgetContext
public class WidgetContext(IServiceProvider serviceProvider) :
IWidgetContext
{
public IServiceProvider ServiceProvider => serviceProvider;
}
@@ -0,0 +1,11 @@
using Hyperbar.Templates;
namespace Hyperbar.Lifecycles;
public class WidgetViewModelBase(ITemplateFactory templateFactory) :
ObservableCollectionViewModel<IWidgetComponentViewModel>,
IWidgetViewModel,
ITemplatedViewModel
{
public ITemplateFactory TemplateFactory { get; } = templateFactory;
}
@@ -1,9 +1,9 @@
namespace Hyperbar.Templates;
public record DataTemplateDescriptor :
IDataTemplateDescriptor
public record ContentTemplateDescriptor :
IContentTemplateDescriptor
{
public required Type DataType { get; set; }
public required Type ContentType { get; set; }
public required Type TemplateType { get; set; }
@@ -1,9 +1,11 @@
namespace Hyperbar.Templates;
public interface IDataTemplateDescriptor
public interface IContentTemplateDescriptor
{
Type DataType { get; set; }
Type ContentType { get; set; }
object Key { get; set; }
Type TemplateType { get; set; }
}