r.a.d.treeview version |
5.4
|
.NET version |
1.0, 1.1 and 2.0
|
Visual Studio version |
N/A
|
programming language |
VB.NET & C#
|
browser support |
all browsers supported by r.a.d.treeview |
PROJECT DESCRIPTION A code snippet which you can paste into your TreeView binding logic if you use a lot of programmatically-generated Context Menus.
Consider the following scenario: You have a TreeView containing 100 nodes spread across 5 levels. Each node represents a file or folder on the server filesystem. You already have your own code to bind the TreeView, and each node also has a Context Menu created which represents the actions that the user has permission to perform. One file node to which the user has full access may have a complete Context Menu including 'Edit' and 'Rename', whilst another node may only have 'View' because of restricted permissions.
In this scenario, you are assigning an ID and Text values to the Context Menu items in order that you can ascertain which item has been clicked upon postback.
Due to differing nodes having the same permissions, the TreeView's HTML output will contain duplicate declarations of effectively the 'same' Context Menu.
Solution
It can be reasonably expected that a list of all the IDs that the Context Menu contains, in order, forms a unique reference that uniquely identifies the contents of that menu.
So, the proposal is to name your menus with this list of IDs. Each time you add a new Context Menu to the TreeView.ContextMenus collection, you first check that collection for an item with the same name and if it exists you don't add it.
For instance if your Context Menu items are:
ID=0, Text=Create New
ID=1, Text=Edit
ID=2, Text=Delete
ID=3, Text=View
Any menus that have al four items could be given the name:
0|1|2|3
...since the name is only used internally. A menu with just 'View' might have the name:
3
The following function will generate the name for you:
VB.NET Function GenerateMenuName(ByVal cmi As ContextMenu) As String
Dim nameBuilder As New System.Text.StringBuilder
For Each menuItem As ContextMenuItem In cmi.Items
nameBuilder.Append(menuItem.ID)
nameBuilder.Append("|")
Next
Return nameBuilder.ToString().TrimEnd("|"c)
End Function
The following function will check the collection for you and tell you if you should add it:
Function CheckMenuExists(ByVal c As ContextMenu, ByVal tv As RadTreeView) As Boolean
For Each cMenu As ContextMenu In tv.ContextMenus
If String.Compare(cMenu.Name, c.Name, True) = 0 Then
Return True
End If
Next
Return False
End Function
Finally, the following function will use the previous two and you can drop this into your existing binding logic in place of any calls to TreeView.ContextMenus.Add()
Sub AutoAddMenu(ByVal node As RadTreeNode, ByVal cm As ContextMenu)
Dim name As String = GenerateMenuName(cm)
If Not CheckMenuExists(cm, node.TreeViewParent) Then
node.TreeViewParent.ContextMenus.Add(cm)
End If
node.ContextMenuName = name
End Sub