Condividi tramite


Eventi di modifica delle proprietà

Windows Presentation Foundation (WPF) definisce diversi eventi generati in risposta a una modifica del valore di una proprietà. Spesso la proprietà è una proprietà di dipendenza. L'evento stesso è talvolta un evento indirizzato e talvolta è un evento CLR (Common Language Runtime) standard. La definizione dell'evento varia a seconda dello scenario, perché alcune modifiche alle proprietà vengono instradate in modo più appropriato tramite un albero degli elementi, mentre altre modifiche alla proprietà sono in genere solo di interesse per l'oggetto in cui la proprietà è cambiata.

Identificazione di un evento di modifica delle proprietà

Non tutti gli eventi che segnalano una modifica di proprietà vengono identificati in modo esplicito come evento di modifica della proprietà, in virtù di un modello di firma o di un modello di denominazione. In genere, la descrizione dell'evento nella documentazione dell'SDK indica se l'evento è direttamente associato a una modifica del valore della proprietà e fornisce riferimenti incrociati tra la proprietà e l'evento.

Eventi di RoutedPropertyChanged

Alcuni eventi usano un tipo di dati evento e un delegato utilizzato esplicitamente per gli eventi di modifica delle proprietà. Il tipo di dati dell'evento è RoutedPropertyChangedEventArgs<T>e il delegato è RoutedPropertyChangedEventHandler<T>. I dati dell'evento e il delegato hanno entrambi un parametro di tipo generico usato per specificare il tipo effettivo della proprietà di modifica quando si definisce il gestore. I dati dell'evento contengono due proprietà, OldValue e NewValue, che vengono quindi passate entrambe come argomento di tipo nei dati dell'evento.

La parte del nome "Routed" indica che l'evento di modifica della proprietà viene registrato come evento instradato. Il vantaggio dell'instradamento di un evento di modifica della proprietà è che il livello superiore di un controllo può ricevere eventi di modifica delle proprietà quando le proprietà degli elementi figlio (le parti composite del controllo) cambiano valori. Ad esempio, è possibile creare un controllo che incorpora un controllo RangeBase, ad esempio un Slider. Se il valore della proprietà Value cambia nella parte del dispositivo di scorrimento, si potrebbe voler gestire quella modifica nel controllo padre piuttosto che nella parte stessa.

Poiché si dispone di un valore precedente e di un nuovo valore, potrebbe essere tentante usare questo gestore eventi come validatore per il valore della proprietà. Tuttavia, non è l'intento progettuale della maggior parte degli eventi di modifica delle proprietà. In genere, i valori vengono forniti in modo che sia possibile agire su tali valori in altre aree logiche del codice, ma la modifica effettiva dei valori dall'interno del gestore eventi non è consigliabile e può causare ricorsione involontaria a seconda della modalità di implementazione del gestore.

Se la tua proprietà è una proprietà di dipendenza personalizzata o se lavori con una classe derivata in cui hai definito il codice di istanza, esiste un modo molto più efficace per monitorare le modifiche delle proprietà già integrato nel sistema di proprietà WPF: i callback del sistema di proprietà CoerceValueCallback e PropertyChangedCallback. Per ulteriori dettagli su come utilizzare il sistema di proprietà WPF per la convalida e la coercizione, vedere Callback e convalida delle proprietà di dipendenza e Proprietà di dipendenza personalizzate.

Eventi di Cambiamento di DependencyProperty

Un'altra coppia di tipi che fanno parte di uno scenario di evento di modifica delle proprietà sono DependencyPropertyChangedEventArgs e DependencyPropertyChangedEventHandler. Gli eventi relativi a queste modifiche delle proprietà non vengono instradati; sono eventi CLR standard. DependencyPropertyChangedEventArgs è un tipo insolito di report dei dati degli eventi perché non deriva da EventArgs; DependencyPropertyChangedEventArgs è una struttura, non una classe.

Gli eventi che usano DependencyPropertyChangedEventArgs e DependencyPropertyChangedEventHandler sono leggermente più comuni rispetto agli eventi RoutedPropertyChanged. Un esempio di evento che usa questi tipi è IsMouseCapturedChanged.

Come RoutedPropertyChangedEventArgs<T>, anche DependencyPropertyChangedEventArgs riporta un valore vecchio e uno nuovo della proprietà. Inoltre, le stesse considerazioni sulle operazioni che è possibile eseguire con i valori si applicano; in genere non è consigliabile provare a modificare nuovamente i valori nel mittente in risposta all'evento.

Trigger di proprietà

Un concetto strettamente correlato a un evento di modifica della proprietà è un attivatore di proprietà. Un trigger di proprietà viene creato all'interno di uno stile o di un modello e consente di creare un comportamento condizionale in base al valore della proprietà a cui è assegnato il trigger di proprietà.

La proprietà per un trigger di proprietà deve essere una proprietà di dipendenza. Può essere (e spesso è) una proprietà di dipendenza di sola lettura. Un buon indicatore per quando una proprietà di dipendenza esposta da un controllo è almeno parzialmente progettata per essere un trigger di proprietà è se il nome della proprietà inizia con "Is". Le proprietà che seguono questa denominazione sono spesso una proprietà di dipendenza booleana di sola lettura, in cui lo scenario principale per la proprietà consiste nel segnalare lo stato del controllo, il che potrebbe avere conseguenze per l'interfaccia utente in tempo reale e quindi può essere un candidato per l'attivazione della proprietà.

Alcune di queste proprietà hanno anche un evento dedicato al cambiamento della proprietà. Ad esempio, la proprietà IsMouseCaptured ha un evento di modifica della proprietà IsMouseCapturedChanged. La proprietà stessa è di sola lettura, con il relativo valore regolato dal sistema di input e il sistema di input genera IsMouseCapturedChanged in ogni modifica in tempo reale.

Rispetto a un vero evento di modifica della proprietà, l'uso di un trigger di proprietà per agire su una modifica della proprietà presenta alcune limitazioni.

I trigger di proprietà funzionano tramite una logica di corrispondenza esatta. Si specifica una proprietà e un valore che indica un valore specifico per il quale il trigger agirà. Ad esempio: <Setter Property="IsMouseCaptured" Value="true"> ... </Setter>. A causa di questa limitazione, la maggior parte degli utilizzi dei trigger di proprietà sarà per le proprietà booleane o le proprietà che accettano un valore di enumerazione dedicato, dove l'intervallo di valori possibile è sufficientemente gestibile per definire un trigger per ogni caso. Oppure i trigger di proprietà potrebbero esistere solo per valori speciali, ad esempio quando un conteggio degli elementi raggiunge zero e non ci sarebbe alcun trigger che conti per i casi in cui il valore della proprietà cambia di nuovo da zero (invece di trigger per tutti i casi, potrebbe essere necessario un gestore eventi di codice qui o un comportamento predefinito che attiva nuovamente lo stato del trigger quando il valore è diverso da zero).

La sintassi del trigger di proprietà è analoga a un'istruzione "if" nella programmazione. Se la condizione del "trigger" è vera, il "corpo" del trigger di proprietà viene eseguito. Il "corpo" di un trigger di proprietà non è codice, ma è markup. Tale markup è limitato all'uso di uno o più elementi Setter per impostare altre proprietà dell'oggetto in cui viene applicato lo stile o il modello.

In genere, per compensare la condizione "if" di un trigger di proprietà con un'ampia gamma di valori possibili, è consigliabile impostare la proprietà stessa su un valore predefinito usando un Setter. In questo modo, il setter contenuto Trigger avrà la precedenza quando la condizione del trigger è vera, e il Setter che non si trova all'interno di un Trigger avrà la precedenza ogni volta che la condizione del trigger è falsa.

I trigger di proprietà sono in genere appropriati per gli scenari in cui una o più proprietà di aspetto devono cambiare, in base allo stato di un'altra proprietà sullo stesso elemento.

Per ulteriori informazioni sui trigger di proprietà, vedere Stili e modelli.

Vedere anche