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.

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:nodeDependenciesexplizit inactivationEventsauflisten.
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 Seitenleistedebug: Ausführen und Debuggen-Ansicht in der Seitenleistescm: Quellcodeverwaltung-Ansicht in der Seitenleistetest: 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 gegebeneelementoder 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 SiecreateTreeView, wenn Sie dieTreeViewAPI benötigen.vscode.window.createTreeView('nodeDependencies', { treeDataProvider: new NodeDependenciesProvider(rootPath) });
Hier ist die Erweiterung in Aktion

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.jsonregistrieren, 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.

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.

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.

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)"
}
]
}

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.