Using Document Libraries as Template Libraries

Download the source / wsp at CodePlex
Update June 1st: Version 1.5 released. The new version no longer requires a webpart, nor a lot of configuration, so I've updated the outlines seen in this post. See this new post for more info on the update.
Background
SharePoint document libraries are capable of handling many day-to-day tasks, right out of the box; there's no question about that. When you approach the need or wish for simple to maintain template libraries, that's an entirely different story.
A usual approach is to configure content types, and a set of hard-to-maintain URL links between these and actual documents in other locations. Administrative tasks, such as adding and removing templates, quickly becomes next to impossible, as you'll have to create new content types, and add /remove these manually for each document library you want the templates available in.
Another issue is the fact that the "New" menu for document libraries will show all content types at the root level. You can't categorize them in submenus, so large amounts of templates will be everything but a smooth ride for the end user.
Fixing things with a simple feature
Realizing that the aforementioned widespread pain is completely unnecessary, I set out yesterday to write a feature which can:
- Connect any document library to another document library, with one serving template documents to the other.
- Not require any administration of new templates, other than uploading them to the template library - Instantly making them available to all document libraries linked with the template library.
- Allow document libraries and template libraries to reside in different sites.
- Make the templates instantly, and hierarchically, available from the "New" menu in the document library.
.. And make it all available to all of you, complete with source code, pre-built solution/feature, instructions and documentation.
Installation and Usage
Download the latest source and install packages here.
- Unpack and run the install.bat file from the root folder. This will install the solution, and deploy it to all site collections. If you want more fine-grained control, feel free to install and deploy the .wsp-file on your own.
- Open a SharePoint portal with document libraries you want to template enable.
- Open the Site Settings, and navigate to the Site Feature page.

- Enable "Grep's SmartDocument Template Library Connector"

- Open a document library you want to expose templates in, and open it's settings.

- Navigate to the "Template Library Connector settings" entry, under "General Settings".

- Make sure you select "Yes" to enable template library connections, pick a document library to act as a template library, and save.

- Navigate back to the document library, and verify that the "New" menu is wired up properly.

- Adding new documents to the selected template library will instantly make new templates available from the "New" menu.
- You can optionally add a column called "Description" to the template document library, for additional text under each template, in the "New" menu view. If you wish to call this something other than "Description", the column name can be changed through the webpart settings shown above.
And that should be it. If you've got any questions or problems, feel free to drop me a note through the comments here.
Getting Technical
Writing a solution like this takes a few steps, and a bit of tinkering with undocumented SharePoint libraries. Here's a rough cut of what's covered in the source:
- Utilizing delegate controls to install handlers for all opened pages
- Find all ListViewWebParts on the webpart page, and retrieve entries from its toolbar.
- Adding items to ListViewWebPart's menus
- Adding submenus to the "New" menu
- Adding submenus to submenus
- Utilizing the default SharePoint document template JavaScripts to create new documents
- Retrieving hierarchies from SharePoint document libraries
- Writing and exposing list settings pages
A few of these steps, such as adding menus and submenus, are powered by extension libraries I've included in the source code. A simple thing like adding a submenu to a submenu isn't easily and readily available in the SharePoint object model, but with the extension libraries in the source project, it's ridiculously simple!
Code Pieces
I won't be covering everything here, but some key parts of the functionality, which I haven't seen elsewhere on the web, will be brought forward.
Extending the LiewViewWebPart's "New" menu
The ListViewWebPart has a toolbar, but this isn't immediately accessible from its object model. Why this is so is oblivious to me, as I see many possible benefits of extending the default views.
Ignoring the ListViewWebPart's attempt at hiding it, and the fact that even toolbar access functions are internal, I extended the System.Web.UI.Control class to give me the following edge:
1: public static T FindChildByType<T>(this Control self)
2: where T : class
3: {
4: var stack = new Stack(self.Controls);
5: while (stack.Count > 0)
6: {
7: var control = stack.Pop() as Control;
8: if (control is T)
9: {
10: return control as T;
11: }
12: foreach (Control child in control.Controls)
13: {
14: stack.Push(child);
15: }
16: }
17: return null;
18: }The approach is pretty straight forward: it will do a stack-based iteration of the control class, until a control of the target type is found.
Including this allows you to call a function such as FindChildByType
Once you get an instance of the NewMenu class (which derives from the superbly named ToolBarMenuButton class), you can call functions such as AddMenuItem and AddMenuItemSeparator (see MSDN). There's however no function to add submenus (or submenus to submenus, for that matter), so that will require another extension.
1: public static SubMenuTemplate AddSubMenuAt(this ToolBarMenuButton self, int index, string id, string displayName,
2: string imageUrl, string description)
3: {
4: SubMenuTemplate child = CreateSubMenu(id, displayName, imageUrl, description);
5: self.MenuTemplateControl.Controls.AddAt(index, child);
6: return child;
7: }The key part in the above code is the call to CreateSubMenu, which returns a SubMenuTemplate. The latter is a contruct from the Microsoft.SharePoint.WebControls namespace, which is used for several menus around the SharePoint UI, such as the Site Settings menu you get in MOSS when the "Office SharePoint Server Publishing" feature is enabled.
1: private static SubMenuTemplate CreateSubMenu(string id, string displayName,
2: string imageUrl, string description)
3: {
4: var child = new SubMenuTemplate();
5: child.ID = id;
6: child.Text = displayName;
7: child.Description = description;
8: if (string.IsNullOrEmpty(imageUrl))
9: {
10: imageUrl = "/_layouts/images/MenuNewItem.gif";
11: child.ImageUrl = imageUrl;
12: }
13: else
14: {
15: if (imageUrl.IndexOf("/") == -1)
16: {
17: imageUrl = "/_layouts/images/" + imageUrl;
18: }
19: child.ImageUrl = imageUrl;
20: }
21: return child;
22: }With these functions, along with a few more included in the source project, such as extending SubMenuTemplate to allow addition of nested submenus; adding menus and submenus is easy as pie.
Adding meaningful menu items
Getting to add menu items is one thing, but actually adding something meaningful is what obviously makes it useful. In this webpart, the goal was to make it possible to instantiate document (templates) from other document libraries, and that turns out to be surprisingly simple if you study how Microsoft does regular template instantiation. The javascript function called "createNewDocumentWithProgID" is the key here, and it accepts such parameters as source file url and target folder url. If the menu items are passed calls to this javascript in its click handler, with the correct urls, document instantiation is in the bag as well.
In Closing
So that's about it. Feel free to check the code, use the webpart, develop it further and share alike. For any questions or comments, use the comment feature on this blog.








