Динамическое скрытие столбцов в NSTableView

StackOverflow https://stackoverflow.com/questions/68821

  •  09-06-2019
  •  | 
  •  

Вопрос

Я хочу динамически скрывать / показывать некоторые столбцы в NSTableView на основе данных, которые будут отображаться - в принципе, если столбец пуст, я бы хотел, чтобы столбец был скрыт.В настоящее время я заполняю таблицу классом контроллера в качестве делегата для таблицы.

Есть какие-нибудь идеи?Я вижу, что могу установить скрытый столбец в Interface Builder, однако, похоже, сейчас не самое подходящее время просматривать столбцы и проверять, пусты они или нет, поскольку, похоже, не существует метода, который вызывался бы до / после заполнения всех данных в таблице.

Это было полезно?

Решение

NSTable - это просто класс, который рисует таблицу.Как вы сами сказали, у вас есть какой-то класс, который вы предоставляете таблице в качестве делегата, и этот класс загружает в таблицу данные для отображения.Если вы храните данные таблицы как NSArray в вашем классе делегата, должно быть легко выяснить, пуст ли один столбец, не так ли?И NSArray запрашивает ваш класс через метод делегирования, сколько в нем столбцов, поэтому, когда вас спросят, почему бы не посмотреть, сколько столбцов у вас есть данных, и сообщить это число вместо реального количества столбцов, которые вы храните внутри, а затем, когда вас попросят предоставить данные для (столбца, строки), просто пропустите пустой столбец.

Другие советы

В Mac OS X версии 10.5 и более поздних версиях есть setHidden: селектор для NSTableColumn.

Это позволяет динамически скрывать / показывать столбцы с использованием идентификаторов:

NSInteger colIdx;
NSTableColumn* col;

colIdx = [myTable columnWithIdentifier:@"columnIdent"];
col = [myTable.tableColumns objectAtIndex:colIdx];
[col setHidden:YES];

Я сделал это с помощью привязок, но настроил их программно, а не через Interface Builder.

Этот псевдо-фрагмент должен дать вам представление об этом:

NSTableColumn *aColumn = [[NSTableColumn alloc] initWithIdentifier:attr];
[aColumn setWidth:DEFAULTCOLWIDTH];
[aColumn setMinWidth:MINCOLWIDTH];
[[aColumn headerCell] setStringValue:columnLabel];

[aColumn bind:@"value"
     toObject:arrayController 
  withKeyPath:keyPath 
  options:nil];             

[tableView addTableColumn:aColumn];
[aColumn release];

Конечно, вы также можете добавить форматеры и все такое прочее.

Это не работает в конструкторе интерфейсов.Однако это работает программно.Вот как я привязываю NSTableViewColumn с идентификатором "Status" к ключу в моем NSUserDefaults:

Быстрый:

tableView.tableColumnWithIdentifier("Status")?.bind("hidden", toObject: NSUserDefaults.standardUserDefaults(), withKeyPath: "TableColumnStatus", options: nil)

Цель-C:

[[self.tableView tableColumnWithIdentifier:@"Status"] bind:@"hidden" toObject:[NSUserDefaults standardUserDefaults] withKeyPath:@"TableColumnStatus" options:nil];

На данный момент у меня нет полного ответа, но посмотрите на Привязки.Как правило, с привязками Cocoa можно делать все, что угодно.

Для NSTableColumn нет привязки к видимости, но вы можете установить ширину равной 0.

Затем вы можете привязать его к заполнителю Null и установить это значение равным 0, но не забудьте установить для других заполнителей разумные значения.

(Как я уже сказал, это только начало, возможно, потребуется некоторая доработка).

Невозможно заполнить все данные за один раз.NSTableView не хранит данные, он динамически запрашивает их из своего источника данных (или привязанных к объектам, если вы используете привязки).Он просто рисует, используя данные, которые получает из источника данных, и отбрасывает их.Вы не должны видеть, как таблица запрашивает данные для чего-либо, что не видно, например.

Похоже, вы используете источник данных?Когда данные изменяются, вы несете ответственность за вызов -reloadData в таблице, что немного неправильно.Это больше похоже на "аннулировать все".

То есть вы уже должны знать, когда изменяются данные.Это точка, в которой вы можете вычислить, какие столбцы должны быть скрыты.

@amrox - Если я правильно понимаю ваше предложение, вы говорите, что я должен привязать значение к скрытому свойству NSTableColumns в моей таблице?Похоже, что это сработало бы, однако я не думаю, что у NSTableColumn есть скрытое свойство, поскольку сообщения isHidden и setHidden контролируют видимость столбца, что говорит мне о том, что это не свойство, если я чего-то не упускаю (что вполне возможно).

Я хотел бы опубликовать свое решение, обновленное для Swift 4, используя привязки Cocoa и фактический isHidden отметьте, не касаясь ширины столбца (так как впоследствии вам может потребоваться восстановить исходное значение ...).Предположим, у нас есть флажок для переключения видимости некоторого столбца (или вы всегда можете переключить hideColumnsFlag переменную в приведенном ниже примере любым другим способом, который вам нравится):

class ViewController: NSViewController {

     // define the boolean binding variable to hide the columns and use its name as keypath
     @objc dynamic var hideColumnsFlag = true

     // Referring the column(s)
     // Method 1: creating IBOutlet(s) for the column(s): just ctrl-drag each column here to add it
     @IBOutlet weak var hideableTableColumn: NSTableColumn!
     // add as many column outlets as you need...

     // or, if you prefer working with columns' string keypaths
     // Method 2: use just the table view IBOutlet and its column identifiers (you **must** anyway set the latter identifiers manually via IB for each column)
     @IBOutlet weak var theTableView: NSTableView! // this line could be actually removed if using the first method on this example, but in a real case, you will probably need it anyway.

     // MARK: View Controller Lifecycle

     override func viewDidLoad() {
         super.viewDidLoad()

         // Method 1
         // referring the columns by using the outlets as such:
         hideableTableColumn.bind(.hidden, to: self, withKeyPath: "hideColumnsFlag", options: nil)
         // repeat for each column outlet.

         // Method 2
         // or if you need/prefer to use the column identifiers strings then:
         // theTableView.tableColumn(withIdentifier: .init("columnName"))?.bind(.hidden, to: self, withKeyPath: "hideColumnsFlag", options: nil)
         // repeat for each column identifier you have set.

         // obviously use just one method by commenting/uncommenting one or the other.
     }

     // MARK: Actions

     // this is the checkBox action method, just toggling the boolean variable bound to the columns in the viewDidLoad method.
     @IBAction func hideColumnsCheckboxAction(_ sender: NSButton) {
         hideColumnsFlag = sender.state == .on
     }
}

Как вы, возможно, заметили, пока нет способа привязать Hidden установите флажок в построителе интерфейса, как в XCode10:вы можете видеть Enabled или Editable привязки, но только программно у вас будет доступ к isHidden установите флажок для столбца, как это называется в Swift.

Как отмечено в комментариях, второй метод основан на идентификаторах столбцов, которые вы должны вручную задать либо через Interface Builder в поле Identity после выбора соответствующих столбцов, либо, если у вас есть массив имен столбцов, вы можете перечислить столбцы таблицы и назначить идентификаторы, а также привязки вместо повторения аналогичных строк кода.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top