Workaround for several nodes with the same ID in the editor’s tree
Have you ever tried to display the same node in the several places simultaneously in the editor tree?
For example, returning a same child PageReference for different parents will result in it. I believe you faced with it during debugging your own page provider.
If not, first I’ll show you
How it NOT works
First of all, believe me that Structure tab and Favorites tab uses the same tree control. They really do. Ok, you can use reflector and check it.
Create simple hierarchy like this one:
Right-click on each of the nodes and select “Add to favorites”. You should see the following in the Favorites tab:
Expand the first level nodes, and you will see two instances of the same node in the tree:
But EPiServer isn’t ready for such cases. There’s no tooltip for second Child2 node. Click on the second Child2 node – selected is first Child2. Try to expand second Child1 node:
Nothing happens! Ok, try to “collapse” it and expand it again:
And you can see the whole new tree under the second Child1 node!
Why is the world so cruel?
If not digging too deep, the idea is simple: they use the PageReference to generate ID of a node control, so from two identical nodes they got two identical HTML controls with the same ID… Which breaks their JS.
My first idea was to generate random IDs for all the nodes; for example, use Guid.NewGuid(). I’ve tried it. Now I know. The tree uses node ID to retrieve node PageReference. Yes, a node has PageReference among other properties on the client. BUT a tree prefer to use node ID.
Ok, I couldn’t sleep for weeks and found an Idea – all I need is something that is parsed into the same PageRefernces, but differs in string representation. I tried a number of ideas here, but most simple is just adding leading zero to a string representation of a PageReference. For the integer it doesn’t change its numerical meaning, so PageReferences like “1” and “01” are the same, but these ARE different client IDs for controls! This will also work for complex references, like 1__RemoteSite. Exactly what I need.
So, basically all I need is to append zeroes to IDs of the “duplicated” nodes, which are already shown in the tree under some other paths. Bad thing here is that there’s no (easy?) way to understand what nodes are already shown to the particular visitor, so I need to create some cache on the server side.
It is easy: create & register adapter for tree, subscribe for ItemDataBound of TreeControl, and change DataPath in a smart way.
Control adapter registration (file <Web project>\App_Browsers\AdapterMappings.browser):