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
                    
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="CG.Infrastructure.Presentation" Version="3.10.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CG.Infrastructure.Presentation" Version="3.10.5" />
                    
Directory.Packages.props
<PackageReference Include="CG.Infrastructure.Presentation" />
                    
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 CG.Infrastructure.Presentation --version 3.10.5
                    
#r "nuget: CG.Infrastructure.Presentation, 3.10.5"
                    
#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 CG.Infrastructure.Presentation@3.10.5
                    
#: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=CG.Infrastructure.Presentation&version=3.10.5
                    
Install as a Cake Addin
#tool nuget:?package=CG.Infrastructure.Presentation&version=3.10.5
                    
Install as a Cake Tool

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 support
    • DialogBaseViewModel: Base class for dialog-based view models
    • ModalDialogBaseViewModel: 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 columns
    • ElementLoadingBehavior: Behavior for element loading events
  • Services: Presentation layer services
    • ResourceDictionaryService: Service for managing resource dictionaries
    • CultureService: Service for culture and localization
    • SecureService: Service for secure operations
    • PasswordBoxWrapper: 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 updates
  • DialogBaseViewModel: Base class for dialog-based view models with dialog result handling
  • ModalDialogBaseViewModel: 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 management
  • ElementLoadingBehavior: Behavior for handling element loading events in WPF applications

Services

  • ResourceDictionaryService: Service for managing and merging resource dictionaries dynamically
  • CultureService: Service for handling culture changes and localization
  • SecureService: Service for secure operations and data handling
  • PasswordBoxWrapper: Wrapper class for password box functionality with secure password handling

Converters

  • BoolVisibilityConverter: Converts boolean values to Visibility enum values
  • DateOffsetToDateConverter: Converts DateTimeOffset to DateTime
  • EnumValuesConverter: Converts enum values for binding
  • FlyoutPositionConverter: Converts flyout positions for MahApps.Metro
  • FlyoutThemeConverter: Converts flyout themes for MahApps.Metro
  • HeaderConverter: Converts header values for display
  • IntToMonthConverter: Converts integer values to month names
  • NullToBoolConverter: Converts null values to boolean
  • NullToVisibilityConverter: Converts null values to Visibility
  • PasswordConverter: Converts password values securely
  • TimeSpanConverter: Converts TimeSpan values
  • TimeSpanHoursConverter: Converts TimeSpan to hours representation

Extensions

  • ServiceCollectionExtensions: Extension methods for Microsoft.Extensions.DependencyInjection

Dialogs

  • ModalMessageDialog: Standard modal message dialog with customizable content
  • ModalCustomMessageDialog: Custom modal dialog for specialized message display

Enums

  • DialogResponseEnum: Enumeration for dialog response values
  • DialogTypeEnum: Enumeration for dialog types
  • FlyoutsPositionEnum: Enumeration for flyout positions in MahApps.Metro
  • FlyoutsThemeEnum: Enumeration for flyout themes in MahApps.Metro

Headers

  • MessageHeaders: Message header definitions for consistent communication

Resources

  • UIResources: UI resource definitions
  • ToolTipResources: 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

  1. MVVM Pattern: Always separate view logic from business logic using view models
  2. Dependency Injection: Use constructor injection for services and dependencies
  3. Async Operations: Use async/await for I/O operations and update UI accordingly
  4. Logging: Include meaningful log messages for debugging and monitoring
  5. Error Handling: Implement proper error handling with user-friendly messages
  6. Resource Management: Use resource dictionaries for consistent styling
  7. Data Binding: Prefer data binding over code-behind for UI updates
  8. 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 Compatible and additional computed target framework versions.
.NET net9.0-windows7.0 is compatible.  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 (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.

Version Downloads Last Updated
3.10.5 56 8/16/2025
3.10.4 135 8/14/2025
3.10.3 128 8/10/2025
3.10.2 496 7/23/2025
3.10.1 143 7/16/2025
3.10.0 141 7/16/2025
3.9.0 129 12/10/2024
2.0.0 179 8/18/2024
1.0.2 308 2/16/2023
1.0.1 482 7/13/2022
1.0.0 462 5/27/2022