-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
This issue has been moved from a ticket on Developer Community.
[severity:It's more difficult to complete my work]
I have followed the steps here to create a Root-level cascading value with notifications (Blazor Server)
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/cascading-values-and-parameters?view=aspnetcore-9.0#root-level-cascading-values-with-notifications
It works great, except for one thing: The instance is a singleton. So in two different browsers, the Cascading Value is the same. Thus when a user changes a value (for example the current Theme), it changes the Theme of all connected users.
What is needed is a Scoped Root Level Cascading Value.
This is the code that adds the Service. As you can see, it is created in Program.cs and thus is going to be a singleton.
builder. Services.AddNotifyingCascadingValue(new NotifyingDalek() { Units = 888 });
I have tried, but I have not found a way to Add NotifyingDalek as a Scoped Service, and then add it using
builder. Services.AddNotifyingCascadingValue<NotifyingDalek>();
Any advice would be appreciated.
Original Comments
Feedback Bot on 9/26/2025, 03:09 AM:
We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.
Original Solutions
Greg Gum solved on 9/25/2025, 06:07 PM, undefined votes:
I was able to update the Registration Code as follows, and then call it as usual:
builder. Services.AddNotifyingCascadingValue<ThemeService>();
public static class CascadingStateServiceCollectionExtensions { public static IServiceCollection AddNotifyingCascadingValue<TState, TImplementation>( this IServiceCollection services, bool isFixed = false) where TState : class, INotifyPropertyChanged where TImplementation : class, TState { // Register the implementation as Scoped services. AddScoped<TImplementation>();
return services. AddCascadingValue<TState>(sp =>
{
var state = sp. GetRequiredService<TImplementation>();
return new CascadingStateValueSource<TState>(state, isFixed);
});
}// Overload for cases where TState and TImplementation are the same
public static IServiceCollection AddNotifyingCascadingValue<TState>(
this IServiceCollection services, bool isFixed = false)
where TState : class, INotifyPropertyChanged
{
return AddNotifyingCascadingValue<TState, TState>(services, isFixed);
}private sealed class CascadingStateValueSource<T>
: CascadingValueSource<T>, IDisposable where T : INotifyPropertyChanged
{
private readonly T state;public CascadingStateValueSource(T state, bool isFixed = false)
: base(state, isFixed)
{
this.state = state;
this.state.PropertyChanged += HandlePropertyChanged;
}private void HandlePropertyChanged(object? sender, PropertyChangedEventArgs e)
{
_ = NotifyChangedAsync();
}
public void Dispose()
{
state. PropertyChanged -= HandlePropertyChanged;
}
}
}