Sử dụng kbmMWSmartBind để liên kết ListView với ClientDataSet hiệu quả trên nhiều nền tảng

Để đạt được cách liên kết ListView với ClientDataSet thông qua thư viện kbmMW một cách tối ưu, cần đáp ứng các yêu cầu sau:

  • Mã liên kết chỉ thực thi một lần.
  • Hỗ trợ mở lại ClientDataSet nhiều lần mà không gây lỗi.
  • Tối ưu hiệu năng hiển thị.
  • Tương thích đa nền tảng (ví dụ: Android, Windows).
  • Không phụ thuộc vào việc khai báo trường tại thời điểm thiết kế.
  • Tách biệt rõ ràng giữa giao diện và logic xử lý.

1. Khởi tạo và giải phóng đối tượng liên kết

Với form hoặc frame trong ứng dụng, cần khởi tạo đối tượng liên kết trong AfterConstruction và giải phóng trong BeforeDestruction:

private
  FNavigatorZC: IkbmMWBinding;
  FBindOrderZC: TkbmMWBindings;

procedure TMyFrame.AfterConstruction;
begin
  inherited;
  FBindOrderZC := TkbmMWBindings.Create;
end;

procedure TMyFrame.BeforeDestruction;
begin
  inherited;
  FNavigatorZC := nil;
  FBindOrderZC.Shutdown;
  FBindOrderZC.Free;
end;

2. Triển khai phương thức liên kết dữ liệu

Phương thức này đảm bảo rằng việc liên kết chỉ xảy ra một lần, đồng thời hỗ trợ cập nhật dữ liệu động:

procedure TMyFrame.Binding;
begin
  if FNavigatorZC = nil then
  begin
    // Gán FNavigatorZC ngay từ lần liên kết đầu tiên
    FNavigatorZC := FBindOrderZC.Bind(qOrderZC, 'fsn', ListView1, '#fsn');
    FBindOrderZC.Bind(qOrderZC, 'FDate',         ListView1, '#fdate');
    FBindOrderZC.Bind(qOrderZC, 'FTruckName',    ListView1, '#ftruckname');
    FBindOrderZC.Bind(qOrderZC, 'FcustomerName', ListView1, '#fcustomername');
    FBindOrderZC.Bind(qOrderZC, 'FUserName',     ListView1, '#fusername');
    FBindOrderZC.Bind(qOrderZC, 'FState',        ListView1, '#fstate');
    FBindOrderZC.Bind(qOrderZC, 'FID',           ListView1, '#fid');
    FBindOrderZC.Bind(qOrderZC, '@',             ListView1, '@', [mwboTwoWay]);
  end;
  // Gọi Refresh hai lần để đảm bảo đồng bộ giao diện trên mọi nền tảng
  FNavigatorZC.Navigator.Refresh;
  FNavigatorZC.Navigator.Refresh;
end;

Lưu ý quan trọng: FNavigatorZC phải được gán giá trị ngay ở dòng đầu tiên của khối if. Nếu gán muộn (ví dụ ở dòng liên kết hai chiều cuối cùng), sẽ gây lỗi hiển thị trên Android dù vẫn hoạt động tốt trên Windows.

3. Mở dữ liệu và kích hoạt liên kết

Khi truy vấn dữ liệu, cần cấu hình ClientDataSet để tránh tái tạo định nghĩa trường không cần thiết:

procedure TMyFrame.QueryOrderZC;
begin
  qOrderZC.DisableControls;
  try
    qOrderZC.AutoFieldDefsOnOpen := mwafoOnce;
    qOrderZC.Close;
    qOrderZC.CommandText := 'SELECT * FROM OrderZC WHERE FState = 0';
    qOrderZC.Open;
    qOrderZC.Fields.LifeCycles := [lcPersistent];
  finally
    qOrderZC.EnableControls;
  end;
end;

Sau đó, gọi tuần tự:

QueryOrderZC;
Binding;

Hai lệnh này có thể thực thi lặp lại nhiều lần — ví dụ khi người dùng thay đổi điều kiện lọc — mà không làm hỏng liên kết hay gây rò rỉ tài nguyên.

4. Sửa lỗi tương thích cho kbmMW 5.12 trở về trước

Phiên bản kbmMW 5.12 và cũ hơn có vấn đề khi sử dụng AutoFieldDefsOnOpen := mwafoOnce: các trường vẫn bị tạo lại mỗi lần mở. Để khắc phục, ghi đè phương thức như sau:

procedure TkbmMWCustomPooledDataSet.InternalCreateFieldsOnOpen;
begin
  inherited;
  if AutoFieldDefsOnOpen = mwafoOnce then
    Fields.LifeCycles := [lcPersistent];
end;

Việc này đảm bảo định nghĩa trường được giữ nguyên sau lần mở đầu tiên, giúp tăng hiệu suất và ổn định liên kết.

Thẻ: kbmMW Delphi FireDAC ListView Data Binding

Đăng vào ngày 15 tháng 8 lúc 09:52