Press "Enter" to skip to content

Forum

Please or Register to create posts and topics.

Uso di PropertyChanged e Binding

Salve a tutti questo mio post è indirizzato a chi ha più esperienza di me con wpf, binding e propertychanged...

Gestisco un progetto molto grande in wpf che utilizza componenti di terze parti " DeveExpress "...

Per motivi di poca padronanza con il binding e tutti gli strumenti messi a disposizione e la necessità di gestire e creare le funzionalità immediatamente, tutti gli eventi, l'aggiornamento dei campi ecc.. viene gestito senza automatismi manualmente..

Volendo iniziare a rivedere tutto lo sviluppo sono preoccupato di perdere mesi di lavoro per poi ritornare al vecchio metodo.

Avrei bisogno di un consiglio da chi ha più esperienza se è il caso di intraprendere questa strada o se è meglio desistere.

Ad esempio..

Il progetto ha moltissime maschere o userControl di acquisizione dati dall'utente... queste sono composte da una serie di campi " codice " e " descrizione ".. l'utente per compilare i campi ha due possibilità:

1 ) Utilizza il pulsante cerca

2) ricordando il codice dell'informazione in archivio ( ad esempio l'id di un soggetto presente nella tabella anagrafiche) all'evento l0stKeyboardFocus vengono popolati i campi associati a quel codice.

per sviluppare questa funzionalità ho realizzato un metodo comune che intercetta il click sul pulsante cerca o l'evento l0stKeyboardFocus  della casella di testo ed esegue la ricerca nel db o apre la finestra di ricerca dei dati.

Per evitare loop o continue richieste al db all'evento l0stKeyboardFocus  ho un oggetto/variabili popolate con l'ultimo valore inserito nella textbox.

Questo mi permette di eseguire il metodo solo quando il valore effettivamente è cambiato e non ogni volta che si passa dalla casella...

dimenticavo di dirvi che per questioni di comodità l'utente utilizza il pulsante invio per navigare in avanti da una casella all'altra e capita spesso che tornano indietro di un paio di caselle con il mouse per modificare un valore e poi per riposizionarsi sulla successiva da popolare premono tante volte invio per superare tutte quelle già popolate.

Quindi se non avessi le variabili sentinella ad ogni passaggio verrebbe fatta una query per aggiornare i valori di pertinenza.

Detto ciò se volessi utilizzare il binding per mappare un oggetto alle caselle e utilizzare il propertyChanged per l'aggiornamento dei valori, tutto il meccanismo di controllo per evitare le ricerche continue funzionerebbe?

o mi ritroverei in loop continui?

Il propertyChanged verifica se il valore effettivamente è cambiato?

ad esempio allo stato attuale se nella casella ho il valore 100 cancello uno 0 quindi diventa 10 fino a quando non perdo il focus dalla casella o fino a quando non svuoto completamente la casella non succede nulla.. quindi ho la possibilità di riportare il valore a 100 evitando di avviare ricerche non volute sul db.

Con il propertyChanged credo che non sia possibile... da scemo mi viene da pensare che nel momento in cui vario il valore la property si aggiorna.

Giusto? , o c'è la possibilità di gestire anche quando la property deve essere aggiornata?

Spero di essere stato chiaro...

Vi ringrazio in anticipo.

 

Ciao

E' difficile darti una risposta corretta senza vedere come e' implementato il tuo codice

Comunque sia, il NotifyPropertyChanged non fa altro che aggiornare l'interfaccia grafica nel momento in cui la property cambia di valore e viceversa.

Non ha impatti su altro codice almeno che non lo abbia stabilito tu. Il vantaggio e' che se hai 100 controlli che fanno riferimento ad una property, al variare del valore della property, tutti e 100 si aggiorneranno, visivamente.

Poi devi essere tu a decidere cosa fare col nuovo valore.

Es:

private int n;

Public int N

{

get

{

return n;

}

set

{

if (n == value) return;

n = value;

NotifyPropertyChanged()

}

}

Se nel setter non metti altro codice, otterrai che al variare di N, magari via codice, si aggiorna solo la UI, o alla modifica della UI, si aggiornerà il valore di N.

Se nel setter ci aggiungi la chiamata ad un metodo tipo OnNChanged(N), puoi gestire il nuovo valore appena modificato e decidere cosa farne.

Es:

private OnNChanged(int n)

{

if (n==1) return; //Quindi non fa niente

if (n==2) RunQuery(); //Esegui il codice di ricerca

}

Se poi crei un evento NChanged(N) puoi sfruttarlo creando dei delegati in altri punti del codice, in altre classi, in altri progetti

public event Action<N> NChanged;

private OnNChanged(int n)

{

if (NChanged != null) //Questo signifca: se qualcuno si e' registrato a NChanged, passagli N
{
NChanged(N);
}

if (n==1) return; //Quindi non fa niente

if (n==2) RunQuery(); //Esegui il codice di ricerca

}

Quindi in un'altra classe ad esempio nel code behind della window:

{

miaClasse  mc = new miaClasse

mc.NChanged += N_Changed //Questa e' la registrazione all'evento NChanged da parte di un'altra classe

}

private void N_Canged(int n)
{

FaiQualcosa() //Questo codice verrà eseguito ogni volta che nella classe miaClasse, varierà il valore di N

}

Inoltre

Il binding puo' essere (Mode=)

Default

OneWay

TwoWay

OneWayToSource

E per questo ti rimando alla documentazione originale.

Alcuni controlli, tipo TextBox hanno una proprietà UpdateSourceTrigger che puo' essere

Default

Explicit

LostFocus

PropertyChanged

Ed anche per questo ti rimando alla documentazione.

Ultima cosa, non sei costretto a usare il binding con gli oggetti "originali", puoi creare delle copie degli oggetti che poi aggiorneranno il oggetti originali al bisogno, tipo quando vuoi salvare.

 

Tirando le somme, direi che puoi tranquillamente gestire il tuo codice esistente implementando il NotifyPropertyChanged

Miky

 

Buonasera Ferdinando,

al solito non sono molto veloce nelle risposte, ma cercherò di essere di aiuto dove posso.

Per quel che riguarda l'iniziare a usare il Data Driven al posto dell'Event Driven nell'implementazione dell'applicazione è chiaro che è un bel salto, ma per esperienza ti posso dire che il Data Driven ti da una potenza di realizzazione che per fare le stesse cose con gli eventi implicava molto più lavoro. Io non mi sono mai pentita di essere passata da Windows Forms a WPF ed ho immediatamente iniziato ad usare il Binding. Capito il meccanismo è come passare da una pistola ad acqua ad un missile Jericho...

Detto ciò, è chiaro che devi capire un po' come funziona il binding e come risolvere i problemi, pertanto, visto che hai portato come primo esempio la ricerca in real time, ti dico cosa uso io in questi casi.

Come Miky ti ha già indicato, quando passi ad una window in cui le property dei controlli sono in binding bidirezionale, se modifichi il testo di una textbox la property collegata è immediatamente aggiornata e se questo aggiornamento chiama un metodo che aggiorna altre 10 property la parte visuale della Window reagisce alle modifiche di conseguenza aggiornando valori, ma anche stili (colori, font ed altro) o Icone/Immagini in modo automatico.

Ovviamente se la modifica ad un dato scatena una chiamata a Database è opportuno trovare modo di evitare l'overload quando l'utente sta digitando delle parole sulla textbox. Questo io lo faccio in modalità "dinosauro" furbescamente utilizzando un Timer resettato ogni volta che l'utente preme il tasto, solo se il timer arriva a scatenare il "Tick" viene eseguita l'operazione su DB, in questo modo, configurando opportunamente tale timer (di solito 500 millisecondi) la ricerca parte quando l'utente smette di scrivere.

Ma se invece ho un dato che mi arriva da un polling, o da una elaborazione, per fare in modo che la finestra aggiorni tutto quello che vi si trova sopra, basta solo aggiornare le property in binding sui controlli e tutto è già fatto.

Se hai una applicazione con molte Window e molti dati, ti consiglierei di iniziare prendendo una delle window, giocare con il binding e se ti pianti mostrarci cosa stai facendo in modo che possiamo darti delle dritte più precise.

Un mini punto di partenza per dare un occhiata al binding potrebbe essere il progettino che ho postato sul forum qualche settimana fa in risposta ad un collega che anche lui passando al Binding si era piantato sui concetti base di binding e property changed.

Se poi ad uno o più dei frequentatori del forum, interessasse approfondire, possiamo organizzare un meetup su una delle piattaforme di videoconferenza che tutti ormai usiamo e parlarne.  Così posso farvi vedere un po' di cose se necessario.

Ti riposto il link: Esempio di Databinding base

Saluti

 

 

 

Grazie mille a tutti...

Dopo questo periodo di fuoco inizierò a giocarci un pò...

per iniziare a migrare definitivamente tutto il progetto con le tecniche giuste...

come dicevo nel mio primo post ho realizzato il progetto in wpf ma per tanti motivi non utilizzo  a pieno tutte le sue potenzialità..

Con l'occasione vi auguro un buon 2021.