2012-12-19 16 views
5

Abbiamo un controllo figlio molto grande che esegue molto rendering per visualizzare i suoi dettagli, ma dal momento che solo una porzione di quel controllo è effettivamente visibile (viene ritagliata da qualcosa più in alto nella gerarchia, non necessariamente dal suo genitore immediato) vogliamo solo per rendere visibile la parte durante la chiamata OnRender.Esiste un modo semplice per determinare i limiti visibili di un controllo per ottimizzare il rendering?

Considerare la figura seguente. Il bambino è 100x50 ma l'area visibile è un rettangolo con angoli a (10,5) e (100,50) in coordinate figlio. Questa è l'area che stiamo cercando.

Clipped Child

Nota: Non si può semplicemente fare coordinare le conversioni da parte del bambino al genitore e il test per il ritaglio, perché non può essere il genitore che sta facendo il ritaglio.

Considerare i controlli nidificati Canvas all'interno di ScrollViewer. La tela interna può benissimo giacere completamente entro i limiti della tela esterna, ma la tela esterna può essere ritagliata dal ScrollViewer, quindi anche la tela interna viene ritagliata visivamente da essa.

Camminare nell'albero visivo e testare ogni genitore ucciderebbe le prestazioni.

Quindi c'è qualcosa di integrato in WPF che può ottenere i limiti dell'area visibile di un controllo?

+0

Questo thread potrebbe aiutare a ottenere ciò che si vuole: http://stackoverflow.com/questions/1517743/in-wpf-how-can-i-determine-whether-a-control-is-visible -per-l'-utente –

+0

No! Questo è solo un controllo dei limiti (vedi la mia 'nota' sopra). Questo in realtà non rappresenta ciò che è visibile. – MarqueIV

+0

Solo una pugnalata al buio - usa il reflector per esaminare l'interno della proprietà IsMouseDirectlyOver (che si trova nella maggior parte dei controlli WPF, probabilmente ereditato da FrameworkElement). Quella proprietà guarda attraverso gli oggetti nidificati per determinare se il mouse è direttamente sul controllo specifico esatto. Sto pensando che potresti essere in grado di usare una logica simile per il controllo dei limiti ... – Marko

risposta

0

Suggerirei che, in generale, all'interno del tuo metodo OnRender dovresti comporre o rendere i tuoi oggetti visibili con attenzione al loro ordine Z, ma non necessariamente spendere tempo a preoccuparsi di ciò che è visibile. Questo non è C++. Parte del ragionamento alla base del design di WPF è che il sistema dovrebbe essere in grado di decidere per te, cosa è visibile e cosa no. È destinato ad essere un livello un po 'più alto di astrazione. Se trovi che stai scrivendo il codice per verificare ciò che è visibile e quali sono i limiti di quella porzione visibile, probabilmente non lo stai usando correttamente. Sii .. un po 'più pigro. Questo (quello che hai descritto sopra) dovrebbe essere abbastanza semplice.

Mentre i tuoi oggetti visibili scivolano o si muovono in ordine verticale (ad esempio, ordine Z), diventano semplicemente visibili o meno. Se vuoi che qualcosa non sia visibile nonostante la sua posizione nell'ordine Z, lo rendi invisibile (idealmente, legandolo a una proprietà che valuta Visibility.Visible, Visibility.Hidden o Visibility.Collapsed).

Nota: quando si guardano varie implementazioni della grafica, specialmente per gli sviluppatori che arrivano su WPF da altre piattaforme, spesso scopro che non è stato necessario sovrascrivere OnRender. A meno che tu non abbia molta grafica che deve essere renderizzata in tempo reale, puoi spesso lasciare che WPF faccia il lavoro per te e solo definire ciò che vuoi mostrare all'interno del tuo XAML.

+0

Questi sono tutti ottimi punti, ma non si applicano. Noi * stiamo * facendo un sacco di rendering personalizzato a cui i binding semplici (o anche complessi) non possono occuparsi in quanto possono consistere in centinaia di calcoli prima che il rendering avvenga effettivamente.Ma la loro area di clip può cambiare in base ad altri fattori, quindi stiamo spendendo molto tempo a rendere le cose che non si vedono mai. Stai essenzialmente proponendo una soluzione alternativa a una domanda diversa, non mia. La mia domanda era trovare un modo per determinare l'area ritagliata. Grazie per la tua indicazione, comunque. Sono sicuro che potrebbe aiutare gli altri. Solo non noi. – MarqueIV

+0

E per la cronaca, sì, lo so in WPF, a meno che non abbiate a che fare, il "rendering" nella chiamata OnRender non è affatto rendering, ma piuttosto il caching delle istruzioni di disegno che verranno poi eseguite durante il chiamate effettive di rendering sull'hardware. Per il punto di questa domanda, supponiamo di usare un WriteableBitmap che dobbiamo ri-generare nella sua interezza molto frequentemente, quindi se qualcosa non è effettivamente visibile, vogliamo ottimizzare quella porzione. – MarqueIV

+0

Ok, capisco. La maggior parte dei Q di questo tipo proviene da sviluppatori relativamente nuovi per WPF o per scenari più semplici - chiaramente non è il caso qui. Non conosco una scorciatoia generalizzata. Ho fatto 2 che richiedeva una grande quantità di rendering complessi: in uno, il contenuto doveva scorrere orizzontalmente (una serie di grafici a scorrimento). Quindi ho usato WritableBitmaps organizzato in modo concettualmente sotto forma di strisce, impilate orizzontalmente. Poiché ogni striscia scivolava a sinistra fuori dalla vista, sarebbe stata contrassegnata come fuori campo e visa-versa quando le strisce vengono visualizzate a destra. Dipende interamente dalla natura geometrica dell'app – JamesWHurst

Problemi correlati