/>
Fields>
PropertySchema>
As the comment indicates, the property schema section is where we define our field type has an additional hidden field used for holding our properties. This “PropertySchema” was meant to allow you to define multiple property fields (one per property), but there is a bug that prevents this from working. Hence, we store one property, which in actuality is a delimited string of all our properties.
2 - UI and Logic for adding your Field to a List
This basically refers to presenting a screen to allow a user to set or change the properties that your custom field uses, and storing these property settings. So it deals with our “DelimitedPropertyValues” property above.
My Tree control is going to have 10 properties:
1. Site (string) - the name of the site holding the list of data that defines this tree.
2. ListName (string) - the name of this list holding the tree data.
3. Levels (int) - the number of levels this tree has. user will select list via a dropdown.
4. SortByAlpha (bool) - whether the nodes in this list will be sorted alphabetically, or be displayed the way they occur in the list.
5. ShowSetNull (bool) - if a “Set this value to be null” link should be displayed beneath the tree.
6. ShowCheckboxes (bool) - if this tree should render checkboxes on nodes as defined in the list holding the tree data.
7. CheckBoxDisplay (string) - a string indicating if the checkboxes should be displayed on “All Nodes”, “Leaf nodes” or “List Defined” nodes. User will select which one via a dropdown.
8. AutoCheckSubnodes (bool) - if a node containing subnodes is checked, should they all be automatically checked also.
9. ExpandCheckedNodes (bool) - if the tree should load in an expanded state, showing all nodes that have been checked.
10. ShowHoverText (bool) - indicates if the tree control should show the hover text as defined in the list holding the Tree data.
So, the first thing I need to do is to create a control that allows the user to set all of these properties when they use my custom field.
In my fileset, the control is the TreeListEditField.ASCX file, and it gets deployed to …\12\TEMPLATE\CONTROLTEMPLATES.
The majority of this control is fairly straight forward, simple ASP.Net controls like Labels and TextBoxes to gather my property values, but you may not be familiar with the controls that enclose these, ie:
wssuc:InputFormSection runat="server" id="MySections" Title="Tree List Details">
Template_InputFormControls>
wssuc:InputFormControl runat="server">
Template_Control>
The “InputFormSection” control & “InputFormControl” are SharePoint controls that creates the standard look and feel that SharePoint forms have. So, with those encasing my control (made up of labels, textboxes, dropdowns etc), I end up with something like this:

(click to see an image that is not squashed down)
Great, so now I need to put together the code that is going to be associated with this control. All this code really needs to do is to create the correct DelimitedPropertyString for the values set by the user in the control. So (for example) if they have checked a checkbox, put a “True;” in the delimited string.
I have a little logic around the “Load Lists” functionality - I want the user to enter a url to a SharePoint site containing the list holding the tree data, to then click a button to load the lists on this site into a dropdown, and finally to select which specific list holds the tree data. I ensure that the path to the site is a relative url by removing the root url for the current web application if it exists in the given site url.
The OnSaveChange method is used to create a delimited string for all the properties, and then set this string against the controls “DelimitedPropertyValues” property.
So that we set these controls to have the correct values when someone is editing an existing TreeList column, the InitializeWithField method must parse the “DelimitedPropertyValues” string and set the state of the controls to be correct as per the values contained in that string.
3 - UI and Logic for your Field when an item in that list is being edited
This is very similar to the previous section, except we are now defining how the column will look and behave when that list item is being edited - that is, that it will display the tree as defined by our list.
As with the TreeListEditField control, this is an ascx file that gets stored on the filesystem at …\12\TEMPLATE\CONTROLTEMPLATES. In the attached solution, this control is called TreeListFieldControl.ascx.
It is made up of three parts - the tree control, a link that can be used to set the string value set by tree control to null, and a label that can be used to show the current string value. These controls are contained by a “RenderingTemplate” control, which allows us to create our control from these three parts.
SharePoint:RenderingTemplate ID="TreeList" runat="server">
Template>
asp:TreeView runat="server" ID="treeList" />
br />br />
asp:LinkButton ID="setNullLink" runat="server" Text="Set this value to be null">asp:LinkButton>
br />br />
asp:Label ID="valueLabel" runat="server">asp:Label>
Template>
SharePoint:RenderingTemplate>
Ok, so like before, we now need to implement the code that is going to be associated with this control. This code has quite a bit to do - it must get the properties that have been set against the control, then build the tree control from the designated list, and configure it based on the properties.
I am not going to describe how the code does this in depth, as it is well commented in the cs file, and hopefully is easy to understand, however I want to point out that I use a viewstate variable (“drawnTree”) to determine whether to run the tree creation code, rather then the usual “if !Page.IsPostBack”.
This is because we use this control on created web pages (in the “PublishingControls:EditModePanel”), which means a page could be considered a postback (say, after web parts have been added) and the tree control not drawn.
And that’s it. Install the solution to your farm (you can use the ~InstallSolution.bat included to help with this), deploy it to your web application (best to do this through central admin), and then it should be available for use in your lists and site columns.
Some things to note:
• The code currently assumes all users will have read access to the list containing the tree control data, if this is not true, you will need to implement some impersonation in the code around where it parses this list and builds the tree
• Because the checked tree nodes are stored as a string showing the TreeNode path, the ‘/’ character cannot be used in any of the tree node names
• I have taken out all of my logging and tracing calls, as these rely on other in-house code libraries. If you want to use this code in a prod system, I suggest you add your own in there
• I have taken out the custom styling classes (css) from the ascx’s, you may want to consider adding in your own
• Although this control works as is, this is really meant as a starting point for you to implement the control you need - an XML file might be a better source for your tree data, you might not like the strict design for the tree data list this control requires, you might want additional tree functionality, etc.
The Visual Studio 2008 solution is in the "TreeListControl.zip" attached to this post - contains compiled WSP file, so can be installed and used directly on SharePoint install.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
After recieving a number of comments on this tree control, I feel I should point out that, as only the text of the tree node is stored against a list item, changing the value of the tree node by updating list item value that sources the tree nodes will not cause the value to be automatically updated on all the list items it is applied against.
It would be a simple change to make the Tree control store a list item guid rather then the node path string, which would then make this possible.
The company I wrote this for uses an external search provider (not microsoft), and it was easier for them to process a bunch of node paths to provide their search filters, rather then to process a bunch of id's, and perform a lookup back to a sharepoint list, hence this design was used.
To resolve this problem for the company mentioned, we created a web part which allows the user to update the values assigned to list items. So when they want to change a tree node item, they delete the item in the list, create a new one, then use this web part to change the original items node path to the new items node path - not really an ideal solution, but seems to work well enough.