Pergunta

Quero ocultar/mostrar dinamicamente algumas das colunas em um NSTableView, com base nos dados que serão exibidos - basicamente, se uma coluna estiver vazia, gostaria que ela fosse ocultada.Atualmente estou preenchendo a tabela com uma classe de controlador como delegado da tabela.

Alguma ideia?Vejo que posso definir a coluna oculta no Interface Builder, porém não parece ser um bom momento para percorrer as colunas e verificar se estão vazias ou não, já que não parece haver um método que seja chamado antes/depois de todos os dados da tabela serem preenchidos.

Foi útil?

Solução

Uma NSTable é apenas a classe que pinta a mesa.Como você mesmo disse, você tem uma classe que dá à tabela como delegado e essa classe alimenta a tabela com os dados a serem exibidos.Se você armazenar os dados da tabela como NSArray em sua classe delegada, será fácil descobrir se uma coluna está vazia, não é?E o NSArray pergunta à sua classe através do método delegado quantas colunas existem, então quando for perguntado, por que não procurar quantas colunas você tem dados e relatar esse número em vez do número real de colunas que você armazena internamente e quando for solicitado fornecendo os dados para (coluna, linha), basta pular a coluna vazia.

Outras dicas

No Mac OS X v10.5 e posterior, existe o setHidden: seletor para NSTableColumn.

Isso permite que as colunas sejam ocultadas/mostradas dinamicamente com o uso de identificadores:

NSInteger colIdx;
NSTableColumn* col;

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

Fiz isso com ligações, mas configurando-as programaticamente, em vez de por meio do Interface Builder.

Este psuedo-snippet deve lhe dar a essência:

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];

Claro que você também pode adicionar formatadores e tudo mais.

Não funciona no Interface Builder.No entanto, funciona programaticamente.Aqui está como eu vinculo um NSTableViewColumn com o identificador "Status" a uma chave em meus NSUserDefaults:

Rápido:

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

Objetivo-C:

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

Não tenho uma resposta completa no momento, mas dê uma olhada em Bindings.Geralmente é possível fazer todo tipo de coisa com Cocoa Bindings.

Não há vinculação de visibilidade para NSTableColumn, mas você pode definir a largura como 0.

Em seguida, você pode vinculá-lo ao Null Placeholder e definir esse valor como 0 - mas não se esqueça de definir os outros Placeholders com valores razoáveis.

(Como eu disse, isso é apenas o começo, pode precisar de alguns ajustes).

Não há um único momento em que todos os dados sejam preenchidos.NSTableView não armazena dados, ele os solicita dinamicamente a partir de sua fonte de dados (ou de objetos vinculados, se você estiver usando ligações).Ele apenas desenha usando dados obtidos da fonte de dados e os descarta.Você não deverá ver a tabela solicitando dados para algo que não esteja visível, por exemplo.

Parece que você está usando uma fonte de dados?Quando os dados mudam, é sua responsabilidade chamar -reloadData na tabela, o que é um nome um pouco impróprio.É mais como 'invalidar tudo'.

Ou seja, você já deve saber quando os dados mudam.Esse é o ponto em que você pode calcular quais colunas devem ser ocultadas.

@amrox - Se entendi sua sugestão corretamente, você está dizendo que devo vincular um valor à propriedade oculta de NSTableColumns em minha tabela?Parece que funcionaria, mas não acho que NSTableColumn tenha uma propriedade oculta, já que as mensagens isHidden e setHidden controlam a visibilidade da coluna - o que me diz que isso não é uma propriedade, a menos que esteja faltando alguma coisa (o que é bem possível).

Gostaria de postar minha solução atualizada para Swift 4 usando ligações Cocoa e o real isHidden flag sem tocar nas larguras das colunas (pois pode ser necessário restaurar o valor original posteriormente...).Suponha que temos uma caixa de seleção para alternar a visibilidade da coluna (ou você sempre pode alternar a hideColumnsFlag variável no exemplo abaixo de qualquer outra maneira que você desejar):

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
     }
}

Como você deve ter notado, ainda não há como vincular o Hidden sinalizador no Interface Builder como no XCode10:você pode ver o Enabled ou Editable ligações, mas apenas programaticamente você terá acesso ao isHidden sinalizador para a coluna, como é chamado em Swift.

Conforme observado nos comentários, o segundo método depende dos identificadores de coluna que você deve definir manualmente por meio do Interface Builder no campo Identidade após selecionar as colunas relevantes ou, se você tiver uma matriz de nomes de colunas, poderá enumerar as colunas da tabela e atribuir o identificadores, bem como as ligações, em vez de repetir linhas de código semelhantes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top