问题
I'm writing a VS Code extension that implements a custom viewsContainer. It is activated in an onView:
event specified in the package JSON.
This all works great, and my view pulls in data from a static JSON file and does add each node to the view.
My JSON is strucutured like this:
{
"name": "root",
"children": {
"Child1": [
{ "id": "childId1", "name": "childName1" },
{ "id": "childId2", "name": "childId2" }
],
"Child2": [
{ "id": "childId1", "name": "childName1" },
{ "id": "childId2", "name": "childId2" }
],
"Child3": [
{ "id": "childId1", "name": "childName1" },
{ "id": "childId2", "name": "childId2" }
],
"Child4": [
{ "id": "childId1", "name": "childName1" },
{ "id": "childId2", "name": "childId2" }
]
}
}
and my class that is registered as a treeviewprovider in extension.ts
is:
import * as vscode from "vscode";
import * as validateMenuItems from "./validateMenuItems.json";
export class ValidateMenuProvider
implements vscode.TreeDataProvider<ValidateMenu> {
private _onDidChangeTreeData: vscode.EventEmitter<
ValidateMenu | undefined
> = new vscode.EventEmitter<ValidateMenu | undefined>();
readonly onDidChangeTreeData: vscode.Event<ValidateMenu | undefined> = this
._onDidChangeTreeData.event;
constructor() {}
refresh(): void {
this._onDidChangeTreeData.fire();
}
getTreeItem(element: ValidateMenu): vscode.TreeItem {
if(element) {
console.log(`element: ${element}`);
return element;
}
return element;
}
getChildren(element?: ValidateMenu): Thenable<ValidateMenu[]> {
if (element) {
return Promise.resolve([]);
} else {
return Promise.resolve(this.getValidateMenu());
}
}
private getValidateMenu(): ValidateMenu[] {
const toMenu = (
menuTitle: string,
collapsibleState: vscode.TreeItemCollapsibleState
): ValidateMenu => {
return new ValidateMenu(menuTitle, collapsibleState);
};
let menuItems: any = [];
let menuHeadings: any = validateMenuItems.children;
let j: number = 0;
for (var i in menuHeadings) {
// send the parent as a menu item
if (menuHeadings[i] !== null && typeof menuHeadings[i] === "object") {
let firstChildLabel: string = Object.keys(validateMenuItems.children)[
j
];
let parentMenuItem = toMenu(
firstChildLabel,
vscode.TreeItemCollapsibleState.Collapsed
);
menuItems.push(parentMenuItem);
// send each child object to the view
for (var k = 0; k < menuHeadings[i].length; k++) {
if (
menuHeadings[i][k] !== null &&
typeof menuHeadings[i][k] === "object"
) {
let secondChildLabel: string = menuHeadings[i][k].name;
let childMenuItem = toMenu(
secondChildLabel,
vscode.TreeItemCollapsibleState.None
);
menuItems.push(childMenuItem);
} else {
return [];
}
}
} else {
return [];
}
j++;
}
return menuItems;
}
}
export class ValidateMenu extends vscode.TreeItem {
constructor(
public readonly label: string,
public readonly collapsibleState: vscode.TreeItemCollapsibleState,
public readonly command?: vscode.Command
) {
super(label, collapsibleState);
}
}
What this does is put every item in the JSON into the view, the first set of object under root.children
as collapsed items, and their respective children as non-expandable/collapsible.
However, for each of the expandable items, if I click to expand it, the entire rest of the JSON schema is repeated underneath it.
From stepping through and watching the call stack frames it appears that the requried getChildren()
method is first initially called when the provider is registered, and at each expand event.
My question is - since getChildren()
requires a <Thenable>
, where am I going wrong with my implementation with getValidateMenu()
that will avoid duplicating the schema on the collapsed objects, and actually group it's child objects within the collapsed item?
Do the immediate root.children
items need to have a command that calls some kind of onclick
sort of method, that gets this
and reveals its children?
Any pointers from those more familiar greatly appreciated.
回答1:
You're not implementing getChildren() correctly. It's documented like this:
Get the children of
element
or root if no element is passed.
What your implementation seems to do instead is "return a flat list of all tree items when no element
is passed, and an empty list otherwise".
You need to actually return the children of the requested element
(and only the immediate children, instead of returning the whole tree at once for the root element).
The official Tree View Sample might be worth checking out.
回答2:
Even I struggled with this for quite a while, found the github repo shared by the OP in another question. I think it's worthwhile mentioning it here so that others are benefited.
https://github.com/trebleCode/dxdevcheck/blob/master/src/validateMenu.ts
The key for me was to add children
field to my TreeItem
subclass as mentioned by @Gama11 in the comments.
来源:https://stackoverflow.com/questions/55418551/duplicate-treeview-schema-is-vs-code-extension