0Pricing
C# Academy · บทเรียน

การสื่อสารระหว่างคอมโพเนนต์และ DI

ส่งข้อมูลระหว่างคอมโพเนนต์แม่และลูก ใช้พารามิเตอร์แบบลำดับชั้น และฉีดบริการเข้าไปในคอมโพเนนต์

การสื่อสารระหว่างคอมโพเนนต์และ DI เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

รูปแบบการสื่อสารระหว่างคอมโพเนนต์

คอมโพเนนต์ Blazor สื่อสารกันได้สามทิศทาง ได้แก่ จากคอมโพเนนต์แม่ไปยังคอมโพเนนต์ลูก (พารามิเตอร์) จากคอมโพเนนต์ลูกไปยังคอมโพเนนต์แม่ (EventCallback) และ ทั่วทั้งโครงสร้างต้นไม้ (CascadingParameters หรือบริการที่ใช้ร่วมกันผ่าน DI)

จากคอมโพเนนต์แม่ไปยังคอมโพเนนต์ลูก: พารามิเตอร์

กำกับคุณสมบัติของคอมโพเนนต์ด้วย [Parameter] เพื่อให้คอมโพเนนต์แม่กำหนดค่าได้ คอมโพเนนต์แม่จะส่งค่าต่าง ๆ เป็นแอตทริบิวต์ HTML บนแท็กของคอมโพเนนต์

@* 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." />

จากคอมโพเนนต์ลูกไปยังคอมโพเนนต์แม่: EventCallback

คอมโพเนนต์ลูกเปิดให้ใช้พารามิเตอร์ EventCallback ส่วนคอมโพเนนต์แม่จัดเตรียมเมธอดตัวจัดการไว้ แล้วคอมโพเนนต์ลูกจะเรียกใช้เมธอดนั้นเมื่อเกิดเหตุการณ์บางอย่าง

@* 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>

การสื่อสารระหว่างคอมโพเนนต์พี่น้องผ่านคอมโพเนนต์แม่

หากคอมโพเนนต์พี่น้องต้องสื่อสารกัน ให้ส่งข้อมูลผ่านคอมโพเนนต์แม่ร่วมกัน คอมโพเนนต์แม่จะเก็บสถานะที่ใช้ร่วมกันและส่งต่อให้คอมโพเนนต์ลูกเป็นพารามิเตอร์

@* 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 *@

พารามิเตอร์แบบส่งต่อ

ครอบโครงสร้างย่อยด้วย <CascadingValue> เพื่อส่งข้อมูลไปยังคอมโพเนนต์ลูกหลานทั้งหมด โดยไม่ต้องส่งข้อมูลผ่านคอมโพเนนต์ตัวกลางทุกตัว

@* 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>

การฉีดบริการด้วย @inject

ใช้คำสั่ง @inject เพื่อฉีดบริการ DI ที่ลงทะเบียนไว้เข้าไปในคอมโพเนนต์โดยตรง กรอบงานจะค้นหาและสร้างบริการเหล่านี้ให้โดยอัตโนมัติ

@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}");
}

บริการแบบมีขอบเขตใน Blazor Server

ใน Blazor Server ขอบเขต DI จะคงอยู่ตลอดอายุการใช้งานของการเชื่อมต่อ SignalR ทั้งหมด ไม่ใช่เพียงคำขอเดียว โปรดทราบว่าบริการแบบมีขอบเขตจะถูกใช้ร่วมกันโดยคอมโพเนนต์ทั้งหมดในวงจรเดียวกัน

// 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 สำหรับการกำหนดเส้นทาง

ฉีด NavigationManager เพื่อเปลี่ยนเส้นทางด้วยโปรแกรม อ่าน URL ปัจจุบัน และจัดการเหตุการณ์การเปลี่ยนเส้นทาง

@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 ใน Blazor WASM

ใน Blazor WebAssembly ให้ฉีด HttpClient ที่กำหนดค่าไว้ล่วงหน้าเพื่อเรียกใช้ API ของคุณ และลงทะเบียนโดยระบุที่อยู่ฐานใน 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();
    }
}

ตัวอย่างจริง: บริการบริบทผู้ใช้

มีการฉีด UserContextService แบบมีขอบเขตเข้าไปในคอมโพเนนต์หลายตัวทั่วทั้งแอป แต่ละคอมโพเนนต์จึงเห็นข้อมูลผู้ใช้ชุดเดียวกันโดยไม่ต้องส่งคุณสมบัติผ่านหลายชั้น

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>

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ใน Blazor Server อายุการใช้งานของบริการ DI แบบ 'มีขอบเขต' นานเท่าใด

สรุป: การสื่อสารระหว่างคอมโพเนนต์และ DI

ประเด็นสำคัญ:

  • จากคอมโพเนนต์แม่ → ลูก: คุณสมบัติ [พารามิเตอร์]; ใช้ [EditorRequired] สำหรับพารามิเตอร์ที่จำเป็น
  • จากคอมโพเนนต์ลูก → แม่: EventCallback ซึ่งจะเรียก StateHasChanged ของคอมโพเนนต์แม่โดยอัตโนมัติ
  • คอมโพเนนต์พี่น้อง: ส่งผ่านสถานะของคอมโพเนนต์แม่ หรือใช้บริการ DI ร่วมกัน
  • ข้ามโครงสร้างต้นไม้: ใช้ CascadingValue/CascadingParameter สำหรับโครงสร้างย่อยที่อยู่ลึก
  • ใช้ @inject สำหรับบริการ ส่วนบริการแบบมีขอบเขตใน Blazor Server จะคงอยู่ตลอดอายุการใช้งานของวงจร
  • ใช้ NavigationManager สำหรับการกำหนดเส้นทางด้วยโปรแกรม

คำถามที่พบบ่อย

บทเรียน “การสื่อสารระหว่างคอมโพเนนต์และ DI” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การสื่อสารระหว่างคอมโพเนนต์และ DI” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การสื่อสารระหว่างคอมโพเนนต์และ DI”

ส่งข้อมูลระหว่างคอมโพเนนต์แม่และลูก ใช้พารามิเตอร์แบบลำดับชั้น และฉีดบริการเข้าไปในคอมโพเนนต์ คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การสื่อสารระหว่างคอมโพเนนต์และ DI” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. รูปแบบคอมโพเนนต์ของ Blazor
  2. การผูกข้อมูลและการจัดการเหตุการณ์
  3. การสื่อสารระหว่างคอมโพเนนต์และ DI
  4. การจัดการสถานะใน Blazor
← กลับไปที่ C# Academy