Newsgroup: it.comp.lang.delphi
Titolo: Raise Exception... ma il codice continua

Ho una action abbinata ad un pulsante che adopero per salvare il 
contenuto di un form di immissione dati.
 
Il codice della Execute è il seguente:
 
procedure TMxDataSetPost.ExecuteTarget(Target: TObject);
var
   AForm: TForm;
   AControl: TWinControl;
   BM: TBookmark;
   DataSet: TDataSet;
begin
   AForm := Application.Mainform.ActiveMDIChild;
   AControl := AForm.ActiveControl;
   if (AControl <> nil) then
   begin
     repeat
       THackForm(AForm).SelectNext(AControl, true, true);
 
       if AForm.ActiveControl.Visible then
         AForm.ActiveControl.SetFocus;
     until AForm.ActiveControl.Visible;
   end;
   GetDataSet(Target).Post;
end;
 
durante l'esecuzione dello statement:
THackForm(AForm).SelectNext(AControl, true, true);
 
che serve a verificare se il controllo corrente può essere abbandonato 
viene sollevata una eccezione mediante la seguente procedura:
 
procedure TdmBase.CampoObbligatorio(Field: TField; Help: Integer);
const
   Msg = 'Il Campo "%s" non può essere lasciato vuoto!';
begin
   if Field.IsNull or (Trim(Field.AsString) = '') then
   begin
     Field.FocusControl;
     Raise Exception.Create(Format(Msg, [Field.FieldName]));
   end;
end;
 
Mi aspettavo che il flusso di esecuzione si fermasse nella riga:
 
THackForm(AForm).SelectNext(AControl, true, true);
 
ed invece le righe di codice successive fino alla fine della procedura 
vengono eseguite.
 
Cosa sto sbagliando?
 
Grazie.

Mi sfugge il senso del while.
 
A.

 
??? forse ti riferisci al "until"? è perché mi è capitato che l'oggetto 
seguente trovato da
THackForm(AForm).SelectNext(AControl, true, true);
sia un oggetto *invisibile* e che pertanto non possa ricevere il "focus" 
per cui si rende necessario riprovarci.
 
Grazie.
 
Ciao.

 ??? forse ti riferisci al "until"? è perché mi è capitato che l'oggetto 
 
Si scusa...Uso sempre while  e mai repeat....
 
Perchè usare una logica "sporca" basata su un metodo protected di TForm invece di activecontrol.selectnext(....?
 
A.

 
 
ActiveControl è di tipo TWinControl che non ha un metodo pubblico 
SelectNext. Ce l'ha protected, infatti TForm discende da TWinControl.
 
Su Delphi 2010 è così.
Ciao.

Ho scritto una cazzata...
 
Bloccare un utente su un campo fino a che non mette un valore è una logica di validazione del dato superata da anni.
Per la cronaca, prova a pensare in quanti casi tu stesso ti trovi a usare delle UI che lavorano in questo modo...
Non so tu, ma quando mi capitava,  sta cosa mi stressava tanto...
 
 
In più, la tua logica di validazione è strettamente accoppiata alla UI stessa (ti basi sul focus...) e questo NON VA BENE, PUNTO.
 
Il mio suggerimento è cambiare la logica, usando si la post-validazione come fai tu, ma COLLEZIONANDO gli errori relativi ai dati mancanti tipo in una istanza di TStringList e poi mostrandoli tutti in una botta sola con uno showmessage o similare, buttando via le logiche basate sul focus.
 
 
Quindi...
 
 
1) nella tua form dichiara una TStringList (fmandatoryfieldlist) che sarà creata dal costruttore e liberata sul distruttore
2) nella tua form dichiara una TStringList (fmissingffields) che sarà creata dal costruttore e liberata sul distruttore
3) in fmandatoryfieldlist aggiungi i nomi dei campi che non possono essere lasciati vuoti
4) nella tua action fai una cosa del tipo:
 
 
fmissingffields.Clear;
 
for i := 0 to Pred(fmandatoryfieldlist.Count) do begin
  currentfieldname := fmandatoryfieldlist[i];
  currentfield := tuodataset.FindField(currentfieldname);
 if (not assigned(currentfield)) then begin
  Raise Exception.Create('strunz...sto campo non esiste:"' + currentfieldname + '"');
 end;
if (currentfield.isnull) or (trim(currentfield.asstring) = '') then begin
 
  fmissingffields.Add('missing value about " + currentfieldname + '"');
end;
end;
 
 
if (fmissingffields.Count > 0) then begin
  ShowMessage(fmissingfields.text);
end
else begin
  tuodataset.post...
end;
 
 
In questo modo te ne fotti di focus, controlli visibili, nextcontrol etc....
 
A.
 
 
 

 
 
Interessante, approfondisco. Grazie.
 
 
Però continuo a non comprendere *perché* al primo *Raise* sollevato il 
flusso non viene interrotto.
Naturalmente (ma non per tutti, cit. ;) ) non ci si trova all'interno di 
un try..finally..end.
 
Grazie.
 
Ciao.