Question

Je souhaite masquer / afficher de manière dynamique certaines des colonnes d'un NSTableView, en fonction des données qui seront affichées. En gros, si une colonne est vide, j'aimerais que la colonne soit masquée. Je remplis actuellement la table avec une classe de contrôleur en tant que délégué de la table.

Des idées? Je vois que je peux définir la colonne masquée dans Interface Builder, mais il ne semble pas y avoir de bon moment pour parcourir les colonnes et vérifier si elles sont vides ou non, car il ne semble pas y avoir de méthode appelé avant / après le remplissage de toutes les données de la table.

Était-ce utile?

La solution

Une table NSTable est simplement la classe qui peint la table. Comme vous l'avez dit vous-même, vous donnez une classe à la table en tant que délégué et cette classe alimente la table avec les données à afficher. Si vous stockez les données de la table sous forme de NSArray dans votre classe de délégué, il devrait être facile de savoir si une colonne est vide, n'est-ce pas? Et NSArray demande à votre classe via la méthode déléguée combien de colonnes il y a, alors quand on vous le demande, pourquoi ne pas chercher combien de colonnes vous avez et rapportez ce nombre au lieu du nombre réel de colonnes que vous stockez en interne et ensuite quand on vous le demande fournissant les données pour (colonne, ligne), ignorez simplement la colonne vide.

Autres conseils

Sous Mac OS X version 10.5 et ultérieure, sélecteur setHidden: pour NSTableColumn.

Ceci permet aux colonnes d'être masquées / affichées dynamiquement à l'aide d'identifiants:

NSInteger colIdx;
NSTableColumn* col;

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

Je l'ai fait avec des liaisons, mais en les configurant par programme plutôt que via Interface Builder.

Ce fragment de code devrait vous en donner l'essentiel:

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

Bien sûr, vous pouvez aussi ajouter des formateurs et tout ça.

Cela ne fonctionne pas dans Interface Builder. Cependant, cela fonctionne par programmation. Voici comment je lie un NSTableViewColumn avec l'identifiant "Etat". à une clé de mes NSUserDefaults:

Swift:

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

Objective-C:

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

Je n’ai pas de réponse complète pour l’instant, mais examinez Bindings. Il est généralement possible de faire toutes sortes de choses avec Cocoa Bindings.

Il n'y a pas de liaison Visibility pour NSTableColumn, mais vous pourrez peut-être définir la largeur sur 0.

Ensuite, vous pouvez le lier à l'espace réservé nul et définir cette valeur sur 0, sans oublier de définir les autres espaces réservés sur des valeurs raisonnables.

(Comme je l'ai dit, ceci n'est qu'un début, il pourrait être nécessaire de le peaufiner).

Il n’existe pas un jour où toutes les données sont renseignées. NSTableView ne stocke pas de données, il les demande de manière dynamique à sa source de données (ou à des objets liés si vous utilisez des liaisons). Il tire simplement à l'aide des données qu'il obtient de la source de données et les abandonne. Vous ne devriez pas voir la table demander des données pour tout ce qui n'est pas visible, par exemple.

On dirait que vous utilisez une source de données? Lorsque les données changent, il est de votre responsabilité d'appeler -reloadData sur la table, ce qui est un peu trompeur. Cela ressemble plus à «tout invalider».

Autrement dit, vous devriez déjà savoir quand les données changent. C’est à ce stade que vous pouvez calculer quelles colonnes doivent être masquées.

@amrox - Si je comprends bien votre suggestion, vous dites que je devrais lier une valeur à la propriété masquée des NSTableColumns de ma table? Cela semble fonctionner, mais je ne pense pas que NSTableColumn ait une propriété cachée, car les messages isHidden et setHidden contrôlent la visibilité de la colonne - ce qui me dit que ce n'est pas une propriété, sauf si quelque chose me manque (ce qui est tout à fait possible).

Je souhaite publier ma solution mise à jour pour Swift 4 à l'aide de liaisons Cocoa et du drapeau isHidden sans toucher à la largeur des colonnes (car vous devrez peut-être restaurer la valeur d'origine par la suite ...). Supposons que nous ayons une case à cocher pour basculer la visibilité des colonnes (ou que vous puissiez toujours basculer la variable hideColumnsFlag dans l'exemple ci-dessous de la manière que vous préférez):

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

Comme vous l'avez peut-être remarqué, il n'est pas encore possible de lier l'indicateur Hidden dans Interface Builder comme sur XCode10: vous pouvez voir le activé ou le éditable. , mais uniquement par programmation, vous aurez accès à l'indicateur isHidden de la colonne, comme elle est appelée dans Swift.

Comme indiqué dans les commentaires, la deuxième méthode s'appuie sur les identificateurs de colonne que vous devez définir manuellement via Interface Builder dans le champ Identité après avoir sélectionné les colonnes appropriées ou, si vous disposez d'un tableau de noms de colonnes, vous pouvez énumérer les colonnes de la table. et assigner les identifiants ainsi que les liaisons au lieu de répéter des lignes de code similaires.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top