Để đạ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
ClientDataSetnhiề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.