CG.Infrastructure.Presentation
3.10.5
dotnet add package CG.Infrastructure.Presentation --version 3.10.5
NuGet\Install-Package CG.Infrastructure.Presentation -Version 3.10.5
<PackageReference Include="CG.Infrastructure.Presentation" Version="3.10.5" />
<PackageVersion Include="CG.Infrastructure.Presentation" Version="3.10.5" />
<PackageReference Include="CG.Infrastructure.Presentation" />
paket add CG.Infrastructure.Presentation --version 3.10.5
#r "nuget: CG.Infrastructure.Presentation, 3.10.5"
#:package CG.Infrastructure.Presentation@3.10.5
#addin nuget:?package=CG.Infrastructure.Presentation&version=3.10.5
#tool nuget:?package=CG.Infrastructure.Presentation&version=3.10.5
Infrastructure.Presentation
A .NET WPF library that provides base view models, custom controls, and presentation layer infrastructure for building modern Windows desktop applications with the MVVM pattern.
Overview
Infrastructure.Presentation is a .NET 9.0 Windows library designed to accelerate WPF application development by providing common presentation layer components, base classes, and custom controls. It integrates with the infrastructure ecosystem to deliver a consistent development experience across your applications.
Features
- Base View Models: Pre-built base classes for common MVVM patterns
BaseViewModel
: Core base class with initialization and disposal supportDialogBaseViewModel
: Base class for dialog-based view modelsModalDialogBaseViewModel
: Base class for modal dialog view models
- Custom Controls: Reusable WPF controls for consistent UI/UX
NavigationButtonControl
: Navigation button control with custom styling
- Behaviors: WPF behaviors for enhanced functionality
DataGridColumnsBehavior
: Behavior for binding DataGrid columnsElementLoadingBehavior
: Behavior for element loading events
- Services: Presentation layer services
ResourceDictionaryService
: Service for managing resource dictionariesCultureService
: Service for culture and localizationSecureService
: Service for secure operationsPasswordBoxWrapper
: Wrapper for password box functionality
- Converters: Value converters for data binding
- Boolean to Visibility, TimeSpan, Date, and other common conversions
- Extensions: Extension methods for dependency injection and other services
- Dialogs: Pre-built dialog components for common UI patterns
- Enums: Enumeration types for consistent application behavior
- Headers: Message header definitions for consistent communication
- Resources: Resource definitions for UI components
- Dictionaries: Resource dictionaries for controls, converters, and styles
- MVVM Toolkit Integration: Built on CommunityToolkit.Mvvm for modern MVVM development
- Modern UI Framework: MahApps.Metro integration for Metro-style applications
- Logging Support: Integrated logging capabilities for presentation layer debugging
- Service Integration: Leverages core infrastructure services for dependency injection
- Windows-Specific: Optimized for Windows desktop applications
Target Framework
- .NET 9.0 Windows (WPF)
Dependencies
Core Dependencies
- CG.Infrastructure.Core (3.10.8) - Core infrastructure components and service extensions
- CG.Infrastructure.Services (3.10.3) - Service layer abstractions and implementations
MVVM Framework
- CommunityToolkit.Mvvm (8.4.0) - Modern MVVM toolkit with source generators
UI Framework
- MahApps.Metro (2.4.10) - Metro-style UI controls and themes for WPF
Logging
- Microsoft.Extensions.Logging (9.0.8) - Logging framework for .NET
Package Information
- Package ID: CG.Infrastructure.Presentation
- Version: 3.10.3
- Authors: Matthew Evans
- Company: Matthew Evans
- Product: CG.Infrastructure.Presentation
- Description: Infra Presentation library with base viewmodels and custom controls
- GeneratePackageOnBuild: False (not configured in project file)
Components
ViewModels
BaseViewModel
: Abstract base class that provides common functionality for all view models including initialization, disposal, and thread-safe UI updatesDialogBaseViewModel
: Base class for dialog-based view models with dialog result handlingModalDialogBaseViewModel
: Base class for modal dialog view models with modal-specific functionality
Custom Controls
NavigationButtonControl
: Custom button control designed for navigation purposes with enhanced styling and behavior
Behaviors
DataGridColumnsBehavior
: Attached behavior for binding DataGrid columns to observable collections with automatic column managementElementLoadingBehavior
: Behavior for handling element loading events in WPF applications
Services
ResourceDictionaryService
: Service for managing and merging resource dictionaries dynamicallyCultureService
: Service for handling culture changes and localizationSecureService
: Service for secure operations and data handlingPasswordBoxWrapper
: Wrapper class for password box functionality with secure password handling
Converters
BoolVisibilityConverter
: Converts boolean values to Visibility enum valuesDateOffsetToDateConverter
: Converts DateTimeOffset to DateTimeEnumValuesConverter
: Converts enum values for bindingFlyoutPositionConverter
: Converts flyout positions for MahApps.MetroFlyoutThemeConverter
: Converts flyout themes for MahApps.MetroHeaderConverter
: Converts header values for displayIntToMonthConverter
: Converts integer values to month namesNullToBoolConverter
: Converts null values to booleanNullToVisibilityConverter
: Converts null values to VisibilityPasswordConverter
: Converts password values securelyTimeSpanConverter
: Converts TimeSpan valuesTimeSpanHoursConverter
: Converts TimeSpan to hours representation
Extensions
ServiceCollectionExtensions
: Extension methods for Microsoft.Extensions.DependencyInjection
Dialogs
ModalMessageDialog
: Standard modal message dialog with customizable contentModalCustomMessageDialog
: Custom modal dialog for specialized message display
Enums
DialogResponseEnum
: Enumeration for dialog response valuesDialogTypeEnum
: Enumeration for dialog typesFlyoutsPositionEnum
: Enumeration for flyout positions in MahApps.MetroFlyoutsThemeEnum
: Enumeration for flyout themes in MahApps.Metro
Headers
MessageHeaders
: Message header definitions for consistent communication
Resources
UIResources
: UI resource definitionsToolTipResources
: Tooltip resource definitions
Dictionaries
- Controls/: Control-specific resource dictionaries
- Converters/: Converter-specific resource dictionaries
- CustomControls/: Custom control resource dictionaries
- Styles/: Style resource dictionaries
Getting Started
Installation
dotnet add package CG.Infrastructure.Presentation
Basic Setup
<Application x:Class="YourApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
// Program.cs or App.xaml.cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
var services = new ServiceCollection();
// Add logging
services.AddLogging(builder =>
{
builder.AddConsole();
builder.AddDebug();
});
// Add your services
services.AddSingleton<IMainViewModel, MainViewModel>();
services.AddSingleton<MainWindow>();
var serviceProvider = services.BuildServiceProvider();
Usage Examples
Base View Model
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
public partial class MainViewModel : ObservableObject
{
private readonly ILogger<MainViewModel> _logger;
[ObservableProperty]
private string _title = "Main Window";
[ObservableProperty]
private bool _isLoading;
[ObservableProperty]
private string _statusMessage = string.Empty;
public MainViewModel(ILogger<MainViewModel> logger)
{
_logger = logger;
}
[RelayCommand]
private async Task LoadDataAsync()
{
try
{
IsLoading = true;
StatusMessage = "Loading data...";
_logger.LogInformation("Starting data load operation");
// Simulate async operation
await Task.Delay(2000);
StatusMessage = "Data loaded successfully";
_logger.LogInformation("Data load completed successfully");
}
catch (Exception ex)
{
StatusMessage = "Error loading data";
_logger.LogError(ex, "Failed to load data");
}
finally
{
IsLoading = false;
}
}
[RelayCommand]
private void ClearStatus()
{
StatusMessage = string.Empty;
_logger.LogDebug("Status message cleared");
}
}
Custom Control Example
using System.Windows;
using System.Windows.Controls;
namespace YourApp.Controls
{
public class CustomButton : Button
{
static CustomButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomButton),
new FrameworkPropertyMetadata(typeof(CustomButton)));
}
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register(nameof(Icon), typeof(string), typeof(CustomButton),
new PropertyMetadata(string.Empty));
public string Icon
{
get => (string)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
}
}
Metro-Style Window
<Controls:MetroWindow x:Class="YourApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
Title="{Binding Title}"
Height="450" Width="800"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="20,20,20,10">
<TextBlock Text="Welcome to Your App"
FontSize="24"
FontWeight="Bold"
HorizontalAlignment="Center"/>
</StackPanel>
<ScrollViewer Grid.Row="1" Margin="20,10">
<StackPanel>
<Button Content="Load Data"
Command="{Binding LoadDataCommand}"
Style="{StaticResource MahApps.Styles.Button.Square}"
Margin="0,10"/>
<ProgressBar IsIndeterminate="{Binding IsLoading}"
Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}"
Margin="0,10"/>
<TextBlock Text="{Binding StatusMessage}"
Style="{StaticResource MahApps.Styles.TextBlock}"
Margin="0,10"/>
</StackPanel>
</ScrollViewer>
<StackPanel Grid.Row="2" Margin="20,10,20,20">
<Button Content="Clear Status"
Command="{Binding ClearStatusCommand}"
Style="{StaticResource MahApps.Styles.Button.Square.Transparent}"
HorizontalAlignment="Right"/>
</StackPanel>
</Grid>
</Controls:MetroWindow>
Service Integration
public class UserService
{
private readonly ILogger<UserService> _logger;
private readonly IHttpClientFactory _httpClientFactory;
public UserService(ILogger<UserService> logger, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
public async Task<List<User>> GetUsersAsync()
{
try
{
_logger.LogInformation("Fetching users from API");
var client = _httpClientFactory.CreateClient();
var response = await client.GetAsync("api/users");
response.EnsureSuccessStatusCode();
var users = await response.Content.ReadFromJsonAsync<List<User>>();
_logger.LogInformation("Successfully retrieved {Count} users", users?.Count ?? 0);
return users ?? new List<User>();
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to retrieve users");
throw;
}
}
}
// Register in DI container
services.AddHttpClient();
services.AddScoped<UserService>();
Advanced Features
Custom Theme Support
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="CustomPrimaryBrush" Color="#FF1976D2"/>
<SolidColorBrush x:Key="CustomAccentBrush" Color="#FFFF5722"/>
<Style x:Key="CustomButtonStyle" TargetType="Button" BasedOn="{StaticResource MahApps.Styles.Button.Square}">
<Setter Property="Background" Value="{StaticResource CustomPrimaryBrush}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="{StaticResource CustomPrimaryBrush}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource CustomAccentBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource CustomAccentBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Data Binding with Validation
public partial class UserViewModel : ObservableValidator
{
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[MinLength(2)]
[MaxLength(50)]
private string _firstName = string.Empty;
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[EmailAddress]
private string _email = string.Empty;
[ObservableProperty]
[NotifyDataErrorInfo]
[Range(18, 120)]
private int _age;
[RelayCommand(CanExecute = nameof(CanSave))]
private async Task SaveAsync()
{
ValidateAllProperties();
if (HasErrors)
{
return;
}
// Save logic here
await Task.CompletedTask;
}
private bool CanSave() => !HasErrors;
}
Custom Control Templates
<ControlTemplate x:Key="CustomButtonTemplate" TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="8">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="{TemplateBinding Padding}"/>
</Border>
</ControlTemplate>
Best Practices
- MVVM Pattern: Always separate view logic from business logic using view models
- Dependency Injection: Use constructor injection for services and dependencies
- Async Operations: Use async/await for I/O operations and update UI accordingly
- Logging: Include meaningful log messages for debugging and monitoring
- Error Handling: Implement proper error handling with user-friendly messages
- Resource Management: Use resource dictionaries for consistent styling
- Data Binding: Prefer data binding over code-behind for UI updates
- Testing: Write unit tests for view models and business logic
Testing
The library includes comprehensive unit tests covering all major components:
- Test Framework: xUnit with FluentAssertions for readable assertions
- Mocking: Moq for creating test doubles
- WPF Testing: Custom TestBase class providing STA thread context for WPF component testing
- Test Coverage: 328 tests covering ViewModels, Behaviors, Services, and Custom Controls
Test Structure
- ViewModels/: Tests for BaseViewModel, DialogBaseViewModel, and ModalDialogBaseViewModel
- Behaviors/: Tests for DataGridColumnsBehavior and ElementLoadingBehavior
- Services/: Tests for ResourceDictionaryService, CultureService, and other services
- CustomControls/: Tests for NavigationButtonControl
- Converters/: Tests for value converters
- Extensions/: Tests for extension methods
View Model Testing
[Test]
public async Task LoadDataCommand_WhenExecuted_UpdatesStatusAndLoadingState()
{
// Arrange
var mockLogger = new Mock<ILogger<MainViewModel>>();
var viewModel = new MainViewModel(mockLogger.Object);
// Act
await viewModel.LoadDataCommand.ExecuteAsync(null);
// Assert
Assert.That(viewModel.IsLoading, Is.False);
Assert.That(viewModel.StatusMessage, Is.EqualTo("Data loaded successfully"));
}
[Test]
public void ClearStatusCommand_WhenExecuted_ClearsStatusMessage()
{
// Arrange
var mockLogger = new Mock<ILogger<MainViewModel>>();
var viewModel = new MainViewModel(mockLogger.Object);
viewModel.StatusMessage = "Some status";
// Act
viewModel.ClearStatusCommand.Execute(null);
// Assert
Assert.That(viewModel.StatusMessage, Is.Empty);
}
Contributing
This project is part of the CG Infrastructure Libraries. For contributions, please refer to the main infrastructure repository guidelines.
License
See the LICENSE file in the root directory for licensing information.
Support
For issues and questions related to this library, please contact the development team or create an issue in the project repository.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0-windows7.0 is compatible. net10.0-windows was computed. |
-
net9.0-windows7.0
- CG.Infrastructure.Core (>= 3.10.8)
- CG.Infrastructure.Services (>= 3.10.6)
- CommunityToolkit.Mvvm (>= 8.4.0)
- MahApps.Metro (>= 2.4.10)
- Microsoft.Extensions.Logging (>= 9.0.8)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on CG.Infrastructure.Presentation:
Package | Downloads |
---|---|
CG.Platform.Presentation
Platform Presentation library with shared services |
|
CG.Platform.ViewModels
Platform view models library with shared services |
|
CG.Platform.Views
Platform views library with shared services |
|
CG.Infrastructure.Navigating
Infra Navigating library with shared services and base viewmodels |
|
CG.Infrastructure.Navigation
Infra Navigation library with shared services and base viewmodels |
GitHub repositories
This package is not used by any popular GitHub repositories.