Mi piace disabilitare i controlli quando è inutile che l'utente faccia clic su di essi.Come implementare IsFirstRecord e IsLastRecord?
Un caso speciale è un insieme di pulsanti di menu personalizzati che emulano i pulsanti primo, precedente, successivo e ultimo di uno standard TDBNavigator
.
Quando l'utente fa clic sul primo pulsante, i pulsanti primo e precedente sono entrambi disabilitati.
Quando l'utente fa clic sui pulsanti successivi e precedenti, lo TDataSet
sottostante viene posizionato sullo stesso record di prima, ma i pulsanti primo e precedente sono entrambi ancora abilitati.
L'implementazione corrente si presenta così:
NavigationFirstButton.Enabled := not DataSet.IsEmpty and not DataSet.Bof;
NavigationPriorButton.Enabled := not DataSet.IsEmpty and not DataSet.Bof;
NavigationNextButton.Enabled := not DataSet.IsEmpty and not DataSet.Eof;
NavigationLastButton.Enabled := not DataSet.IsEmpty and not DataSet.Eof;
Bof
e Eof
non sono il modo giusto per disabilitare i pulsanti, perché devo sapere in anticipo se il record corrente sta per essere il primo/ultimo record .
così ho pensato di riscrivere questo utilizzando un IsFirstRecord
e IsLastRecord
metodo:
function IsFirstRecord(ADataSet: TDataSet): Boolean;
begin
Result := ADataSet.RecNo = 0;
end;
function IsLastRecord(ADataSet: TDataSet): Boolean;
begin
Result := ADataSet.RecNo = ADataSet.RecordCount - 1;
end;
Non credo che questa sia una buona idea, dal momento che ho visto casi in cui per il primo record RecNo = 0
non è vero. (ad esempio una TADSQuery filtrata)
Che cos'è un'implementazione affidabile per IsFirstRecord
e IsLastRecord
? È persino possibile utilizzare l'attuale architettura TDataSet
?
'RecNo' è opzionale (può essere non implementato) per insiemi di dati SQL. 'RecordCount' è dannoso per il set di dati SQL, poiché richiede di recuperare tutti i dati. Immagina la richiesta SQL SELECT, che genera 10 GB di informazioni. Solitamente l'utente dovrebbe analizzare solo la prima schermata di dati (o forse 3 schermi o 10 schermi) e quindi chiudere il modulo, ignorando il resto di dati molto meno rilevanti. Chiamando .RecordCount si richiede che 1: SQL Server legga correttamente tutti quei 10 GB dai dischi 2: la rete trasferirà tutti quei 10 GB di dati 3: il client memorizzerà nella RAM tutti quei 10 GB di dati. –
Quindi sarebbe stress-test per server e rete (rallentando tutti gli altri lavori) e per problemi di memoria sul client. E tutto questo per motivi di informazione che probabilmente non sarebbero mai necessari. Quindi l'approccio 'RecNo' è appropriato per i database ISAM (DBF, Paradox, ecc.). Per i database SQL il modo corretto è utilizzare le funzioni 'TDataSet.EOF' e' TDataSet.BOF' –
PS. per definizione DataSet.Empty == DataSet.EOF e DataSet.BOF in modo che il controllo sia ridondante. Immagino tu intenda qualcosa 'DataSet.Active e non DataSet.Bof;' –