2010-08-01 10 views
7

Mi chiedo come si potrebbe implementare una vista struttura come quella Xcode 3 sta usando per la configurazione di generazione:Implementazione NSOutlineView/NSTableView con diverse cellule (e tipi di dati) per fila

alt text http://img812.imageshack.us/img812/9467/xcodeoutlineview.png

Quando utilizzando un NSOutlineView/NSTableView con binding e un NSTreeController/NSArrayController, le colonne della vista ottengono i binding assegnati a, non le singole celle, per ovvi motivi. Se ogni riga di una colonna utilizza la stessa cella, è un gioco da ragazzi. Tuttavia se ogni riga (potenzialmente) utilizza il proprio tipo di cella (e con quello potenzialmente la propria raccolta di binding), le cose diventano funky.

Guardando lo screenshot si può vedere chiaramente che la cella del campo di testo ha bisogno di una sola associazione per "valore". Mentre la pila a bottone popup ha bisogno di almeno uno per "contenuti", uno per "contentValues ​​" e, ultimo ma non meno importante un vincolanti per "selectedIndex/selectedObject/SelectedValue". E la casella di controllo ha bisogno di un binding per "valore" e (probabilmente) uno per "titolo".

Come si può ottenere ciò con un codice pulito (e poco) il più possibile?
(O come ci si potrebbe chiedere:Come sarebbe Apple hanno fatto?)

...

Ecco quello che io stesso ho provato finora:
fornisco celle appropriate (copiate) via [outlineView: dataCellForTableColumn: item:] e collegarli ai singoli modelli di dati (da [item representationObject]). Conosco la quantità esatta di dati (< 500 righe) visualizzata nella vista struttura, quindi avere una cella per riga non dovrebbe essere un problema di memoria, no? Ho ottenuto i dati per essere visualizzati correttamente tramite binding (yay!) Tuttavia non sono in grado di modificare nessuno dei loro valori. O_o Apparentemente la modifica del valore non passa mai direttamente al modello dati. C'è altro oltre a un semplice [checkboxCell bind: @ "valore" toObject: rowModel withKeyPath: @ "valore" opzioni: nil]? (Come questo sembra sufficiente per ottenere valori, ma non per l'impostazione di conseguenza.)

non ho trovato alcuna informazione su questo argomento. Un sacco di informazioni e suggerimenti per l'utilizzo di celle personalizzate per colonna, ma nessuno per il loro utilizzo su una base "per riga". :(
Ciò renderebbe alcune grandi cose per un tutorial di Cocoa, non è vero?;)

+0

C'è anche NSDictionaryController. Non so fino a dove ti porterà, ma dai un'occhiata. –

+0

@Mike Non è tanto un problema del controller, ma uno della vista tabella che gestisce le sue celle. Ma grazie comunque :) – Regexident

+0

quasi 5 anni più tardi e questa era l'unica informazione che potevo trovare sul mixare i binding con la sorgente dati su un tavolo con celle diverse, "Questo renderebbe alcune cose grandiose per un tutorial di Cocoa, no?" , diamine si! – rraallvv

risposta

3

La cella di dati di una colonna non viene copiata. La cella è configurata per il valore corretto per la colonna in ogni riga e disegnata nella sua posizione corretta. Un buon punto di aggancio è il metodo NSTableColumn -dataCellForRow:. In una sottoclasse personalizzata, è possibile sovrascrivere questo metodo e passare il suo -dataCell per l'operazione normale o un tipo di cella alternativo.

Ho avuto l'occasione di avere una colonna checkbox che rappresenta "include" in una vista struttura che appariva solo per i bambini (elementi non-root). Gli oggetti radice non potevano essere esclusi, solo i loro figli, quindi aveva senso solo mostrare la casella di controllo per gli elementi non-root.

Ho creato una sottoclasse NSTableColumn personalizzata che ha preso un delegato (il mio controller di origine dati) e controllato per vedere se ha risposto al selector -deadCellColumn: shouldShowDeadCellForRow :. Se così fosse, ho chiamato quel metodo (che è stato implementato sul mio controller di origine dati) per chiedergli se dovrei mostrare una "cella morta" (una sottoclasse di base NSCell che non disegna nulla) e scambiarla in base alla risposta. Se il delegato non ha risposto al selettore, la colonna della tabella restituisce il suo normale -dataCell.

La cella personalizzata (che ho chiamato "DeadCell") era necessaria qui perché volevo assicurarmi che nulla venisse disegnato e che nulla fosse modificabile. Non sono sicuro che fosse strettamente necessario, ma l'ho fatto lo stesso. Questo non è molto utile nel tuo caso, ma ho voluto dichiararlo comunque per completezza.

La situazione è un po 'più complicata, soprattutto perché i collegamenti sono coinvolti (e diversi tipi di celle di dati possono avere legami diversi per il loro valore - i popup possono essere particolarmente impegnativi). Nel mio caso, ho evitato i binding per il meccanismo di origine dei dati provato e vero. Ha semplificato molto le cose. :-) Per il tuo caso, è abbastanza facile scambiare i tipi di cella usando i metodi di origine dei dati.

+0

Oh my ... Immagino che dovrò "just_" unificare il mio input di dati (usando ComboBoxCells per un facile accesso ai valori del template) e usare NSFormatters per garantire un input corretto per il tipo di valore di ciascun oggetto. Non è bello, ma la funzionalità che richiede tale visualizzazione tabella non è abbastanza grande/importante da investire un codice backend così grande e probabilmente un hacker. Un grosso peccato, però, che roba del genere sia un tale casino con cui lavorare. – Regexident

+0

Non vi è alcun coinvolgimento di hacker. È tutto l'uso valido del meccanismo di controllo/cella. Inoltre, Cocoa Bindings è più rivolto al lato "sviluppo rapido delle applicazioni", che elimina solo il codice per i casi più generalizzati. Se vuoi fare cose speciali, devi usare il codice. In molte situazioni, è possibile combinare i due (collegamenti e origine dati). In questa situazione, se i tuoi tipi di cella condividono tutti gli stessi binding, hai solo bisogno della tua colonna personalizzata e tutto il resto dovrebbe "funzionare". –

+0

Sì, ma loro ** non ** condividono gli stessi collegamenti :( E la funzione sarà comunque nerd, con una base di utenti potenzialmente molto limitata, quindi semplicemente non vale la pena di compiere uno sforzo eccessivo mentre si fa ritardare il rilascio del prodotto. ("I grandi sviluppatori spediscono", giusto?;) Ma grazie per la soluzione, sono sicuro che ne avrò un po 'd'uso non troppo lontano – Regexident

Problemi correlati