VieTopikKhoá học
  • Games
  • Cá nhân
Tải app
© 2026 VieTopikChính sách bảo mậtĐiều khoản sử dụngCài appEnglish
  • Trang chủ
  • Học
  • Luyện thi
  • Cẩm nang
  • Games
  • Cá nhân
WinForms với OracleKết nối Oracle
Bài 12/15
5 phút

Master-detail

Bình luận
Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Màn hình đơn hàng cần hai lưới: trên là danh sách đơn, dưới là các dòng hàng của đơn đang chọn. Chọn đơn khác thì lưới dưới đổi theo. Bài này ghép quan hệ một-nhiều của EF Core với hai BindingSource để làm việc đó.

Khái niệm

🗂️ Master-detail (chính-phụ): màn hình hai phần, chọn một dòng ở lưới chính (master) thì lưới phụ (detail) hiện các dòng con của nó.

🧷 DataMember: tên property danh sách con mà BindingSource phụ lấy ra từ dòng đang chọn của BindingSource chính.

Đây vẫn là quan hệ một-nhiều giữa ORDERS và ORDER_LINES ở khoá SQL, đã khai báo thành Order.Lines ở khoá ASP.NET Core. Bài này đưa nó lên màn hình.

Ví dụ

Chép class Order, OrderLine và hai DbSet Orders, OrderLines từ bài Quan hệ một-nhiều của khoá ASP.NET Core vào code. Đơn mẫu đã được tạo bằng POST /api/orders/sample ở bài đó. Muốn có thêm đơn thì gọi lại API này.

using Microsoft.EntityFrameworkCore;

class MainForm : Form
{
    private readonly ShopDbContext _db;
    private readonly BindingSource _orders =
        new BindingSource();
    private readonly BindingSource _lines =
        new BindingSource();

    public MainForm(ShopDbContext db)
    {
        _db = db;
        Text = "Đơn hàng";
        Width = 600;
        Height = 450;

        var ordersGrid = new DataGridView
        {
            Dock = DockStyle.Top,
            Height = 150,
            DataSource = _orders,
            ReadOnly = true,
            AllowUserToAddRows = false
        };
        var linesGrid = new DataGridView
        {
            Dock = DockStyle.Fill,
            DataSource = _lines,
            ReadOnly = true,
            AllowUserToAddRows = false
        };
        Controls.Add(linesGrid);
        Controls.Add(ordersGrid);

        Load += async (sender, e) =>
        {
            _orders.DataSource = await _db.Orders
                .Include(o => o.Lines)
                .ToListAsync();
            _lines.DataSource = _orders;
            _lines.DataMember = "Lines";
        };
    }
}
  • Include(o => o.Lines) đọc đơn kèm các dòng hàng, như ở khoá ASP.NET Core.
  • _lines.DataSource = _orders và DataMember = "Lines": danh sách dưới là Lines của đơn đang chọn ở trên.
  • Lưới trên chỉ có cột Id, CustomerId. Property danh sách Lines không thành cột.
DataMember = Lines BindingSource đơn Lưới đơn BindingSource dòng Lưới dòng hàng
Chọn đơn ở trên, lưới dưới hiện Lines của đơn đó

Thử ngay

Xoá dòng .Include(o => o.Lines) rồi chạy lại.

Đoán trước khi chạy: lưới dưới hiện các dòng hàng, báo lỗi, hay trống?

Xem kết quả
Lưới trên vẫn đủ các đơn.
Lưới dưới trống, dù chọn đơn nào.

Không có Include, EF Core chỉ đọc bảng ORDERS. Lines của mỗi đơn vẫn là list rỗng từ lúc khởi tạo, giống kết quả Thử ngay ở bài Quan hệ một-nhiều của khoá ASP.NET Core.

Lỗi hay gặp

Đặt DataMember trước khi có dữ liệu. Lúc đó _orders chưa có DataSource, nên BindingSource không biết Lines là gì. App dừng ngay khi mở với ArgumentException: không tìm thấy DataMember tên Lines.

// SAI — đặt trong constructor, _orders còn rỗng
_lines.DataSource = _orders;
_lines.DataMember = "Lines";
// ĐÚNG — đặt sau khi _orders đã có danh sách đơn
_orders.DataSource = await _db.Orders
    .Include(o => o.Lines)
    .ToListAsync();
_lines.DataSource = _orders;
_lines.DataMember = "Lines";

Tóm tắt

  • Master-detail: chọn dòng ở lưới chính, lưới phụ hiện các dòng con.
  • BindingSource phụ lấy DataSource là BindingSource chính, DataMember là tên property danh sách con.
  • Phải Include danh sách con, nếu không lưới phụ luôn trống.
  • Đặt DataMember sau khi BindingSource chính đã có dữ liệu.
CRUD với DataGridViewTách giao diện và dữ liệu

Bình luận

Đang tải bình luận…

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt