7

Ich frage mich, wie man 3 eine Ansicht wie der Xcode implementieren würde, wird mit der Build-Konfiguration:Implementierung NSOutlineView/NSTableView mit verschiedenen Zellen (und Datentypen) pro Zeile

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

Wenn Mit einem NSOutlineView/NSTableView mit Bindings und einem NSTreeController/NSArrayController erhalten die Spalten der Ansicht Bindungen zugewiesen, nicht die einzelnen Zellen, aus offensichtlichen Gründen. Wenn jede Zeile in einer Spalte die gleiche Zelle verwendet, ist es ein Kinderspiel. Wenn jedoch jede Zeile (potenziell) ihren eigenen Zelltyp (und damit möglicherweise seine eigene Sammlung von Bindungen) verwendet, dann wird die Sache funky.

Mit Blick auf den Screenshot kann man deutlich sehen, dass die Textfeld Zelle nur eine einzige Bindung für "Wert" benötigt. Während die Pop-up-Knopfzelle mindestens eine für „Inhalt“ benötigt, eine für „content“ und nicht zuletzt eine für „selectedIndex/SelectedObject/selectedValue“ Bindung. Und die Checkbox Zelle benötigt eine Bindung für "Wert" und (wahrscheinlich) eine für "Titel".

Wie würde man dies mit so sauberem (und wenig) Code wie möglich erreichen?
(Oder wie man sich fragen könnte:Wie würde Apple eine haben es getan?)

...

Hier ist, was ich bisher ausprobiert habe:
ich die entsprechenden liefern (kopiert) Zellen über [outlineView: dataCellForTableColumn: item:] und binden Sie sie an die einzelnen Datenmodelle (aus [item_representObject]). Ich kenne die genaue Menge an Daten (< 500 Zeilen), die in der Gliederungsansicht angezeigt wird, so dass eine Zelle pro Zeile nicht zu viel Speicherproblem sein sollte, nein? Ich habe die Daten, um richtig angezeigt über Bindungen (yay!), Aber ich bin nicht in der Lage, einen ihrer Werte zu ändern. O_o Anscheinend geht die Wertänderung einfach nie durch zum Datenmodell. Gibt es mehr als eine einfache [checkboxCell bind: @ "Wert" toObject: rowModel withKeyPath: @ "Wert" Optionen: nil]? (Wie dies scheint ausreichend für bekommen Werte, aber nicht für Einstellung sie entsprechend.)

konnte ich keine Informationen zu diesem Thema finden. Viele Informationen und Hinweise zur Verwendung benutzerdefinierter Zellen pro Spalte, aber keine, um sie pro Reihe zu verwenden. :(
Dies würde einige großartige Sachen für ein Cocoa Tutorial machen, nicht wahr?;)

+0

Es gibt auch NSDictionaryController. Ich weiß nicht, wie weit es dich bringen wird, aber sieh es dir an. –

+0

@Mike Es ist nicht so sehr ein Problem des Controllers, sondern eine der Tabellenansicht, die seine Zellen behandelt. Aber danke trotzdem :) – Regexident

+0

fast 5 Jahre später und das war die einzige Information, die ich über das Mischen von Bindungen mit Datenquellen auf einer Tabelle mit verschiedenen Zellen finden konnte, "Das würde einige großartige Sachen für ein Cocoa Tutorial machen, nicht wahr?" , Oh Ja! – rraallvv

Antwort

3

Die Datenzelle einer Spalte wird nicht kopiert. Die Zelle wird für den richtigen Wert für die Spalte in jeder Zeile konfiguriert und an der richtigen Stelle gezeichnet. Ein guter Einstiegspunkt ist die NSTableColumn-Methode -dataCellForRow:. In einer benutzerdefinierten Unterklasse können Sie diese Methode überschreiben und entweder ihr -DataCell für den normalen Betrieb oder einen anderen Zelltyp übergeben.

Ich hatte eine Gelegenheit, eine Checkbox-Spalte zu haben, die "include" in einer Gliederungsansicht darstellt, die nur für Kinder (Nicht-Root-Elemente) angezeigt wurde. Die Root-Elemente konnten nicht ausgeschlossen werden, nur ihre untergeordneten Elemente. Daher war es sinnvoll, nur das Kontrollkästchen für Nicht-Root-Elemente anzuzeigen.

Ich habe eine benutzerdefinierte NSTableColumn-Unterklasse erstellt, die einen Delegaten (meinen Datenquellen-Controller) akzeptiert und überprüft hat, ob sie auf den Selektor -deadCellColumn reagiert hat: sollteShowDeadCellForRow :. Wenn dies der Fall war, rief ich diese Methode (die auf meinem Datenquellen-Controller implementiert war) an, um zu fragen, ob ich eine "tote Zelle" (eine grundlegende NSCell-Unterklasse, die nichts zeigt) anzeigen und sie entsprechend der Antwort austauschen sollte. Wenn der Delegat nicht auf den Selektor reagiert hat, gibt die Tabellenspalte ihre normale -dataCell zurück.

Die benutzerdefinierte Zelle (die ich "DeadCell" nannte) wurde hier benötigt, weil ich sicherstellen wollte, dass nichts gezeichnet wurde und nichts editierbar war. Ich bin mir nicht sicher, dass es unbedingt notwendig war, aber ich habe es trotzdem getan. Das ist in Ihrem Fall nicht viel sinnvoll, aber ich wollte es trotzdem der Vollständigkeit halber angeben.

Ihre Situation ist ein bisschen komplizierter, vor allem, weil Bindings beteiligt sind (und verschiedene Datenzelltypen können unterschiedliche Bindungen für ihren Wert haben - Popups können besonders schwierig sein). In meinem Fall habe ich auf Bindungen für den bewährten Datenquellenmechanismus verzichtet. Es vereinfachte die Dinge sehr. :-) Für Ihren Fall ist es einfach genug, Zelltypen mit Datenquellenmethoden zu umgehen.

+0

Oh mein ... Ich denke, ich werde dann meine Dateneingabe vereinheitlichen müssen (mit ComboBoxCells für den einfachen Zugriff auf Vorlagenwerte) und NSFormatters verwenden, um eine korrekte Eingabe für den Werttyp jedes Elements sicherzustellen. Nicht schön, aber die Funktion, die eine solche Tabellenansicht erfordert, ist einfach nicht groß genug, um solch einen riesigen Backend-Code und wahrscheinlich Hacker in solche zu investieren. Major bummer obwohl, dass solche Sachen so ein Chaos ist, mit zu arbeiten. – Regexident

+0

Es ist überhaupt kein Hacker beteiligt. Es ist alles gültige Verwendung des Kontroll-/Zellmechanismus. Außerdem sind Cocoa Bindings mehr auf die "Rapid Application Development" -Seite der Dinge ausgerichtet, die nur Code für die allgemeineren Fälle eliminiert. Wenn Sie spezielle Dinge tun wollen, müssen Sie Code verwenden. In vielen Situationen können Sie die beiden kombinieren (Bindungen und Datenquelle). Wenn Ihre Zelltypen alle die gleichen Bindungen haben, benötigen Sie in dieser Situation nur Ihre benutzerdefinierte Spalte und alles andere sollte "einfach funktionieren". –

+0

Ja, aber sie ** ** nicht ** teilen die gleichen Bindungen :( Und das Feature wird sowieso ein nerdy sein, mit einer sehr begrenzten potenziellen Benutzerbasis, so einfach nicht so eine übermäßige Anstrengung wert, während Produkt Release verzögert.: ("große Entwickler versenden", richtig?;) Aber danke für die Lösung.Ich bin mir sicher, dass ich etwas dafür nicht zu weit weg haben werde .. – Regexident

Verwandte Themen