csharp-scripts
Run file-based C# apps with the .NET CLI when the user explicitly wants C#/.NET code without creating a project. Use for C# language/API experiments, one-file…
Share state between components that don't have a direct parent-child parameter relationship, using cascading values, scoped services with change events, or CascadingValueSource via DI. USE WHEN the user needs a CascadingParameter or CascadingValue that works across render mode
$ npx -y skills add dotnet/skills --skill coordinate-components --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/coordinate-componentsContext preview
The summary Claude sees to decide when to auto-load this skill.
Share state between components that don't have a direct parent-child parameter relationship, using cascading values, scoped services with change events, or CascadingValueSource via DI. USE WHEN the user needs a CascadingParameter or CascadingValue that works across render mode
license: MIT name: coordinate-components description: > Share state between components that don't have a direct parent-child parameter relationship, using cascading values, scoped services with change events, or CascadingValueSource via DI. USE WHEN the user needs a CascadingParameter or CascadingValue that works across render mode boundaries, a shopping cart or notification count accessible from multiple pages, a theme or user preference cascaded app-wide, or when components in different parts of the tree must react when shared data changes. Also USE WHEN cascading values aren't reaching interactive children in per-page interactivity mode, or when the user needs to understand scoped vs singleton service lifetime for state on Blazor Server. DO NOT USE for direct parent-child parameter passing or EventCallback (see author-component), for persisting state across prerender-to-interactive transitions (see support-prerendering), or for service abstractions for data fetching in Auto/WebAssembly (see fetch-and-send-data).
Read `AGENTS.md` at the workspace root to learn the project's conventions before making changes.
| Need | Mechanism | When to use | |------|-----------|-------------| | Subtree (same render mode) | `CascadingValue` component | Theme, layout config within a layout | | App-wide (all render modes) | `CascadingValueSource<T>` via DI | Current user, feature flags, theme shared globally | | Mutable shared state within a circuit | Scoped service + `Action` event | Shopping cart, notification count, selected filters |
For parent→child one level: use `[Parameter]` / `EventCallback` (see `author-component` skill). For persisting state across prerender→interactive: see `support-prerendering` skill.
1. Choose the mechanism from the table in Step 2 2. If crossing render mode boundaries → use `CascadingValueSource<T>` (Step 4) 3. Register in `Program.cs` with `AddCascadingValue(...)` and `isFixed: false` 4. Consume via `[CascadingParameter]` in child components 5. Update via `NotifyChangedAsync(newValue)` — never page reload 6. For additional mutable state within a circuit → add scoped service (Step 5) 7. Wrap any `StateHasChanged` from background threads in `InvokeAsync` 8. Implement `IDisposable` — dispose timers, cancel tokens, unsubscribe events
Wrap a subtree with `<CascadingValue>` to flow data to all descendants without passing it through every intermediate component.
@* In a layout or parent component *@
<CascadingValue Value="theme">
@Body
</CascadingValue>
@code {
private ThemeInfo theme = new() { ButtonClass = "btn-primary" };
}Consume in any descendant:
[CascadingParameter]
private ThemeInfo? Theme { get; set; }**Rules:**
<CascadingValue Value="primary" Name="PrimaryTheme">...</CascadingValue>
[CascadingParameter(Name = "PrimaryTheme")]
private ThemeInfo? Primary { get; set; }Register a `CascadingValueSource<T>` in DI when the value must be available to **all components regardless of render mode**.
// Program.cs
builder.Services.AddCascadingValue(sp =>
{
var theme = new ThemeInfo { ButtonClass = "btn-primary" };
return new CascadingValueSource<ThemeInfo>(theme, isFixed: false);
});Consume identically to Step 3:
[CascadingParameter]
private ThemeInfo? Theme { get; set; }**To update and notify subscribers**, either mutate the existing object or replace it:
@* Component that changes the theme *@
@inject CascadingValueSource<ThemeInfo> ThemeSource
<button @onclick="ToggleDarkMode">Toggle theme</button>
@code {
private bool isDark;
private async Task ToggleDarkMode()
{
isDark = !isDark;
// Replace the value entirely:
var newTheme = new ThemeInfo { ButtonClass = isDark ? "btn-dark" : "btn-primary" };
await ThemeSource.NotifyChangedAsync(newTheme);
}
}`NotifyChangedAsync()` (no argument) also works — mutate the object and then call it. `NotifyChangedAsync(newValue)` replaces the value and notifies in one step.
**Update protocol:** Whenever shared state changes, the component that changes it MUST inject `CascadingValueSource<T>` and call `NotifyChangedAsync()`. This is the only mechanism that triggers re-rendering in all `[CascadingParameter]` subscribers. Without this call, no subscribers update. Do not use `NavigationManager.Refresh()` or page reloads as a substitute.
**Rules:**
For mutable shared state that multiple components read **and write** (shopping cart, notification count, filters), use a scoped service with an event for change notification.
**Define the service:**
public class CartState
{
private readonly List<CartItem> _items = [];
public IReadOnlyList<CartItem> Items => _items;
public intThis repository contains the .NET team's curated set of core skills and custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io.
Repo: dotnet/skills
Run file-based C# apps with the .NET CLI when the user explicitly wants C#/.NET code without creating a project. Use for C# language/API experiments, one-file…
Correctly call native (C/C++) libraries from .NET using P/Invoke and LibraryImport. Covers function signatures, string marshalling, memory lifetime,…
Set up NuGet trusted publishing (OIDC) on a GitHub Actions repo — replaces long-lived API keys with short-lived tokens. USE FOR: trusted publishing, NuGet…
Design, implement, optimize, and review SIMD code in .NET. USE FOR: vectorizing scalar loops with TensorPrimitives, Vector64/128/256/512, or platform hardware…
Guides technology selection and implementation of AI and ML features in .NET 8+ applications using ML.NET, Microsoft.Extensions.AI (MEAI), Microsoft Agent…
Configure OpenTelemetry distributed tracing, metrics, and logging in ASP.NET Core using the .NET OpenTelemetry SDK. Use when adding observability, setting up…