WPF UI components for license-management.com end-user SDK.
This library provides ready-to-use WPF views and view models for license registration, validation display, and unregistration workflows.
Important
Account Required: This library requires a publisher account at license-management.com.
Free with Dev Subscription: A developer subscription is available at no cost, which provides full access to all features for development and testing purposes.
- Pre-built Views - Ready-to-use WPF windows for common license operations
- MVVM Architecture - Clean separation with ViewModels and Commands
- Value Converters - License status to UI element converters
- Validation Rules - Input validation for receipt codes
- Customizable - Use as-is or extend with your own styles
dotnet add package LicenseManagement.EndUser.WpfOr via NuGet Package Manager:
Install-Package LicenseManagement.EndUser.Wpf
Warning
Breaking Change in v2.0.0: The package has been renamed from Hymma.Lm.EndUser.Wpf to LicenseManagement.EndUser.Wpf. See the Migration Guide below.
| View | Description |
|---|---|
MainWindow |
Main license management window (standalone) |
LicenseControl |
Embeddable UserControl for license management |
RegisterLicenseView |
Product key/receipt code entry |
UnregisterView |
Computer unregistration confirmation |
ErrorView |
Error display with details |
This package provides two ways to display license management UI:
-
MainWindow- A standaloneWindowthat can be shown as a dialog. Use this when you want to show license management in a separate popup window. -
LicenseControl- AUserControlthat can be embedded directly into your application's UI. Use this when you want to integrate license management into an existing window, tab, or settings panel.
| ViewModel | Description |
|---|---|
LicenseViewModel |
License status, products, grouping and chosen layout |
ProductViewModel |
A single product card (status, validity meter, actions) |
ProductGroupViewModel |
A presentation group of product cards (label, caption, accent) |
RegisterLicenseViewModel |
Registration workflow logic |
UnregisterViewModel |
Unregistration workflow logic |
ErrorViewModel |
Error handling and display |
BaseViewModel |
Base class with INotifyPropertyChanged |
| Converter | Description |
|---|---|
LicenseStatusConverter |
Converts LicenseStatusTitles to display strings |
BooleanToVisibilityConverter |
Standard bool to Visibility converter |
UtcToLocalTimeConverter |
Converts UTC DateTime to local time |
| Command | Description |
|---|---|
RelayCommand |
ICommand implementation for MVVM |
| Rule | Description |
|---|---|
ReceiptCodeRule |
Validates receipt code format |
using LicenseManagement.EndUser.Wpf.Views;
using LicenseManagement.EndUser.Wpf.ViewModels;
var mainWindow = new MainWindow();
mainWindow.License = new LicenseViewModel
{
Status = LicenseStatusTitles.Valid,
ExpirationDate = DateTime.UtcNow.AddMonths(6),
ProductName = "My Product"
};
mainWindow.ShowDialog();<Window xmlns:views="clr-namespace:LicenseManagement.EndUser.Wpf.Views;assembly=LicenseManagement.EndUser.Wpf">
<Grid>
<!-- Other UI elements -->
<views:LicenseControl x:Name="licenseControl" />
</Grid>
</Window>// In code-behind or ViewModel
licenseControl.License = new LicenseViewModel
{
Status = LicenseStatusTitles.Valid,
ExpirationDate = DateTime.UtcNow.AddMonths(6),
ProductName = "My Product"
};using LicenseManagement.EndUser.Wpf.Views;
using LicenseManagement.EndUser.Wpf.ViewModels;
var viewModel = new RegisterLicenseViewModel();
var view = new RegisterLicenseView
{
DataContext = viewModel
};
if (view.ShowDialog() == true)
{
string receiptCode = viewModel.ReceiptCode;
// Process the receipt code
}using LicenseManagement.EndUser.Wpf.ViewModels;
var licenseVm = new LicenseViewModel
{
Status = LicenseStatusTitles.Valid,
ExpirationDate = DateTime.UtcNow.AddMonths(6),
ProductName = "My Product"
};<Window xmlns:converters="clr-namespace:LicenseManagement.EndUser.Wpf.Converters.ValueConverters;assembly=LicenseManagement.EndUser.Wpf">
<Window.Resources>
<converters:LicenseStatusConverter x:Key="StatusConverter"/>
<converters:UtcToLocalTimeConverter x:Key="TimeConverter"/>
</Window.Resources>
<TextBlock Text="{Binding Status, Converter={StaticResource StatusConverter}}"/>
<TextBlock Text="{Binding ExpirationDate, Converter={StaticResource TimeConverter}}"/>
</Window><Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/LicenseManagement.EndUser.Wpf;component/AppResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>Since v2.3.0 the license window shows each product as a card (instead of a dropdown), arranged into developer-defined groups — e.g. Monthly and Annual — each with its own colour, label and count. You pick one of three layouts; the end user cannot change it.
| Layout | Looks like |
|---|---|
Bands (default) |
Full-width tinted bands stacked top to bottom |
Lanes |
One coloured column per group, side by side |
Switcher |
A segmented control showing one group at a time |
using LicenseManagement.EndUser.Wpf.Configuration;
using LicenseManagement.EndUser.Wpf.ViewModels;
license.ApplyGrouping(new[]
{
new ProductGroupDefinition
{
Key = "monthly", Label = "Monthly", Caption = "Renews every month",
Accent = "#0E8F9C", ProductIds = { "PRD_aaa", "PRD_bbb" }
},
new ProductGroupDefinition
{
Key = "annual", Label = "Annual", Caption = "Renews once a year",
Accent = "#B5751A", ProductIds = { "PRD_ccc" }
},
}, ProductLayout.Bands);A product not named in any group falls into a trailing default group. Applying no grouping
(or ApplyGrouping(null)) renders every product as cards in a single unlabeled group, so
existing consumers keep working unchanged.
Add a <ProductGroups> section and a licenseLayout setting; the control reads them
automatically. Each entry's value is "Label | Caption | #Accent | id1,id2,...".
<configSections>
<section name="Products" type="System.Configuration.NameValueSectionHandler" />
<section name="ProductGroups" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<appSettings>
<!-- vendorId / ApiKey / publicKey / validDays as usual -->
<add key="licenseLayout" value="Bands" /> <!-- Bands | Lanes | Switcher -->
</appSettings>
<Products>
<add key="PRD_aaa" value="Product A" />
<add key="PRD_bbb" value="Product B" />
<add key="PRD_ccc" value="Product C" />
</Products>
<ProductGroups>
<add key="monthly" value="Monthly | Renews every month | #0E8F9C | PRD_aaa,PRD_bbb" />
<add key="annual" value="Annual | Renews once a year | #B5751A | PRD_ccc" />
</ProductGroups>Grouping is purely presentational — no server or license-model change is required.
We provide a complete sample WPF application demonstrating real-world usage patterns:
The WPF Sample Application demonstrates:
- License validation at application startup
- Handling different license states (Valid, Trial, Expired)
- Feature gating based on license status
- Integration with built-in license management UI
- Centralized license service pattern
// Example: Validate license at startup
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var context = _licenseService.ValidateLicense(
onLicFileNotFound: DownloadLicenseFile,
onTrialEnded: HandleTrialEnded
);
UpdateFeatureAccess(context.LicenseModel.Status);
}See the sample README for complete setup instructions.
- .NET Framework 4.8.1
- WPF (Windows Presentation Foundation)
- LicenseManagement.EndUser (dependency)
Version 2.0.0 introduces breaking changes: the namespace has been renamed from Hymma.Lm.EndUser.Wpf to LicenseManagement.EndUser.Wpf.
-
Update NuGet Package Reference
# Remove old package dotnet remove package Hymma.Lm.EndUser.Wpf # Add new package dotnet add package LicenseManagement.EndUser.Wpf
-
Update Namespace Imports in C# Replace all occurrences:
// Old using Hymma.Lm.EndUser.Wpf.Views; using Hymma.Lm.EndUser.Wpf.ViewModels; using Hymma.Lm.EndUser.Wpf.Converters; // New using LicenseManagement.EndUser.Wpf.Views; using LicenseManagement.EndUser.Wpf.ViewModels; using LicenseManagement.EndUser.Wpf.Converters;
-
Update XAML Namespaces
<!-- Old --> xmlns:views="clr-namespace:Hymma.Lm.EndUser.Wpf.Views;assembly=Hymma.Lm.EndUser.Wpf" <!-- New --> xmlns:views="clr-namespace:LicenseManagement.EndUser.Wpf.Views;assembly=LicenseManagement.EndUser.Wpf"
-
Update Resource Dictionary References
<!-- Old --> <ResourceDictionary Source="pack://application:,,,/Hymma.Lm.EndUser.Wpf;component/AppResources.xaml"/> <!-- New --> <ResourceDictionary Source="pack://application:,,,/LicenseManagement.EndUser.Wpf;component/AppResources.xaml"/>
| v1.x | v2.0.0 |
|---|---|
Hymma.Lm.EndUser.Wpf namespace |
LicenseManagement.EndUser.Wpf namespace |
Hymma.Lm.EndUser.Wpf.dll |
LicenseManagement.EndUser.Wpf.dll |
NuGet: Hymma.Lm.EndUser.Wpf |
NuGet: LicenseManagement.EndUser.Wpf |
LicenseControl- A new embeddable UserControl for integrating license management directly into your application's UI, as an alternative to the standaloneMainWindowdialog.
See CHANGELOG.md for version history and release notes.
MIT - See LICENSE for details.
- LicenseManagement.EndUser - Core end-user SDK (includes WiX Custom Action sample)
- LicenseManagement.EndUser.Avalonia - Avalonia UI version (cross-platform)
- LicenseManagement.Client - Server-side SDK for vendors