VOOZH about

URL: https://www.nuget.org/packages/Nabs.Launchpad.Ui.Shell/10.0.226

⇱ NuGet Gallery | Nabs.Launchpad.Ui.Shell 10.0.226




👁 Image
Nabs.Launchpad.Ui.Shell 10.0.226

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Nabs.Launchpad.Ui.Shell --version 10.0.226
 
 
NuGet\Install-Package Nabs.Launchpad.Ui.Shell -Version 10.0.226
 
 
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nabs.Launchpad.Ui.Shell" Version="10.0.226" />
 
 
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nabs.Launchpad.Ui.Shell" Version="10.0.226" />
 
Directory.Packages.props
<PackageReference Include="Nabs.Launchpad.Ui.Shell" />
 
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nabs.Launchpad.Ui.Shell --version 10.0.226
 
 
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Nabs.Launchpad.Ui.Shell, 10.0.226"
 
 
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nabs.Launchpad.Ui.Shell@10.0.226
 
 
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nabs.Launchpad.Ui.Shell&version=10.0.226
 
Install as a Cake Addin
#tool nuget:?package=Nabs.Launchpad.Ui.Shell&version=10.0.226
 
Install as a Cake Tool
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

Nabs Launchpad UI Shell Library

The Nabs Launchpad UI Shell library provides core UI services and messaging infrastructure for Blazor applications. This library implements global loading state management using the MVVM messaging pattern, enabling coordinated UI feedback across components without tight coupling.

Key Features

  • Global Loading State Management: Centralized control of loading indicators across the application
  • MVVM Messaging: Built on CommunityToolkit.Mvvm's WeakReferenceMessenger for memory-safe communication
  • Simple API: Static methods for easy integration from any component or service
  • Decoupled Architecture: Components subscribe to loading state changes without direct references
  • Thread-Safe: Safe for use across multiple threads and components
  • Memory Efficient: Uses weak references to prevent memory leaks

Core Components

LoadingService

Static service providing global loading state control with three simple methods: Start(), Stop(), and Spin(bool).

LoadingStateMessage

Message class carrying loading state changes through the MVVM messenger infrastructure.

Usage Examples

Basic Loading State Control

// In a service or code-behind
public async Task LoadDataAsync()
{
 // Start loading indicator
 LoadingService.Start();
 
 try
 {
 await FetchDataFromApiAsync();
 // Process data...
 }
 finally
 {
 // Always stop loading indicator
 LoadingService.Stop();
 }
}

Using Spin for Toggle

public async Task ProcessItemsAsync()
{
 LoadingService.Spin(true); // Start loading
 
 try
 {
 foreach (var item in items)
 {
 await ProcessAsync(item);
 }
 }
 finally
 {
 LoadingService.Spin(false); // Stop loading
 }
}

Subscribing to Loading State Changes

@page "/dashboard"
@implements IDisposable
@inject IMessenger Messenger

@if (isLoading)
{
 <div class="loading-overlay">
 <div class="spinner-border" role="status">
 <span class="visually-hidden">Loading...</span>
 </div>
 </div>
}

<div class="content">
 
</div>

@code {
 private bool isLoading = false;

 protected override void OnInitialized()
 {
 // Subscribe to loading state changes
 Messenger.Register<LoadingStateMessage>(this, (recipient, message) =>
 {
 isLoading = message.Value;
 InvokeAsync(StateHasChanged);
 });
 }

 public void Dispose()
 {
 // Clean up subscription
 Messenger.UnregisterAll(this);
 }
}

Global Progress Component

@* GlobalProgress.razor *@
@implements IRecipient<LoadingStateMessage>
@implements IDisposable
@inject IMessenger Messenger

@if (IsLoading)
{
 <div class="global-progress-overlay">
 <div class="progress-spinner">
 <span class="spinner-border spinner-border-lg"></span>
 <p>Loading...</p>
 </div>
 </div>
}

@code {
 private bool IsLoading { get; set; }

 protected override void OnInitialized()
 {
 Messenger.RegisterAll(this);
 }

 public void Receive(LoadingStateMessage message)
 {
 IsLoading = message.Value;
 InvokeAsync(StateHasChanged);
 }

 public void Dispose()
 {
 Messenger.UnregisterAll(this);
 }
}

Integration with ViewModels

public class UserManagementViewModel : BaseItemViewModel<UserDto>
{
 private readonly IUserService _userService;

 public UserManagementViewModel(IUserService userService, IStringLocalizer localizer)
 : base(localizer)
 {
 _userService = userService;
 }

 public async Task LoadUsersAsync()
 {
 LoadingService.Start();
 
 try
 {
 var result = await _userService.GetAllUsersAsync();
 
 if (result.IsSuccess)
 {
 // Process users
 }
 }
 finally
 {
 LoadingService.Stop();
 }
 }
}

Nested Loading Scenarios

public class DataSyncService
{
 public async Task SyncAllDataAsync()
 {
 LoadingService.Start();
 
 try
 {
 // Sync users - inner loading states are ignored
 await SyncUsersAsync();
 
 // Sync orders
 await SyncOrdersAsync();
 
 // Sync products
 await SyncProductsAsync();
 }
 finally
 {
 LoadingService.Stop();
 }
 }

 private async Task SyncUsersAsync()
 {
 // This won't interfere with outer loading state
 LoadingService.Start();
 try
 {
 await Task.Delay(1000);
 }
 finally
 {
 LoadingService.Stop();
 }
 }
}

Loading State in HTTP Interceptor

public class LoadingHttpMessageHandler : DelegatingHandler
{
 protected override async Task<HttpResponseMessage> SendAsync(
 HttpRequestMessage request,
 CancellationToken cancellationToken)
 {
 LoadingService.Start();
 
 try
 {
 return await base.SendAsync(request, cancellationToken);
 }
 finally
 {
 LoadingService.Stop();
 }
 }
}

// Register in Program.cs
builder.Services.AddTransient<LoadingHttpMessageHandler>();
builder.Services.AddHttpClient("api")
 .AddHttpMessageHandler<LoadingHttpMessageHandler>();

API Reference

LoadingService

Static service for controlling global loading state.

Methods
Start
public static void Start()

Starts the global loading indicator by sending a loading state message with value true.

Usage:

LoadingService.Start();
Stop
public static void Stop()

Stops the global loading indicator by sending a loading state message with value false.

Usage:

LoadingService.Stop();
Spin
public static void Spin(bool value)

Sets the loading state to the specified value.

Parameters:

  • value: true to start loading, false to stop

Usage:

LoadingService.Spin(isLoading);

LoadingStateMessage

Message class for communicating loading state changes.

Constructor
public LoadingStateMessage(bool isLoading)

Creates a new loading state message.

Parameters:

  • isLoading: The loading state value
Properties
Value
public bool Value { get; }

Gets the loading state value (inherited from ValueChangedMessage<bool>).

Architecture and Design Patterns

MVVM Messaging Pattern

The library uses CommunityToolkit.Mvvm's WeakReferenceMessenger to implement a publish-subscribe pattern:

  1. Publisher: LoadingService publishes LoadingStateMessage instances
  2. Subscribers: Components register to receive messages
  3. Weak References: Prevents memory leaks from forgotten subscriptions

Singleton Service Pattern

LoadingService is implemented as a static class providing a singleton-like behavior without requiring dependency injection registration.

Message Broadcasting

When a loading state changes, all registered subscribers receive the message simultaneously, enabling coordinated UI updates.

Best Practices

1. Always Use Try-Finally

// Good
LoadingService.Start();
try
{
 await DoWorkAsync();
}
finally
{
 LoadingService.Stop();
}

// Bad - loading might not stop on exception
LoadingService.Start();
await DoWorkAsync();
LoadingService.Stop();

2. Dispose Subscriptions

// Implement IDisposable in components
public void Dispose()
{
 Messenger.UnregisterAll(this);
}

3. Use InvokeAsync for State Changes

Messenger.Register<LoadingStateMessage>(this, (r, m) =>
{
 isLoading = m.Value;
 InvokeAsync(StateHasChanged); // Required for Blazor components
});

4. Centralize Loading Indicators

Create a single global progress component rather than multiple loading indicators throughout the application.

5. Avoid Nesting Issues

Be careful with nested operations that both control loading state. Consider using a counter-based approach for complex scenarios.

6. Consider User Experience

  • Don't show loading for operations < 300ms
  • Provide cancellation options for long operations
  • Show progress details when possible

Integration with Launchpad Components

With Core.ViewModels

public class MyViewModel : BaseItemViewModel<MyDto>
{
 protected override async Task LoadDataAsync()
 {
 LoadingService.Start();
 try
 {
 // Load data
 }
 finally
 {
 LoadingService.Stop();
 }
 }
}

With Ui.Shell.Blazor.Sf

The Syncfusion UI Shell library includes a pre-built GlobalProgress component that subscribes to loading state messages.

With Core.Portal

Portal applications can use the loading service in middleware or during authentication.

Memory Management

Weak References

The messenger uses weak references, which means:

  • Subscribers don't prevent garbage collection
  • No memory leaks from forgotten unregistrations
  • Components are still cleaned up properly

Manual Cleanup (Recommended)

public void Dispose()
{
 // Explicitly unregister for cleaner resource management
 Messenger.UnregisterAll(this);
}

Thread Safety

The loading service is thread-safe:

  • Can be called from any thread
  • Multiple simultaneous calls are safe
  • Message delivery is thread-safe
// Safe to call from multiple threads
await Task.WhenAll(
 Task.Run(() => Operation1()),
 Task.Run(() => Operation2()),
 Task.Run(() => Operation3())
);

async Task Operation1()
{
 LoadingService.Start();
 try { /* work */ }
 finally { LoadingService.Stop(); }
}

Testing

Unit Testing with Loading Service

[Fact]
public async Task Service_ShowsLoadingState()
{
 // Arrange
 var messenger = WeakReferenceMessenger.Default;
 var loadingStates = new List<bool>();
 
 messenger.Register<LoadingStateMessage>(this, (r, m) =>
 {
 loadingStates.Add(m.Value);
 });

 var service = new MyService();

 // Act
 await service.ProcessAsync();

 // Assert
 loadingStates.Should().Contain(true); // Started loading
 loadingStates.Should().Contain(false); // Stopped loading
 
 // Cleanup
 messenger.UnregisterAll(this);
}

Testing Components with Loading State

[Fact]
public void Component_RespondsToLoadingState()
{
 // Arrange
 using var ctx = new TestContext();
 var component = ctx.RenderComponent<MyComponent>();
 
 // Act - Send loading message
 WeakReferenceMessenger.Default.Send(new LoadingStateMessage(true));
 
 // Assert
 component.Find(".loading-indicator").Should().NotBeNull();
 
 // Act - Stop loading
 WeakReferenceMessenger.Default.Send(new LoadingStateMessage(false));
 
 // Assert
 component.FindAll(".loading-indicator").Should().BeEmpty();
}

Advanced Scenarios

Loading with Progress Percentage

// Define custom message
public class LoadingProgressMessage : ValueChangedMessage<(bool IsLoading, int Percentage)>
{
 public LoadingProgressMessage(bool isLoading, int percentage)
 : base((isLoading, percentage)) { }
}

// Service with progress
public static class ProgressLoadingService
{
 public static void ReportProgress(int percentage)
 {
 WeakReferenceMessenger.Default.Send(
 new LoadingProgressMessage(true, percentage));
 }
}

Multiple Loading Contexts

// Different loading contexts
public enum LoadingContext
{
 Global,
 Grid,
 Form
}

public class ContextualLoadingMessage : ValueChangedMessage<(LoadingContext Context, bool IsLoading)>
{
 public ContextualLoadingMessage(LoadingContext context, bool isLoading)
 : base((context, isLoading)) { }
}

Troubleshooting

Loading Indicator Doesn't Appear

Issue: Loading state changes but UI doesn't update

Solutions:

  • Ensure you're using InvokeAsync(StateHasChanged) in the message handler
  • Verify the component is registered as a message recipient
  • Check that the global progress component is included in your layout

Loading Never Stops

Issue: Loading indicator stays visible

Solutions:

  • Ensure Stop() is called in a finally block
  • Check for exceptions that prevent finally execution
  • Verify no other code is calling Start() without matching Stop()

Memory Leaks

Issue: Components not being garbage collected

Solutions:

  • Implement IDisposable and call Messenger.UnregisterAll(this)
  • Don't capture this in lambda expressions that outlive the component
  • Use weak reference patterns for long-lived subscriptions

Dependencies

  • CommunityToolkit.Mvvm: For MVVM messaging infrastructure and weak reference messenger
  • Nabs.Launchpad.Core.Context: For portal and user context integration

Related Libraries

  • Nabs.Launchpad.Ui.Shell.Blazor.Sf: Syncfusion-based UI components with built-in loading indicators
  • Nabs.Launchpad.Core.ViewModels: ViewModel base classes that can integrate with loading service
  • Nabs.Launchpad.Core.Portal: Portal infrastructure that may use loading states

Target Framework

  • .NET 10
Product Versions Compatible and additional computed target framework versions.
.NET net10.0 net10.0 is compatible.  net10.0-android net10.0-android was computed.  net10.0-browser net10.0-browser was computed.  net10.0-ios net10.0-ios was computed.  net10.0-maccatalyst net10.0-maccatalyst was computed.  net10.0-macos net10.0-macos was computed.  net10.0-tvos net10.0-tvos was computed.  net10.0-windows net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Nabs.Launchpad.Ui.Shell:

Package Downloads
Nabs.Launchpad.Core.ViewModels

Package Description

Nabs.Launchpad.Ui.Shell.Blazor.Sf

Package Description

Nabs.Launchpad.Core.Portal

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.250 120 6/23/2026
10.0.249 132 6/6/2026
10.0.248 137 6/6/2026
10.0.247 130 6/6/2026
10.0.246 138 6/6/2026
10.0.242 126 6/4/2026
10.0.241 128 6/4/2026
10.0.240 127 6/4/2026
10.0.239 134 6/3/2026
10.0.234 131 5/31/2026
10.0.233 135 5/31/2026
10.0.232 123 5/30/2026
10.0.230 129 5/30/2026
10.0.229 123 5/30/2026
10.0.228 131 5/30/2026
10.0.226 153 4/26/2026
10.0.221 142 2/3/2026
10.0.220 153 1/14/2026
10.0.219 155 1/5/2026
10.0.218 156 1/4/2026
Loading failed