MR
Mayur Rathi
@github
⭐ 34.1k GitHub stars

Mvvm-Toolkit-Messenger

Mvvm-Toolkit-Messenger是一款code方向的AI技能,核心价值是CommunityToolkit,可用于解决开发者在code领域的实际问题,帮助用户提升效率、自动化重复任务或优化工作流。

CommunityToolkit.Mvvm Messenger pub/sub for decoupled communication between ViewModels (or any objects). Covers WeakReferenceMessenger vs StrongReferenceMessenger, IRecipient<TMessage>, RequestMessage

Last verified on: 2026-05-30
mkdir -p ./skills/mvvm-toolkit-messenger && curl -sfL https://raw.githubusercontent.com/github/awesome-copilot/main/skills/mvvm-toolkit-messenger/SKILL.md -o ./skills/mvvm-toolkit-messenger/SKILL.md

Run in terminal / PowerShell. Requires curl (Unix) or PowerShell 5+ (Windows).

Skill Content

# CommunityToolkit.Mvvm Messenger


Pub/sub messaging for ViewModels (or any objects) without forcing a shared

reference graph. Part of `CommunityToolkit.Mvvm` 8.x.


> **TL;DR.** Default to `WeakReferenceMessenger.Default`. Register handlers

> with the `(recipient, message)` lambda and the `static` modifier so you

> never capture `this`. Inherit from `ObservableRecipient` and toggle

> `IsActive` at activation/deactivation to get automatic register/unregister.


---


When to use this skill


- Two or more ViewModels need to react to an event (login, theme change,

save, navigation) without holding references to each other

- A ViewModel needs to ask another VM for a value (request/reply)

- You're scoping events to a sub-system or window with channel tokens

- Diagnosing "my handler never fires" or weak-reference recipient lifetime

problems


For source generators, base classes, and commands see the **`mvvm-toolkit`**

skill. For DI wiring (registering an `IMessenger` instance), see

**`mvvm-toolkit-di`**.


---


Choose an implementation


| Type | When |

|------|------|

| `WeakReferenceMessenger.Default` | **Default.** Recipients held weakly — eligible for GC even while registered. Internal trimming runs during full GCs; no manual `Cleanup()` needed. |

| `StrongReferenceMessenger.Default` | Profiler shows the messenger is hot and allocation matters. Recipients are pinned until you `Unregister`. Forgetting unregistration leaks them. |

| Custom `IMessenger` instance | Per-window/per-scope (e.g., one messenger per app window). Construct directly, inject via DI. |


`ObservableRecipient`'s parameterless constructor uses

`WeakReferenceMessenger.Default`. Pass a different `IMessenger` to its

constructor to override.


---


Define a message


The toolkit ships base classes; any class works.


csharp
using CommunityToolkit.Mvvm.Messaging.Messages;

// Single-payload broadcast
public sealed class LoggedInUserChangedMessage(User user)
    : ValueChangedMessage<User>(user);

// Custom shape (records are great for this)
public sealed record ThemeChangedMessage(AppTheme NewTheme);

// Empty signal
public sealed record RefreshRequestedMessage;

---


Register a recipient


Lambda style (recommended)


csharp
WeakReferenceMessenger.Default.Register<MyViewModel, ThemeChangedMessage>(
    this,
    static (recipient, message) => recipient.OnThemeChanged(message.NewTheme));

The `static` modifier prevents accidental closure allocation and keeps

`this` out of the lambda — use the `recipient` parameter instead.


`IRecipient<TMessage>` interface style


csharp
public sealed class MyViewModel : ObservableRecipient,
    IRecipient<ThemeChangedMessage>,
    IRecipient<RefreshRequestedMessage>
{
    public void Receive(ThemeChangedMessage message) { /* ... */ }
    public void Receive(RefreshRequestedMessage message) { /* ... */ }
}

`ObservableRecipient.OnActivated()` calls `Messenger.RegisterAll(this)`,

which subscribes every `IRecipient<T>` interface implemented by the type.

If you're not using `ObservableRecipient`, register manually:


csharp
WeakReferenceMessenger.Default.RegisterAll(this);

---


Send a message


csharp
WeakReferenceMessenger.Default.Send(new ThemeChangedMessage(AppTheme.Dark));

// Empty payloads use the parameterless overload:
WeakReferenceMessenger.Default.Send<RefreshRequestedMessage>();

---


Channels (tokens)


Scope messages to a sub-system or window with a token (any equatable

value — `int`, `string`, `Guid`):


csharp
const int LeftPaneChannel = 1;

WeakReferenceMessenger.Default.Register<MyViewModel, RefreshRequestedMessage, int>(
    this, LeftPaneChannel,
    static (r, _) => r.RefreshLeft());

WeakReferenceMessenger.Default.Send(new RefreshRequestedMessage(), LeftPaneChannel);

Messages sent without a token use the default shared channel — they are

**not** delivered to channel-scoped recipients.


---


Request / reply


For ask-style scenarios where a recipient provid

🎯 Best For

  • Claude users
  • GitHub Copilot users
  • Software engineers
  • Development teams
  • Tech leads

💡 Use Cases

  • Code quality improvement
  • Best practice enforcement

📖 How to Use This Skill

  1. 1

    Install the Skill

    Copy the install command from the Terminal tab and run it. The SKILL.md file downloads to your local skills directory.

  2. 2

    Load into Your AI Assistant

    Open Claude or GitHub Copilot and reference the skill. Paste the SKILL.md content or use the system prompt tab.

  3. 3

    Apply Mvvm-Toolkit-Messenger to Your Work

    Open your project in the AI assistant and ask it to apply the skill. Start with a small module to verify the output quality.

  4. 4

    Review and Refine

    Review AI suggestions before committing. Run tests, check for regressions, and iterate on the skill output.

❓ Frequently Asked Questions

Is Mvvm-Toolkit-Messenger compatible with Cursor and VS Code?

Yes — this skill works with any AI coding assistant including Cursor, VS Code with Copilot, and JetBrains IDEs.

Do I need specific dependencies for Mvvm-Toolkit-Messenger?

Check the install command and Works With section. Most code skills only require the AI assistant and your codebase.

How do I install Mvvm-Toolkit-Messenger?

Copy the install command from the Terminal tab and run it. The skill downloads to ./skills/mvvm-toolkit-messenger/SKILL.md, ready to use.

Can I customize this skill for my team?

Absolutely. Edit the SKILL.md file to add team-specific instructions, examples, or workflows.

⚠️ Common Mistakes to Avoid

Skipping validation

Always test AI-generated code changes, even for simple refactors.

Missing dependency updates

Check if the skill requires updated dependencies or new packages.

🔗 Related Skills