Comunicação entre componentes e DI
Passe dados entre componentes pai e filho, use parâmetros em cascata e injete serviços nos componentes.
Comunicação entre componentes e DI é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.
Padrões de comunicação entre componentes
Os componentes do Blazor comunicam-se em três direções: do pai para o filho (parâmetros), do filho para o pai (EventCallback) e entre diferentes pontos da árvore (CascadingParameters ou serviços compartilhados via DI).
Do pai para o filho: parâmetros
Decore uma propriedade do componente com [Parameter] para permitir que ela seja definida pelo pai. O pai passa valores como atributos HTML na tag do componente.
@* Child: Alert.razor *@
<div class="alert alert-@Type">
@Message
</div>
@code {
[Parameter] public string Type { get; set; } = "info"; // primary, warning, danger
[Parameter, EditorRequired] public string Message { get; set; } = "";
}
@* Parent usage: *@
<Alert Type="danger" Message="Something went wrong!" />
<Alert Message="Record saved." />Do filho para o pai: EventCallback
Um componente filho expõe um parâmetro EventCallback. O pai fornece um método manipulador. O filho o invoca quando algo acontece.
@* Child: QuantityPicker.razor *@
<button @onclick="() => OnChanged.InvokeAsync(Value - 1)">-</button>
<span>@Value</span>
<button @onclick="() => OnChanged.InvokeAsync(Value + 1)">+</button>
@code {
[Parameter] public int Value { get; set; } = 1;
[Parameter] public EventCallback<int> OnChanged { get; set; }
}
@* Parent: *@
<QuantityPicker Value="@_qty" OnChanged="q => _qty = q" />
<p>Quantity: @_qty</p>Comunicação entre irmãos via pai
Para que componentes irmãos se comuniquem, encaminhe os dados pelo pai comum. O pai mantém o estado compartilhado e o passa aos filhos como parâmetros.
@* Parent holds shared state *@
<CategoryFilter OnChanged="c => _category = c" />
<ProductList Category="_category" />
@code {
private string _category = "All";
}
@* CategoryFilter raises an event -> Parent updates _category
-> ProductList re-renders with new Category *@Parâmetros em cascata
Envolva uma subárvore em <CascadingValue> para passar dados a todos os descendentes sem encaminhá-los por cada componente intermediário.
@* Wrap a subtree *@
<CascadingValue Value="_theme">
<MainLayout />
</CascadingValue>
@code { private Theme _theme = new Theme { PrimaryColor = "#6366f1" }; }
@* Any descendant can receive it: *@
@code {
[CascadingParameter]
public Theme AppTheme { get; set; } = default!;
}
<h1 style="color: @AppTheme.PrimaryColor">Hello</h1>Injetando serviços com @inject
Use a diretiva @inject para injetar serviços DI registrados diretamente nos componentes. Eles são resolvidos automaticamente pela estrutura.
@inject IProductService ProductSvc
@inject ILogger<ProductList> Logger
@inject NavigationManager Nav
@code {
private List<Product> _products = new();
protected override async Task OnInitializedAsync()
{
Logger.LogInformation("Loading products");
_products = await ProductSvc.GetAllAsync();
}
private void GoToProduct(int id)
=> Nav.NavigateTo($"/products/{id}");
}Serviços com escopo no Blazor Server
No Blazor Server, o scope do DI dura todo o lifetime da conexão SignalR — não apenas uma única solicitação. Esteja ciente de que os serviços com escopo são compartilhados por todos os componentes de um circuito.
// Blazor Server: scoped = per circuit (connection lifetime)
builder.Services.AddScoped<CartService>();
// All components in the same browser tab share the SAME CartService
// This is GOOD for cart state (user's items persist across pages)
// This is BAD for request-scoped data — treat as session-like scope
// For true per-render-cycle scope, create your own:
using var scope = ScopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();NavigationManager para roteamento
Injete NavigationManager para navegar programaticamente, ler a URL atual e tratar eventos de navegação.
@inject NavigationManager Nav
@code {
private void GoHome() => Nav.NavigateTo("/");
private void GoToProduct(int id) => Nav.NavigateTo($"/products/{id}");
private void ForceReload() => Nav.NavigateTo("/", forceLoad: true);
protected override void OnInitialized()
{
// Read current URL
var uri = Nav.Uri;
var path = new Uri(uri).AbsolutePath;
}
}HttpClient no Blazor WASM
No Blazor WebAssembly, injete um HttpClient pré-configurado para chamar sua API. Registre-o com um endereço base em Program.cs.
// Program.cs (Blazor WASM)
builder.Services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
// Component:
@inject HttpClient Http
@code {
private List<Product> _products = new();
protected override async Task OnInitializedAsync()
{
_products = await Http.GetFromJsonAsync<List<Product>>("/api/products")
?? new();
}
}Na prática: serviço de contexto do usuário
Um UserContextService com escopo é injetado em vários componentes do aplicativo — cada um vê os mesmos dados do usuário sem o encadeamento de propriedades.
public class UserContextService
{
public string? Name { get; private set; }
public bool IsAdmin { get; private set; }
public async Task InitializeAsync(AuthenticationState auth)
{
var user = auth.User;
Name = user.Identity?.Name;
IsAdmin = user.IsInRole("Admin");
}
}
// Registered as scoped:
builder.Services.AddScoped<UserContextService>();
// Used in any component:
@inject UserContextService UserCtx
<p>Hello, @UserCtx.Name @(UserCtx.IsAdmin ? "(Admin)" : "")</p>Verificação rápida
No Blazor Server, por quanto tempo dura o lifetime de um serviço DI com escopo?
Recapitulação: comunicação entre componentes e DI
Principais conclusões:
- Do pai para o filho: propriedades [Parâmetro]; [EditorObrigatório] para parâmetros obrigatórios
- Do filho para o pai: EventCallback; dispara automaticamente StateHasChanged no pai
- Irmãos: encaminhe pelo estado do pai ou use um serviço DI compartilhado
- Entre diferentes pontos da árvore: CascadingValue/CascadingParameter para subárvores profundas
- @inject para serviços; os serviços DI com escopo do Blazor Server duram o lifetime do circuito
- NavigationManager para roteamento programático
Perguntas Frequentes
A aula “Comunicação entre componentes e DI” é grátis?
Sim — o texto completo de “Comunicação entre componentes e DI” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.
O que vou aprender em “Comunicação entre componentes e DI”?
Passe dados entre componentes pai e filho, use parâmetros em cascata e injete serviços nos componentes. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C# Academy?
Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Comunicação entre componentes e DI”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C# Academy?
Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Modelo de componentes do Blazor
- Vinculação de dados e tratamento de eventos
- Comunicação entre componentes e DI
- Gerenciamento de estado no Blazor