twLMControls.Avalonia 2.0.9470.32102
Tipwinns Avalonia License Manager Controls
Tipwinns, Inc
A comprehensive licence assembly to be used for all Tipwinns products specifically designed for .Net 8 Avalonia - Cross-platform support for Windows, Linux, and macOS.
Copyright 2024-2025 Tipwinns, Inc.
Usage of this libary can only be granted by Tipwinns, Inc with written consent.
Description
This assembly contains public controls that can be used in any Avalonia application to manage the licensing of Tipwinns products. The assembly is built using Avalonia 11.2 UI framework and is designed to be used in any cross-platform Avalonia application. The assembly is built using .NET 8.0 and is compatible with any Avalonia application that targets 8.0 or later, running on Windows, Linux, or macOS.
Quick start
Installation
dotnet add package twLMControls.Avalonia
Usage in XAML
<Window xmlns:lm="clr-namespace:twLMControls.Avalonia.Views;assembly=twLMControls.Avalonia">
<lm:LMPortalView/>
</Window>
Configure Dependency Injection
// In App.axaml.cs or your startup code
services.AddSingleton<ITWLicManager, TWLicManager>();
services.AddSingleton<IPortalViewModel, PortalViewModel>();
services.AddSingleton<CurrentLicenseViewModelFactory>();
// Set DIServiceProvider for views
DIServiceProvider.Instance = serviceProvider;
UI Controls
LMPortalView
Main license management portal with:
- Trial license activation
- License key activation
- License deactivation
- Current license status display
- Store and portal navigation links
CurrentLicenseView
Detailed license information display showing:
- License type, status, and validity
- Product information
- Activation counts and limits
- Grace period information
- File location with explorer button
Dependencies
- Avalonia 11.2.2+
- CommunityToolkit.Mvvm 8.4.0+
- LicenseSpring.NetSDK (via twLM core library)
- Microsoft.Extensions.Logging.Abstractions 8.0.2+
Cross-Platform Support
This library supports:
- Windows - Full functionality
- Linux - Full functionality
- macOS - Full functionality
All UI controls are designed to work identically across all platforms.
Objectives
While this license manager is a full feature library, we are only going to be using it for obtaining trial licenses.
We want to use this library because it does a good job locking down a machine that once we have issued a trial. Customers can uninstall/reinstall the application, but they will not be able to get another trial license on that machine unless we reset the license from the cloud.
Use Case #1: New Clean Installation - Obtain a trial license for a new clean installation of the application.
Users will be able to download the application and install it on their machine. When they run the application for the first time, they will be prompted to enter a license key. The license key will be validated against the LicenseSpring server and if the key is valid, a trial license will be issued to the user. The user will be able to use the application for the trial period. Once the trial period has expired, the user will be prompted to purchase a license to continue using the application.
Use Case #2: Tipwinns Aided License Reset for an Expired Trial - Reset a license on a machine so that the user can obtain a new trial license on the same machine or extend their current license period.
The license manager will lock down a given machine on activation of a trial license. If the trial period has expired, the user will not be able to obtain a new trial license on the same machine. The user will have to contact Tipwinns support to request an extension for the license on the machine. Once the license is reset, the user can obtain a new trial license or the license should extend the trial license already on the same machine.
Architecture
This library uses the MVVM (Model-View-ViewModel) pattern with:
- ViewModels:
IPortalViewModel,ICurrentLicenseViewModel(from twLM core library) - Views: Avalonia XAML views with data binding
- Commands: CommunityToolkit.Mvvm
IRelayCommandfor user interactions - Converters: Custom value converters for bool-to-visibility and color coding
All business logic resides in the platform-agnostic twLM core library, making the UI views lightweight and testable.
๐๏ธ Project Structure
twLMControls.Avalonia/
โโโ Views/
โ โโโ LMPortalView.axaml - Main license portal view
โ โโโ LMPortalView.axaml.cs - Code-behind with event handlers
โ โโโ CurrentLicenseView.axaml - License details display
โ โโโ CurrentLicenseView.axaml.cs - Code-behind
โโโ Converters/
โ โโโ BoolToVisibilityConverter.cs - Bool โ Visibility conversion
โ โโโ BoolToColorConverter.cs - Bool โ Color conversion (IsValid, IsTrial)
โโโ Behaviors/
โ โโโ (Future: RegEx validation behavior)
โโโ twLMControls.Avalonia.csproj
โ Completed Features
LMPortalView
โ
All data bindings to IPortalViewModel
โ
Command bindings (GetTrialLicense, ActivateWithKey, DeactivateLicense)
โ
Conditional visibility (valid vs invalid license states)
โ
Event handling (navigation, dialog prompts)
โ
Tooltip bindings
โ
Custom styling (trial button, hyperlinks, deactivate button)
CurrentLicenseView
โ
All 25+ property bindings to ICurrentLicenseViewModel
โ
Read-only text fields in grid layout
โ
Color-coded fields (IsValid = Green, IsTrial = Cyan)
โ
File explorer command binding
โ
Responsive scrollable layout
Converters
โ
BoolToVisibilityConverter - Standard visibility binding
โ
InverseBoolToVisibilityConverter - Inverted visibility
โ
IsValidColorConverter - Green background/foreground when valid
โ
IsTrialColorConverter - Cyan background/foreground when trial
๐ง TODO Items
High Priority
- Implement Avalonia MessageBox for
PromptForDeleteLicenseEvent - Create RegEx validation behavior for license key input
- Replace emoji placeholders with proper Avalonia icons/SVG
- Add proper error validation display (DataValidationErrors)
Medium Priority
- Improve layout responsiveness for different screen sizes
- Add loading indicators for async operations
- Implement proper theming (Light/Dark mode support)
- Add animations for state transitions
Low Priority
- Create custom license key input control with auto-formatting
- Add accessibility features (keyboard navigation, screen reader support)
- Optimize performance for large license lists (if applicable)
๐จ Design Decisions
Layout Strategy
- WinForms: DevExpress LayoutControl with groups
- Avalonia: StackPanel with Border groups (simpler, more maintainable)
Styling Approach
- Inline styles in XAML for component-specific styling
- Fluent theme as base
- Custom button classes:
.trial-button,.hyperlink,.deactivate-button
Color Coding
- Uses
IValueConverterinstead of direct property binding - Supports both Background and Foreground color changes
- Transparent fallback when condition is false
๐ Dependencies
NuGet Packages
Avalonia(11.2.2) - Core frameworkAvalonia.Themes.Fluent(11.2.2) - Modern UI themeAvalonia.Fonts.Inter(11.2.2) - TypographyCommunityToolkit.Mvvm(8.4.0) - Shared MVVM frameworkMicrosoft.Extensions.Logging(8.0.2) - Logging abstractionSerilog(4.1.0) - Logging implementation
Project References
twLM- Core library with ViewModels and business logic
๐ Integration Guide
1. Add to Solution
dotnet sln twlicense.sln add twLMControls.Avalonia/twLMControls.Avalonia.csproj
2. Reference in Avalonia App
<ProjectReference Include="..\twLMControls.Avalonia\twLMControls.Avalonia.csproj" />
3. Use in Avalonia Window
<Window xmlns:views="clr-namespace:twLMControls.Avalonia.Views;assembly=twLMControls.Avalonia">
<views:LMPortalView/>
</Window>
4. Ensure DI Container is Configured
The views expect DIServiceProvider.Instance to provide:
IPortalViewModelITWLicManagerILogger<LMPortalView>CurrentLicenseViewModelFactory
๐ Known Issues
Dialog Prompts
PromptForDeleteLicenseEvent currently returns a default value (TWDialogResult.No).
Solution Needed:
// Option 1: Use Avalonia.MessageBox.Avalonia NuGet package
var result = await MessageBoxManager.GetMessageBoxStandard(
title, message, ButtonEnum.YesNo).ShowAsync();
// Option 2: Create custom dialog window
var dialog = new ConfirmationDialog(message, title);
var result = await dialog.ShowDialog<TWDialogResult>(parentWindow);
License Key Validation
RegEx mask [A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4} needs implementation.
Solution Needed: Create an Avalonia Behavior:
public class LicenseKeyMaskBehavior : Behavior<TextBox>
{
// Apply RegEx validation on TextChanged
// Format input with dashes automatically
}
Icons/Images
Emoji placeholders (๐, ๐, ๐, ๐, ๐) need replacement with proper icons.
Recommended Solutions:
- Use
Avalonia.Svgfor vector graphics - Use
Avalonia.Icons.FluentNuGet package - Convert DevExpress SVG to Avalonia PathGeometry
๐งช Testing Strategy
Next Steps
- Create
twLMControls.Avalonia.Testsproject - Add
Avalonia.Headless.XUnitorAvalonia.Headless.NUnit - Write binding validation tests
- Test command execution
- Test visibility state transitions
Example Test:
[AvaloniaFact]
public void LMPortalView_InvalidLicense_ShowsActivationControls()
{
var view = new LMPortalView();
var viewModel = new Mock<IPortalViewModel>();
viewModel.Setup(x => x.InvalidLicenseViewVisibility).Returns(true);
view.DataContext = viewModel.Object;
var trialButton = view.FindControl<Button>("sbGetTrialLicense");
trialButton.IsVisible.Should().BeTrue();
}
๐ Reference Documentation
- WinForms Extraction:
docs/WINFORMS_UI_EXTRACTION.md - Avalonia Docs: https://docs.avaloniaui.net/
- CommunityToolkit.Mvvm: https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/
๐ค Contributing
When making changes:
- Update XAML bindings if ViewModel interface changes
- Test both light and dark themes
- Ensure cross-platform compatibility (Windows, Linux, macOS)
- Add XML documentation to code-behind
- Update this README with new TODO items or completions
Created: October 21, 2025
Status: Initial implementation - Ready for testing and refinement
No packages depend on twLMControls.Avalonia.
.NET 8.0
- twLM (>= 2.0.9470.32102)
- Avalonia (>= 11.2.2)
- Avalonia.Controls.DataGrid (>= 11.2.2)
- Avalonia.Fonts.Inter (>= 11.2.2)
- Avalonia.Themes.Fluent (>= 11.2.2)
- CommunityToolkit.Mvvm (>= 8.4.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
| Version | Downloads | Last updated |
|---|---|---|
| 2.0.9470.32102 | 0 | 12/04/2025 |
| 2.0.9470.31595 | 1 | 12/04/2025 |
| 2.0.9470.30116 | 1 | 12/04/2025 |
| 2.0.9470.29618 | 0 | 12/04/2025 |
| 2.0.9470.29116 | 1 | 12/04/2025 |
| 2.0.9470.27905 | 1 | 12/04/2025 |
| 2.0.9470.27032 | 0 | 12/04/2025 |
| 2.0.9466.24920 | 1 | 11/30/2025 |
| 2.0.9465.3936 | 1 | 11/30/2025 |
| 2.0.9436.38232 | 1 | 10/31/2025 |
| 2.0.9436.38034 | 0 | 10/31/2025 |