LicenseManagement.EndUser.Wpf
2.4.0
See the version list below for details.
Requires NuGet 2.5 or higher.
dotnet add package LicenseManagement.EndUser.Wpf --version 2.4.0
NuGet\Install-Package LicenseManagement.EndUser.Wpf -Version 2.4.0
<PackageReference Include="LicenseManagement.EndUser.Wpf" Version="2.4.0" />
<PackageVersion Include="LicenseManagement.EndUser.Wpf" Version="2.4.0" />
<PackageReference Include="LicenseManagement.EndUser.Wpf" />
paket add LicenseManagement.EndUser.Wpf --version 2.4.0
#r "nuget: LicenseManagement.EndUser.Wpf, 2.4.0"
#:package LicenseManagement.EndUser.Wpf@2.4.0
#addin nuget:?package=LicenseManagement.EndUser.Wpf&version=2.4.0
#tool nuget:?package=LicenseManagement.EndUser.Wpf&version=2.4.0
LicenseManagement.EndUser.Wpf
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.
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.
Features
- 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
Installation
dotnet add package LicenseManagement.EndUser.Wpf
Or via NuGet Package Manager:
Install-Package LicenseManagement.EndUser.Wpf
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.
Components
Views
| 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 |
Window vs UserControl
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.
ViewModels
| 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 |
Converters
| Converter | Description |
|---|---|
LicenseStatusConverter |
Converts LicenseStatusTitles to display strings |
BooleanToVisibilityConverter |
Standard bool to Visibility converter |
UtcToLocalTimeConverter |
Converts UTC DateTime to local time |
Commands
| Command | Description |
|---|---|
RelayCommand |
ICommand implementation for MVVM |
Validation Rules
| Rule | Description |
|---|---|
ReceiptCodeRule |
Validates receipt code format |
Quick Start
Show License Window (Dialog)
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();
Embed LicenseControl in Your UI
<Window xmlns:views="clr-namespace:LicenseManagement.EndUser.Wpf.Views;assembly=LicenseManagement.EndUser.Wpf">
<Grid>
<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"
};
Show Registration Dialog
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
}
Display License Status
using LicenseManagement.EndUser.Wpf.ViewModels;
var licenseVm = new LicenseViewModel
{
Status = LicenseStatusTitles.Valid,
ExpirationDate = DateTime.UtcNow.AddMonths(6),
ProductName = "My Product"
};
Use Converters in XAML
<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>
Include Resource Dictionary
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/LicenseManagement.EndUser.Wpf;component/AppResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Grouped product cards
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.
Layouts (ProductLayout)
| 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 |
Group in code
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.
Group via App.config (zero code)
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>
<add key="licenseLayout" value="Bands" />
</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.
Sample Application
We provide a complete sample WPF application demonstrating real-world usage patterns:
WPF Sample App
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.
Requirements
- .NET Framework 4.8.1
- WPF (Windows Presentation Foundation)
- LicenseManagement.EndUser (dependency)
Migrating from v1.x
Version 2.0.0 introduces breaking changes: the namespace has been renamed from Hymma.Lm.EndUser.Wpf to LicenseManagement.EndUser.Wpf.
Steps to Migrate
Update NuGet Package Reference
# Remove old package dotnet remove package Hymma.Lm.EndUser.Wpf # Add new package dotnet add package LicenseManagement.EndUser.WpfUpdate 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
xmlns:views="clr-namespace:Hymma.Lm.EndUser.Wpf.Views;assembly=Hymma.Lm.EndUser.Wpf" xmlns:views="clr-namespace:LicenseManagement.EndUser.Wpf.Views;assembly=LicenseManagement.EndUser.Wpf"Update Resource Dictionary References
<ResourceDictionary Source="pack://application:,,,/Hymma.Lm.EndUser.Wpf;component/AppResources.xaml"/> <ResourceDictionary Source="pack://application:,,,/LicenseManagement.EndUser.Wpf;component/AppResources.xaml"/>
What Changed
| 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 |
New in v2.0.0
LicenseControl- A new embeddable UserControl for integrating license management directly into your application's UI, as an alternative to the standaloneMainWindowdialog.
Changelog
See CHANGELOG.md for version history and release notes.
License
MIT - See LICENSE for details.
Related Packages
- 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
Documentation
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-windows7.0 is compatible. net9.0-windows was computed. net10.0-windows was computed. |
| .NET Framework | net481 is compatible. |
-
.NETFramework 4.8.1
- No dependencies.
-
net8.0-windows7.0
- LicenseManagement.EndUser (>= 3.3.0)
- System.Configuration.ConfigurationManager (>= 9.0.17)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
2.4.0: Machine identity v2 via LicenseManagement.EndUser 3.3.0 — the device id is now the per-install Windows MachineGuid fingerprint, fixing cross-machine id collisions (shared CPU model + placeholder OEM board serials) that could show another customer's computer name and trial state in the license window; existing installs are re-keyed server-side, no user action needed. 2.3.4: Clearer status labels — "Unverified"→"Couldn't verify", "Expired"→"File Expired", "Renewal needed"→"Subscription Ended", "Not registered"→"Computer Unregistered" (and the matching meta line). 2.3.3: Cards now load their licence state asynchronously with a per-card spinner — the window paints immediately, never freezes, and each card shows a "Checking license…" spinner while it (or a Check/Register/Unregister action) runs. 2.3.2: The window no longer reads every product's licence on open (which blocked the UI thread and, for non-valid states, hit the server, leaving the window painted-but-frozen for a beat). Cards a host has already validated are shown immediately via UpdateLicenseSnapshot; the rest load on demand when opened. 2.3.1: Fixes on top of 2.3.0's grouped-card UI. MainWindow now renders products when License is assigned in code (a bare {Binding} resolved against the control's own default DataContext, so a code-set License never reached the control). Product cards now stretch to fill the window instead of sitting at a fixed width with dead space. Buttons gained real hover and pressed states. All product statuses load on open (offline per-product read) instead of only the first card. The validity meter no longer reads ~0% when a server date is missing — a default(DateTime) period start is treated as unknown rather than spanning ~2000 years. 2.3.0: Redesigned license UI — products render as grouped cards (Bands / Lanes / Switcher) with per-card status, validity meter and actions; group via LicenseViewModel.ApplyGrouping(...) or App.config. Existing LicenseViewModel.License / FromContext usage is unchanged.