Skip to content
Skillpedia
APIs & servers (backend)40k · #5245

mvvm-toolkit-di

Helps your agent connect parts of .NET applications. It manages how components communicate and are created.

What it does

This 'skill' helps connect parts of your code (called ViewModels) with other parts that provide services (like saving files or sending messages) in an organized way. It uses a system called 'Dependency Injection' so the right parts find each other automatically.

When to use it

  • ✓When you're setting up a new app with a graphical interface (WPF, MAUI, etc.) and need to organize how different parts of your program talk to each other.
  • ✓To decide how long a service or ViewModel should exist (forever, only when needed, etc.).
  • ✓To ensure message communication between app parts is set up correctly and available where needed.

Example of what to ask your AI

“How do I set up my app so it knows how to create and provide my ViewModels and services?”

Want more? Open the sections below.

How to use

The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.

Skill link

https://github.com/github/awesome-copilot/blob/main/skills/mvvm-toolkit-di/SKILL.md

Ready-to-paste message

Use this skill to help me: https://github.com/github/awesome-copilot/blob/main/skills/mvvm-toolkit-di/SKILL.md Read the SKILL.md file at that link and follow its instructions for my task.
How it works

It uses a system called 'Dependency Injection' that acts like an organizer. You tell it what services exist and how to create them, and it handles delivering them automatically to where they are needed, usually through the constructors of classes.

Installation

Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.

In the terminal (Claude Code, Codex, Cursor), in your project folder:

npx skills add github/awesome-copilot --skill mvvm-toolkit-di

Or download just the file:

curl -L https://raw.githubusercontent.com/github/awesome-copilot/main/skills/mvvm-toolkit-di/SKILL.md -o SKILL.md
Technical content (original SKILL.md)

Original text by the author, straight from GitHub.

CommunityToolkit.Mvvm + Microsoft.Extensions.DependencyInjection

The MVVM Toolkit deliberately ships no DI container — it composes with Microsoft.Extensions.DependencyInjection, the same container ASP.NET Core, Worker services, and the .NET Generic Host use.

TL;DR. Build the service provider once at startup (prefer Host.CreateDefaultBuilder()). Register services and ViewModels. Inject through constructors. Avoid Ioc.Default.GetService<T>() in user code.


When to use this skill

  • Standing up the composition root for a new XAML app (WPF, WinUI 3, MAUI, Uno, Avalonia)
  • Choosing service/VM lifetimes
  • Wiring IMessenger once and injecting it into ObservableRecipient ViewModels
  • Resolving a page's ViewModel without coupling to a service locator
  • Diagnosing "Unable to resolve service for type X while attempting to activate Y"

For source generators and ViewModel patterns see the mvvm-toolkit skill. For Messenger pub/sub see mvvm-toolkit-messenger.


Recommended composition root (Generic Host)

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using CommunityToolkit.Mvvm.Messaging;

public partial class App : Application
{
    public IHost Host { get; }

    public App()
    {
        Host = Microsoft.Extensions.Hosting.Host
            .CreateDefaultBuilder()
            .ConfigureServices((_, services) =>
            {
                services.AddSingleton<IFilesService, FilesService>();
                services.AddSingleton<ISettingsService, SettingsService>();
                services.AddSingleton<IMessenger>(WeakReferenceMessenger.Default);

                services.AddSingleton<ShellViewModel>();
                services.AddTransient<ContactViewModel>();
                services.AddTransient<EditorViewModel>();
            })
            .Build();
    }

    public static T GetService<T>() where T : class =>
        ((App)Current).Host.Services.GetRequiredService<T>();
}

Generic Host benefits:

  • appsettings.json binding via Microsoft.Extensions.Configuration
  • Logging via Microsoft.Extensions.Logging
  • Hosted services (IHostedService) for background work
  • Scope validation in development builds

WPF and Windows Forms must integrate the host lifetime with the app lifetime — see Use the .NET Generic Host in a WPF app.

Without Generic Host

When you only need a service container and want zero extra dependencies:

var services = new ServiceCollection();
services.AddSingleton<IFilesService, FilesService>();
services.AddTransient<ContactViewModel>();
ServiceProvider provider = services.BuildServiceProvider();

Constructor injection

Inject services and child ViewModels through the constructor:

public sealed partial class ContactViewModel(
    IFilesService files,
    IMessenger messenger,
    ILogger<ContactViewModel> logger)
    : ObservableRecipient(messenger)
{
    [ObservableProperty]
    private string? name;

    [RelayCommand]
    private async Task SaveAsync()
    {
        logger.LogInformation("Saving {Name}", Name);
        await files.SaveAsync(Name!);
    }
}

Why constructor injection beats a service locator:

  • Dependencies are explicit and visible at the call site
  • Unit tests inject fakes/mocks directly
  • The DI container validates the dependency graph at startup
  • Missing registrations throw immediately, not at first use

Lifetimes

Lifetime Method Typical use in XAML apps
Singleton AddSingleton<T> Shell/main-window VM, settings, file/HTTP services, the shared IMessenger, app-wide caches
Transient AddTransient<T> Per-page or per-document ViewModels (a fresh instance every resolve)
Scoped AddScoped<T> Rarely needed in client apps; useful with explicit IServiceScope (e.g., per-window scopes)
services.AddSingleton<ShellViewModel>();   // 1 instance for app lifetime
services.AddTransient<NoteViewModel>();    // new instance per resolve
services.AddScoped<DialogService>();       // 1 per scope (rare)

Resolving in a View

Resolve the page's root ViewModel in code-behind, then let it pull its own dependencies:

public sealed partial class ContactPage : Page
{
    public ContactViewModel ViewModel { get; }


…
FAQ

What is 'Dependency Injection'?

It's a way to organize your code where, instead of a class creating its own dependencies (other classes it needs), those dependencies are 'injected' (provided) from the outside. This makes code more flexible and easier to test.

What's the difference between Singleton, Transient, and Scoped?

Singleton: only one instance exists for the entire app lifetime. Transient: a new instance is created every time it's requested. Scoped: an instance is created per specific 'scope', like a window or a request (less common in desktop apps).

Why shouldn't I create my ViewModels manually?

Manual creation can lead to code that's harder to manage and test. Using 'Dependency Injection' ensures dependencies are resolved correctly, and you don't have to worry about how to create them every time.

Details

Original description by the author

Wire CommunityToolkit.Mvvm ViewModels into Microsoft.Extensions.DependencyInjection. Covers the .NET Generic Host composition root, constructor injection, service lifetimes (Singleton / Transient / Scoped), IMessenger registration, resolving ViewModels in Views, keyed services, testing seams, and the legacy Ioc.Default escape hatch. Use across WPF, WinUI 3, .NET MAUI, Uno, and Avalonia.

repo: github/awesome-copilot

Popularity

GitHub stars
40k
Ranking position
#5245
License
MIT
Updated
10/15/2026

Is this skill useful?

0

Sign in to vote.

Comments

  • …

More skills from this repository

Similar skills