308 messaggi dal 08 gennaio 2011
Ciao,
se c'ho una Window in un'applicazione WPF che contiene vari controlli TextBox in Binding con le proprietà di un oggetto che implementa InotifyPropertyChanged, per esempio Contatto, se digito in una TextBox e mentre il cursore è ancora nella TextBox faccio click sul pulsante di chiusura della Window, nel gestore dell'evento Closing la modifica non è ancora rilevata; ma prima che la Window si chiuda completamente la modifica viene rilevata e il Binding viene eseguito correttamente, cioè la proprietà dell'oggetto viene aggiornata e se nella Window è presente un gestore dell?evento PropertyChanged, il codice del gestore viene eseguito.

Potrei risolvere, per avere la modifica disponibile nel gestore di Closing, impostando nel Binding delle TextBox la proprietà UpdateSourceTrigger o su Explicit o su PropertyChanged; però usando Explicit sarei costretto a chiamare per ogni TextBox il metodo UpdateSource, mentre usando PropertyChanged farei scattare ad ogni pressione di tasto l'evento PropertyChanged. In entrambi i casi perderei la comodità offerta dal Binding o quanto meno dovrei scrivere più codice nella Window.

Se invece il click sul pulsante di chiusura della Window, facesse perdere il focus alla TextBox, che nel Binding di default per la UpdateSourceTrigger ha proprio il valore LostFocus, il problema non ci sarebbe.

Dato che ho fatto una prova pratica e come dicevo sopra, alla fine però, prima che la Window si chiuda completamente la modifica viene fatta, allora mi chiedo: devo usare un evento diverso da Closing per porre ad esempio la domanda ''Vuoi salvare le modifiche ?''

Questa cosa diventa un pò più grave se la Window viene aperta ad esempio da un'altra Window che mostra una collezione di oggetti. Nella Window collezione la modifica si 'Vede' ma se per esempio si è legato il salvataggio dell'oggetto sul DB ad una conferma esplicita, ad un rispondere Si alla domanda vuoi salvare le modifiche, la modifica sul db non viene fatta, anche se si ha l'impressione del contrario.

Grazie dell'attenzione.
Modificato da Mario Formosa il 30 settembre 2019 12:38 -
Modificato da Mario Formosa il 30 settembre 2019 12:57 -
308 messaggi dal 08 gennaio 2011
Posso risolvere comunque gestendo l'evento Unloaded al posto di Closing anche se al verificarsi dell'evento Unloaded la Window è già scomparsa dallo schermo.

Rimango tuttavia scontento per il fatto che la TextBox che ha il Focus non lo perde quando clicko sul pulsante di chiusura della Window.
135 messaggi dal 01 febbraio 2017
... salve ... c'è un evento QuesryClose associato ? Dovrebbe essere un evento attivato alla richiesta di chiusura della form, ovvero prima che viuene chiusa materialemnte la form, in cui andare ad implementare i controlli che vuoi in maniera molto semplice ...
Es. pratico.
1) focus su textbox1
2) clicco su chiusura
3) si attiva l'evento queryclose
4) esecuzione codice query close (setta un deviatore di chiusura form)
5) evento lost focus su textbox1, controlli il deviatore di prima, se settato nn esegui la solita riutine
6) evento chiusura form normalmente
..
Nn so se mi sono spiegato.
Ciao.
Gino.

UNSTRING identifier-1 id-2 id-3
DELIMITED BY [ALL] OR [ALL] literal-1 lit-2
INTO {id-4 [DELIMITER IN id-5]
[COUNT IN id-6]}
[WITH POINTER id-7]
[TALLYING IN id-8]
[ON OVERFLOW imperative-statement-1]
[NOT ON OVERFLOW imper-2]
[END-UNSTRING]
308 messaggi dal 08 gennaio 2011
Ciao Gino,
ti ringrazio per l'attenzione però io sto parlando di Window WPF non di Form. In più la discussione è riferita ad uno scenario di Binding dove la perdita del Focus dei controlli TextBox è utilizzata per eseguire appunto il Binding quindi la modifica dei dati.

Come dicevo nell'ultimo mio post il modo più semplice per risolvere è utilizzare l'evento Unloaded che però non mi piace tanto perchè scatta quando la Window è già sparita dallo schermo.

L'evento di cui parli tu QueryClose mi pare che sia qualcosa che riguarda VBA e comunque non esiste ne in WinForms ne in WPF.

Ciao, grazie.
135 messaggi dal 01 febbraio 2017
Mario Formosa ha scritto:
Ciao Gino,
ti ringrazio per l'attenzione però io sto parlando di Window WPF non di Form. In più la discussione è riferita ad uno scenario di Binding dove la perdita del Focus dei controlli TextBox è utilizzata per eseguire appunto il Binding quindi la modifica dei dati.

Infatti il mio suggerimento era di modificare tale proprietà nell'evento LostFocus della TextBox.

L'evento di cui parli tu QueryClose mi pare che sia qualcosa che riguarda VBA e comunque non esiste ne in WinForms ne in WPF.

Ciao, grazie.

Si l'ho usato in VBA, per questo chiedevo se esistesse tale evento anche nel tuo ambiente, o qualcosa di simile. Ti serve intercettare l'evento che segnala all'ambiente che è stata richiesta la chisura ...
o altrimenti ....
Ragionare al contrario ... ovvero tieni tale proprietà (il binding) sempre disattivato, e lo attivi 'soltanto' durante il normale LostFocus di ogni campo, dovresti aggiungere però la logica per tenere traccia del campo precedente da cui provieni ... e le cose cominciano ad diventare più complicate.
Gino.

UNSTRING identifier-1 id-2 id-3
DELIMITED BY [ALL] OR [ALL] literal-1 lit-2
INTO {id-4 [DELIMITER IN id-5]
[COUNT IN id-6]}
[WITH POINTER id-7]
[TALLYING IN id-8]
[ON OVERFLOW imperative-statement-1]
[NOT ON OVERFLOW imper-2]
[END-UNSTRING]
11.886 messaggi dal 09 febbraio 2002
Contributi
Impostare a true la proprietà Cancel può aiutare? Qui sto gestendo l'evento Closing.
private void MyWindow_Closing(object sender, CancelEventArgs e)
{
  if (MessageBox.Show("Tutte le modifiche andranno perse. Vuoi davvero uscire senza salvare?", "Conferma", MessageBoxButton.YesNo) == MessageBoxResult.No)
  {
    e.Cancel = true; //Così la chiusura viene evitata
  }
}


ciao,
Moreno

Enjoy learning and just keep making
308 messaggi dal 08 gennaio 2011
@SensoBit
Ciao Gino, tu mi proponi di aumentare inutilmente la complessità mentre il Binding risolve automaticamente tutti gli aspetti;

@BrightSoul
Ciao Moreno, la soluzione da te proposta non mi trova d'accordo per il semplice fatto che verrebbe fatta la domanda anche senza aver modificato alcunché.

Ho fatto un piccolo video dove si può vedere in pratica sia lo schema di base da me adottato per sviluppare funzionalità di accesso ai dati, sia il problema posto nella discussione. Molto graditi suggerimenti e/o osservazioni.

https://1drv.ms/v/s!AgKkXs_MK51Y-08N6a-mlMvKIjnW?e=gGt3Lu

Ciao, grazie.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Mario,
grazie per il video, sei stato molto chiaro, bravo.

Per me non è corretto che le modifiche siano visibili anche nella prima finestra, quella in cui ci sono le informazioni in sola lettura. Quella dovrebbe aggiornarsi solo SE l'utente decide di salvare le modifiche.

Quindi, la cosa più facile che puoi fare è mettere in binding le proprietà *_VI nella finestra di modifica, e poi copiarle i valori sulle proprietà "originali" quando l'utente salva i dati.

Comunque, questo è un approccio che si presta ad errori perché per ogni proprietà devi anche creare la corrispettiva *_VI e assicurarti che i valori siano sempre copiati correttamente. Prima o poi introdurrai un bug, è garantito.

La responsabilità di tracciare le modifiche dovrebbe essere assolta da un altro oggetto. Vedi per esempio questa implementazione. C'è un progetto di esempio da scaricare.
https://www.codeproject.com/Articles/41791/Almost-automatic-INotifyPropertyChanged-automatic

Grazie al NotifyPropertyChangeObject che vedi nell'articolo, sarai in grado di annullare le modifiche in qualsiasi momento chiamando il metodo suo Reset.

Poi fai in modo che il binding agisca ogni volta che si digita un carattere. Così eviterai il problema del focus.

Quando la finestra di modifica viene chiusa, notifica alla finestra in sola lettura che i dati sono cambiati. Ti basta esporre una proprietà come vedi qui. È sufficiente una proprietà booleana che vale true se i dati sono stati aggiornati.
https://stackoverflow.com/questions/3468433/return-an-object-from-a-popup-window

A questo punto la finestra in sola lettura, se i dati sono cambiati, recupererà dal db (dal file di testo) i dati aggiornati. Così l'utente vedrà sempre i dati attuali.
Questo approccio ha due vantaggi:
  • Ti permette di visualizzare all'utente i valori generati automaticamente lato database (es. gli id autoincrementanti);
  • Un domani potrai fare in modo che la finestra in sola lettura usi un oggetto diverso da quello usato dalla finestra di modifica. Infatti non è raro che le due finestre visualizzino più o meno dati rispetto all'altra.


ciao,
Moreno
Modificato da BrightSoul il 02 ottobre 2019 22:32 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.