Download the Solution Example here: CustomAssetTree.dbsln

  • Solution Name: Tree Asset Custom Data
  • Software Version: v10
  • Keywords: Asset Tree. Unified Namespace.

Summary

This solution example demonstrates how to create an asset tree with personalized labels, icons and tags.


Technical Information

To customize asset trees with your own icons, you first need to add images to your solution. To do so, go to Displays → Images. You will be taken to a table containing all of your solution’s images. Click on “Import from a File“ and use the file browser to select the image you want. Once you are done, your Images table should look like this:

With the images in our solution file, we prepare the tags we want to display in the asset tree. These tags are stored in Table1 of the Historian Database. The tags' names are modified to follow a convention, and then they are added to a hash set, to track which tags are loaded into the tree.

DataTable table = await TK.ProjectDB.GetDataTableAsync("HistorianHistorianTags");
this.hashOfHistorian = new HashSet<string>();
 
foreach (DataRow row in table.Rows) {
    string tagName = TK.To<string>(row["TagName"]);
    
    // Remove ".Value" suffix if present
    if (tagName.EndsWith(".Value", StringComparison.CurrentCultureIgnoreCase)) {
        tagName = tagName.Remove(tagName.LastIndexOf('.'));
    }
    
    // Add "Tag." prefix if missing
    if (!tagName.StartsWith("Tag.", StringComparison.CurrentCultureIgnoreCase)) {
        tagName = "Tag." + tagName;
    }
    
    // Add tag to hash set
    this.hashOfHistorian.Add(tagName.ToLower());
}


To customize the asset tree, we first access the Display CodeBehind and get the asset tree’s control. Then, we apply the folder icon we imported into the solution (“Resource1“) to the tree root, and initialize the tree:

TAssetsTree control = this.CurrentDisplay.GetControl("asset") as TAssetsTree;

ImageSource iconRoot;
string rootName = "Historian Tags";

// Retrieves the folder image's ID from the solution's database using the image's name
int imageID = await TK.GetImageIDFromNameAsync("Resource1");
// Prepares to transfer the image as a stream of bytes
Stream stream = await TK.GetImageAsync(imageID) as Stream;
BitmapImage bitmapImage = new BitmapImage();
// Creates a bitmap image from the byte stream
// The #if #else macros ensure the procedure works fine on both WPF and HTML5
#if	HTML5_BROWSER
	bitmapImage.SetSource(stream);
#else
	bitmapImage.BeginInit();
	bitmapImage.StreamSource = stream;
	bitmapImage.EndInit();
#endif
iconRoot = bitmapImage;

// Creates the custom root of the asset tree
ElementItem tagRoot = new ElementItem(true, rootName, iconRoot, null, null);
control.InitializeCustom(new ElementItem[] {tagRoot}, this.GetObjectChildren);

GetObjectChildren is the method responsible for generating the tree structure. Initially, this method loads the images that will be applied to levels and tags, just like in the code snippet above. The rest of the code handles tree expansion when items are clicked. The code snippet below extracts an asset’s name and deals with clicks on level assets:

private async Task<ElementItem[]> GetObjectChildren(object sender, ElementItem item) {
	// List of elements to append to the tree
	List<ElementItem> elements = new List<ElementItem>();
	// Formats the string representing the selected item
	string asset = (item.FullDisplayString ?? "").Replace('\\', '.').Replace('|', '.').Replace(".[", "[");
	if(asset.StartsWith("Historian Tags/"))
	{
		asset = asset.Substring(15);
	}
	else asset = "Tag";
	// Creates a reference to the object represented by the selected item
	ObjRef objRef = TK.ObjServer.DB.GetObjRef(asset, false);
    if (objRef != null) {
		if (objRef.RunObj is ListObj) {
        // Handle list-based tags
        foreach (RunObj runObj in objRef.RunObj as ListObj) {
            string fullName = runObj.GetName().ToLower();
            if (this.hashOfHistorian.Contains(fullName)) {
				ElementItem elementItem;
				if(runObj is ITagObj)
					elementItem = new ElementItem(false, runObj.GetSimpleName(), iconTag, null, null);
                else
					elementItem = new ElementItem(true, runObj.GetSimpleName(), iconLevel, null, null);
                elements.Add(elementItem);
            }
        }
    }
}

Note that the GetObjectChildren method is longer than this. Please check the CodeBehind of this solution’s MainPage to see the full method, which includes code to interpret and display array tags.

Finally, to display the value of each tag, we open the asset tree’s settings and configure its Selected Asset field as follows:

Then, we configure the Label containing the tag’s name and value:


Reference Information

→ See Asset Tree for more information.

→ See Displays Images to learn more about images.


In this section:

  • No labels