ist jetzt verfügbar! Lesen Sie über die neuen Funktionen und Fehlerbehebungen vom November.

Tree View API

Die Tree View API ermöglicht Erweiterungen, Inhalte in der Seitenleiste von Visual Studio Code anzuzeigen. Diese Inhalte sind als Baumstruktur aufgebaut und entsprechen dem Stil der integrierten Ansichten von VS Code.

Zum Beispiel zeigt die integrierte Referenzsuchansicht-Erweiterung Referenzsuchergebnisse als separate Ansicht an.

References Search View

Die Ergebnisse von Alle Referenzen finden werden in einer Referenzen: Ergebnisse-Baumansicht angezeigt, die sich im Referenzen-Ansichtscontainer befindet.

Dieser Leitfaden zeigt Ihnen, wie Sie eine Erweiterung schreiben, die Baumansichten und Ansichtscontainer zu Visual Studio Code hinzufügt.

Grundlagen der Tree View API

Um die Tree View API zu erklären, werden wir eine Beispielerweiterung namens Node Dependencies erstellen. Diese Erweiterung verwendet eine Baumansicht, um alle Node.js-Abhängigkeiten im aktuellen Ordner anzuzeigen. Die Schritte zum Hinzufügen einer Baumansicht sind: Beitrag zur Baumansicht in Ihrer package.json, Erstellen eines TreeDataProvider und Registrieren des TreeDataProvider. Den vollständigen Quellcode dieser Beispielerweiterung finden Sie im tree-view-sample im GitHub-Repository vscode-extension-samples.

package.json-Beitrag

Zuerst müssen Sie VS Code mitteilen, dass Sie eine Ansicht beisteuern, indem Sie den Beitragspunkt contributes.views in package.json verwenden.

Hier ist die package.json für die erste Version unserer Erweiterung

{
  "name": "custom-view-samples",
  "displayName": "Custom view Samples",
  "description": "Samples for VS Code's view API",
  "version": "0.0.1",
  "publisher": "alexr00",
  "engines": {
    "vscode": "^1.74.0"
  },
  "activationEvents": [],
  "main": "./out/extension.js",
  "contributes": {
    "views": {
      "explorer": [
        {
          "id": "nodeDependencies",
          "name": "Node Dependencies"
        }
      ]
    }
  },
  "scripts": {
    "vscode:prepublish": "npm run compile",
    "compile": "tsc -p ./",
    "watch": "tsc -watch -p ./"
  },
  "devDependencies": {
    "@types/node": "^10.12.21",
    "@types/vscode": "^1.42.0",
    "typescript": "^3.5.1",
    "tslint": "^5.12.1"
  }
}

Hinweis: Wenn Ihre Erweiterung auf eine VS Code-Version vor 1.74 abzielt, müssen Sie onView:nodeDependencies explizit in activationEvents auflisten.

Sie müssen eine Kennung und einen Namen für die Ansicht angeben, und Sie können zu den folgenden Speicherorten beitragen

  • explorer: Explorer-Ansicht in der Seitenleiste
  • debug: Ausführen und Debuggen-Ansicht in der Seitenleiste
  • scm: Quellcodeverwaltung-Ansicht in der Seitenleiste
  • test: Test-Explorer-Ansicht in der Seitenleiste
  • Benutzerdefinierte Ansichtscontainer

Tree Data Provider

Der zweite Schritt ist die Bereitstellung von Daten für die Ansicht, die Sie registriert haben, damit VS Code die Daten in der Ansicht anzeigen kann. Dazu sollten Sie zuerst den TreeDataProvider implementieren. Unser TreeDataProvider stellt Node-Abhängigkeitsdaten bereit, aber Sie können einen Datenanbieter haben, der andere Arten von Daten bereitstellt.

Es gibt zwei notwendige Methoden in dieser API, die Sie implementieren müssen

  • getChildren(element?: T): ProviderResult<T[]> - Implementieren Sie dies, um die Kinder für das gegebene element oder die Wurzel (wenn kein Element übergeben wird) zurückzugeben.
  • getTreeItem(element: T): TreeItem | Thenable<TreeItem> - Implementieren Sie dies, um die UI-Darstellung (TreeItem) des Elements zurückzugeben, das in der Ansicht angezeigt wird.

Wenn der Benutzer die Baumansicht öffnet, wird die Methode getChildren ohne element aufgerufen. Von dort sollte Ihr TreeDataProvider Ihre obersten Baum-Elemente zurückgeben. In unserem Beispiel ist der collapsibleState der obersten Baum-Elemente TreeItemCollapsibleState.Collapsed, was bedeutet, dass die obersten Baum-Elemente als zusammengeklappt angezeigt werden. Das Setzen von collapsibleState auf TreeItemCollapsibleState.Expanded führt dazu, dass Baum-Elemente als erweitert angezeigt werden. Das Belassen von collapsibleState auf seinem Standardwert von TreeItemCollapsibleState.None zeigt an, dass das Baum-Element keine Kinder hat. getChildren wird nicht für Baum-Elemente mit einem collapsibleState von TreeItemCollapsibleState.None aufgerufen.

Hier ist ein Beispiel für eine TreeDataProvider-Implementierung, die Node-Abhängigkeitsdaten bereitstellt

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

export class NodeDependenciesProvider implements vscode.TreeDataProvider<Dependency> {
  constructor(private workspaceRoot: string) {}

  getTreeItem(element: Dependency): vscode.TreeItem {
    return element;
  }

  getChildren(element?: Dependency): Thenable<Dependency[]> {
    if (!this.workspaceRoot) {
      vscode.window.showInformationMessage('No dependency in empty workspace');
      return Promise.resolve([]);
    }

    if (element) {
      return Promise.resolve(
        this.getDepsInPackageJson(
          path.join(this.workspaceRoot, 'node_modules', element.label, 'package.json')
        )
      );
    } else {
      const packageJsonPath = path.join(this.workspaceRoot, 'package.json');
      if (this.pathExists(packageJsonPath)) {
        return Promise.resolve(this.getDepsInPackageJson(packageJsonPath));
      } else {
        vscode.window.showInformationMessage('Workspace has no package.json');
        return Promise.resolve([]);
      }
    }
  }

  /**
   * Given the path to package.json, read all its dependencies and devDependencies.
   */
  private getDepsInPackageJson(packageJsonPath: string): Dependency[] {
    if (this.pathExists(packageJsonPath)) {
      const toDep = (moduleName: string, version: string): Dependency => {
        if (this.pathExists(path.join(this.workspaceRoot, 'node_modules', moduleName))) {
          return new Dependency(
            moduleName,
            version,
            vscode.TreeItemCollapsibleState.Collapsed
          );
        } else {
          return new Dependency(moduleName, version, vscode.TreeItemCollapsibleState.None);
        }
      };

      const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));

      const deps = packageJson.dependencies
        ? Object.keys(packageJson.dependencies).map(dep =>
            toDep(dep, packageJson.dependencies[dep])
          )
        : [];
      const devDeps = packageJson.devDependencies
        ? Object.keys(packageJson.devDependencies).map(dep =>
            toDep(dep, packageJson.devDependencies[dep])
          )
        : [];
      return deps.concat(devDeps);
    } else {
      return [];
    }
  }

  private pathExists(p: string): boolean {
    try {
      fs.accessSync(p);
    } catch (err) {
      return false;
    }
    return true;
  }
}

class Dependency extends vscode.TreeItem {
  constructor(
    public readonly label: string,
    private version: string,
    public readonly collapsibleState: vscode.TreeItemCollapsibleState
  ) {
    super(label, collapsibleState);
    this.tooltip = `${this.label}-${this.version}`;
    this.description = this.version;
  }

  iconPath = {
    light: path.join(__filename, '..', '..', 'resources', 'light', 'dependency.svg'),
    dark: path.join(__filename, '..', '..', 'resources', 'dark', 'dependency.svg')
  };
}

Registrieren des TreeDataProvider

Der dritte Schritt ist die Registrierung des obigen Datenanbieters für Ihre Ansicht.

Dies kann auf folgende zwei Arten erfolgen

  • vscode.window.registerTreeDataProvider - Registriert den Baumdatenanbieter, indem die registrierte Ansichts-ID und der obige Datenanbieter übergeben werden.

    const rootPath =
      vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0
        ? vscode.workspace.workspaceFolders[0].uri.fsPath
        : undefined;
    vscode.window.registerTreeDataProvider(
      'nodeDependencies',
      new NodeDependenciesProvider(rootPath)
    );
    
  • vscode.window.createTreeView - Erstellt die Baumansicht, indem die registrierte Ansichts-ID und der obige Datenanbieter übergeben werden. Dies gibt Zugriff auf die TreeView, die Sie für andere Ansichtsoperationen verwenden können. Verwenden Sie createTreeView, wenn Sie die TreeView API benötigen.

    vscode.window.createTreeView('nodeDependencies', {
      treeDataProvider: new NodeDependenciesProvider(rootPath)
    });
    

Hier ist die Erweiterung in Aktion

View

Aktualisieren des Tree View-Inhalts

Unsere Node-Abhängigkeitsansicht ist einfach und wird nach der Anzeige der Daten nicht aktualisiert. Es wäre jedoch nützlich, eine Aktualisierungsschaltfläche in der Ansicht zu haben und die Node-Abhängigkeitsansicht mit den aktuellen Inhalten von package.json zu aktualisieren. Dazu können wir das Ereignis onDidChangeTreeData verwenden.

  • onDidChangeTreeData?: Event<T | undefined | null | void> - Implementieren Sie dies, wenn sich Ihre Baumdaten ändern können und Sie die Baumansicht aktualisieren möchten.

Fügen Sie Folgendes zu Ihrem NodeDependenciesProvider hinzu.

  private _onDidChangeTreeData: vscode.EventEmitter<Dependency | undefined | null | void> = new vscode.EventEmitter<Dependency | undefined | null | void>();
  readonly onDidChangeTreeData: vscode.Event<Dependency | undefined | null | void> = this._onDidChangeTreeData.event;

  refresh(): void {
    this._onDidChangeTreeData.fire();
  }

Jetzt haben wir eine Aktualisierungsmethode, aber niemand ruft sie auf. Wir können einen Befehl hinzufügen, um die Aktualisierung aufzurufen.

Fügen Sie im Abschnitt contributes Ihrer package.json hinzu

    "commands": [
            {
                "command": "nodeDependencies.refreshEntry",
                "title": "Refresh",
                "icon": {
                    "light": "resources/light/refresh.svg",
                    "dark": "resources/dark/refresh.svg"
                }
            },
    ]

Und registrieren Sie den Befehl bei der Aktivierung Ihrer Erweiterung

import * as vscode from 'vscode';
import { NodeDependenciesProvider } from './nodeDependencies';

export function activate(context: vscode.ExtensionContext) {
  const rootPath =
    vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0
      ? vscode.workspace.workspaceFolders[0].uri.fsPath
      : undefined;
  const nodeDependenciesProvider = new NodeDependenciesProvider(rootPath);
  vscode.window.registerTreeDataProvider('nodeDependencies', nodeDependenciesProvider);
  vscode.commands.registerCommand('nodeDependencies.refreshEntry', () =>
    nodeDependenciesProvider.refresh()
  );
}

Jetzt haben wir einen Befehl, der die Node-Abhängigkeitsansicht aktualisiert, aber eine Schaltfläche in der Ansicht wäre noch besser. Wir haben bereits ein icon zum Befehl hinzugefügt, daher wird er mit diesem Symbol angezeigt, wenn wir ihn zur Ansicht hinzufügen.

Fügen Sie im Abschnitt contributes Ihrer package.json hinzu

"menus": {
    "view/title": [
        {
            "command": "nodeDependencies.refreshEntry",
            "when": "view == nodeDependencies",
            "group": "navigation"
        },
    ]
}

Aktivierung

Es ist wichtig, dass Ihre Erweiterung nur dann aktiviert wird, wenn der Benutzer die Funktionalität benötigt, die Ihre Erweiterung bietet. In diesem Fall sollten Sie erwägen, Ihre Erweiterung nur dann zu aktivieren, wenn der Benutzer beginnt, die Ansicht zu verwenden. VS Code erledigt dies automatisch für Sie, wenn Ihre Erweiterung eine Ansichtsbeitrag deklariert. VS Code gibt ein Aktivierungsereignis onView:${viewId} (onView:nodeDependencies für das obige Beispiel) aus, wenn der Benutzer die Ansicht öffnet.

Hinweis: Für VS Code-Versionen vor 1.74.0 müssen Sie dieses Aktivierungsereignis explizit in package.json registrieren, damit VS Code Ihre Erweiterung für diese Ansicht aktiviert

"activationEvents": [
       "onView:nodeDependencies",
],

Ansichtscontainer

Ein Ansichtscontainer enthält eine Liste von Ansichten, die in der Aktivitätsleiste oder im Panel zusammen mit den integrierten Ansichtscontainern angezeigt werden. Beispiele für integrierte Ansichtscontainer sind Quellcodeverwaltung und Explorer.

View Container

Um einen Ansichtscontainer beizusteuern, sollten Sie ihn zuerst mit dem Beitragspunkt contributes.viewsContainers in package.json registrieren.

Sie müssen die folgenden erforderlichen Felder angeben

  • id - Die ID des neuen Ansichtscontainers, den Sie erstellen.
  • title - Der Name, der oben im Ansichtscontainer angezeigt wird.
  • icon - Ein Bild, das für den Ansichtscontainer in der Aktivitätsleiste angezeigt wird.
"contributes": {
  "viewsContainers": {
    "activitybar": [
      {
        "id": "package-explorer",
        "title": "Package Explorer",
        "icon": "media/dep.svg"
      }
    ]
  }
}

Alternativ könnten Sie diese Ansicht dem Panel beisteuern, indem Sie sie unter dem panel-Knoten platzieren.

"contributes": {
  "viewsContainers": {
    "panel": [
      {
        "id": "package-explorer",
        "title": "Package Explorer",
        "icon": "media/dep.svg"
      }
    ]
  }
}

Ansichten zu Ansichtscontainern beisteuern

Nachdem Sie einen Ansichtscontainer erstellt haben, können Sie den Beitragspunkt contributes.views in package.json verwenden.

"contributes": {
  "views": {
    "package-explorer": [
      {
        "id": "nodeDependencies",
        "name": "Node Dependencies",
        "icon": "media/dep.svg",
        "contextualTitle": "Package Explorer"
      }
    ]
  }
}

Eine Ansicht kann auch eine optionale Eigenschaft visibility haben, die auf visible, collapsed oder hidden gesetzt werden kann. Diese Eigenschaft wird nur beim ersten Öffnen eines Arbeitsbereichs mit dieser Ansicht von VS Code berücksichtigt. Danach wird die Sichtbarkeit auf die Wahl des Benutzers gesetzt. Wenn Sie einen Ansichtscontainer mit vielen Ansichten haben oder Ihre Ansicht nicht für jeden Benutzer Ihrer Erweiterung nützlich ist, sollten Sie die Ansicht auf collapsed oder hidden setzen. Eine hidden-Ansicht wird im Menü "Ansichten" des Ansichtscontainers angezeigt.

Views Menu

Ansichtsaktionen

Aktionen sind als Inline-Symbole für Ihre einzelnen Baum-Elemente, in den Kontextmenüs von Baum-Elementen und oben in Ihrer Ansicht im Ansichttitel verfügbar. Aktionen sind Befehle, die Sie so einstellen, dass sie an diesen Stellen angezeigt werden, indem Sie Beiträge zu Ihrer package.json hinzufügen.

Um zu diesen drei Stellen beizutragen, können Sie die folgenden Menübeitragspunkte in Ihrer package.json verwenden

  • view/title - Speicherort zum Anzeigen von Aktionen im Ansichttitel. Primäre oder Inline-Aktionen verwenden "group": "navigation" und der Rest sind sekundäre Aktionen, die sich im ...-Menü befinden.
  • view/item/context - Speicherort zum Anzeigen von Aktionen für das Baum-Element. Inline-Aktionen verwenden "group": "inline" und der Rest sind sekundäre Aktionen, die sich im ...-Menü befinden.

Sie können die Sichtbarkeit dieser Aktionen mithilfe einer when-Klausel steuern.

View Actions

Beispiele

"contributes": {
  "commands": [
    {
      "command": "nodeDependencies.refreshEntry",
      "title": "Refresh",
      "icon": {
        "light": "resources/light/refresh.svg",
        "dark": "resources/dark/refresh.svg"
      }
    },
    {
      "command": "nodeDependencies.addEntry",
      "title": "Add"
    },
    {
      "command": "nodeDependencies.editEntry",
      "title": "Edit",
      "icon": {
        "light": "resources/light/edit.svg",
        "dark": "resources/dark/edit.svg"
      }
    },
    {
      "command": "nodeDependencies.deleteEntry",
      "title": "Delete"
    }
  ],
  "menus": {
    "view/title": [
      {
        "command": "nodeDependencies.refreshEntry",
        "when": "view == nodeDependencies",
        "group": "navigation"
      },
      {
        "command": "nodeDependencies.addEntry",
        "when": "view == nodeDependencies"
      }
    ],
    "view/item/context": [
      {
        "command": "nodeDependencies.editEntry",
        "when": "view == nodeDependencies && viewItem == dependency",
        "group": "inline"
      },
      {
        "command": "nodeDependencies.deleteEntry",
        "when": "view == nodeDependencies && viewItem == dependency"
      }
    ]
  }
}

Standardmäßig werden Aktionen alphabetisch sortiert. Um eine andere Reihenfolge festzulegen, fügen Sie @ gefolgt von der gewünschten Reihenfolge zur Gruppe hinzu. Zum Beispiel führt navigation@3 dazu, dass die Aktion an dritter Stelle in der Gruppe navigation angezeigt wird.

Sie können Elemente im ...-Menü weiter trennen, indem Sie verschiedene Gruppen erstellen. Diese Gruppennamen sind beliebig und werden alphabetisch nach Gruppennamen sortiert.

Hinweis: Wenn Sie eine Aktion für bestimmte Baum-Elemente anzeigen möchten, können Sie dies tun, indem Sie den Kontext eines Baum-Elements mit TreeItem.contextValue definieren und den Kontextwert für den Schlüssel viewItem im when-Ausdruck angeben.

Beispiele

"contributes": {
  "menus": {
    "view/item/context": [
      {
        "command": "nodeDependencies.deleteEntry",
        "when": "view == nodeDependencies && viewItem == dependency"
      }
    ]
  }
}

Willkommensinhalte

Wenn Ihre Ansicht leer sein kann oder wenn Sie Willkommensinhalte zu einer leeren Ansicht einer anderen Erweiterung hinzufügen möchten, können Sie viewsWelcome-Inhalte beisteuern. Eine leere Ansicht ist eine Ansicht, die keine TreeView.message und keinen leeren Baum hat.

"contributes": {
  "viewsWelcome": [
    {
      "view": "nodeDependencies",
      "contents": "No node dependencies found [learn more](https://www.npmjs.com/).\n[Add Dependency](command:nodeDependencies.addEntry)"
    }
  ]
}

Welcome Content

Links werden in Willkommensinhalten unterstützt. Per Konvention ist ein Link, der allein auf einer Zeile steht, ein Button. Jeder Willkommensinhalt kann auch eine when-Klausel enthalten. Weitere Beispiele finden Sie in der integrierten Git-Erweiterung.

TreeDataProvider

Erweiterungsschreiber sollten programmatisch einen TreeDataProvider registrieren, um Daten in der Ansicht zu füllen.

vscode.window.registerTreeDataProvider('nodeDependencies', new DepNodeProvider());

Weitere Informationen finden Sie unter nodeDependencies.ts im tree-view-sample für die Implementierung.

TreeView

Wenn Sie programmgesteuert UI-Operationen auf der Ansicht durchführen möchten, können Sie window.createTreeView anstelle von window.registerTreeDataProvider verwenden. Dies gibt Zugriff auf die Ansicht, die Sie für Ansichtsoperationen verwenden können.

vscode.window.createTreeView('ftpExplorer', {
  treeDataProvider: new FtpTreeDataProvider()
});

Weitere Informationen finden Sie unter ftpExplorer.ts im tree-view-sample für die Implementierung.

© . This site is unofficial and not affiliated with Microsoft.