It’s a fairly known technique to make use of CustomActions to add elements to the out-of-the-box user interface of SharePoint: you can add menu items to the Site Actions menu, you can add links on the Site Settings page, etc. The following piece of XML is the manifest of a feature that will add a new menu item to the Site Actions menu:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction
        Id="{B0B5A0CB-7FBE-4dd6-9B2A-2B1E1321B8F9}"
        Location="Microsoft.SharePoint.StandardMenu"
        GroupId="SiteActions"
        Title="Dummy Menu Item"> 
    <UrlAction
        Url="/_layouts/dummy.aspx"/>   
    </CustomAction>
</Elements>

For a more detailed description of CustomActions, I recommend following articles:

Another variation on this technique is to provide a reference to a class, instead of having fixed UI element specified in the XML. The following piece of XML points to the class ListSettingsMenu in the DemoCustomAction assembly.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction 
        Id="{42550415-FD08-4f1f-BAE6-93CCB2A2DE60}"
        Location="Microsoft.SharePoint.StandardMenu"
        GroupId="SiteActions"
        ControlAssembly="DemoCustomAction"
        ControlClass="DemoCustomAction.ListSettingsMenu">
    </CustomAction>
</Elements>

The cool thing is that you now can write code that will render the UI element; it’s even possible to create a hierarchical menu. The following implementation of the ListSettingsMenu class, in combination with the XML from above, is adding one extra menu item to the Site Actions menu (List Settings). This new menu item will contain a sub menu item for every list on the site, these sub menu items will point to the settings pages of the corresponding lists. The ListSettingsMenu class inherits from the WebControl class, by overriding the CreateChildControls method, you can instantiate SubMenuTemplate and MenuItemTemplate instances, and add them to the Controls collection. An instance of the SubMenuItemTemplate class corresponds with a menu item that contains sub menu items. These sub menu items are instances of the MenuItemTemplate class. By setting the Text, Description and ImageUrl properties of these classes, you can specify how the menu items will be rendered in the SharePoint UI. The ClientOnClickNavigateUrl of the MenuItemTemplate class specifies the URL for the menu item itself.

namespace DemoCustomAction
{
    public class ListSettingsMenu: System.Web.UI.WebControls.WebControl
    {
        protected override void CreateChildControls()
        {
            SubMenuTemplate listSettings = new SubMenuTemplate();
            listSettings.Text = "List Settings";
            listSettings.Description = "Manage settings for lists on this site";
            listSettings.ImageUrl = "/_layouts/images/lg_ICASCX.gif";

            foreach (SPList list in SPContext.Current.Web.Lists)
            {
                if (!list.Hidden)
                {
                    MenuItemTemplate listItem = new MenuItemTemplate();
                    listItem.Text = list.Title;
                    listItem.Description = string.Format(
                        "Manage settings for {0}", list.Title);
                    listItem.ImageUrl = list.ImageUrl;

                    string url = string.Format(
                        "{0}/_layouts/listedit.aspx?List={{{1}}}",
                        SPContext.Current.Web.Url, list.ID.ToString());
                    listItem.ClientOnClickNavigateUrl = url;

                    listSettings.Controls.Add(listItem);
                }
            }

            this.Controls.Add(listSettings);
        }
    }
}

To deploy all of this first of all the assembly (DLL) that contains the ListSettingsMenu should be built and copied either to the Global Assembly Cache or the BIN folder of the SharePoint site where you’d like to use it. Secondly the feature should be installed by copying the feature files and running STSADM -o installfeature -n featurename. Finally a SafeControl element must be added to the web.config, so the ListSettingsMenu control is marked as safe. If you forget the last step, you won’t get an error, but the extra menu item won’t be rendered. Here is a screenshot of the result:

The only caveat for this technique seems to be that you can’t use it to add a hierarchical menu in a EditControlBlock (ECB) CustomAction. The menu items of the ECB are rendered using Javascript. If you want to see a full blown example of what you can accomplish, check out the latest addition to the SmartTools project: the Enhanced Site Actions menu.

Juist a quick post so I won't forget this link: http://graegert.com/?p=505

Steve Graegert has written a great post on how you can work with the SPPropertyBag to store configuration settings. Of course that's very interesting, but in this post he also describes how you can build a custom Application Page that looks like it's an OOB Application Page. The trick is to know the SharePoint user controls that are responsible for building the UI, like InputFormSection and InputFormControl. Once again, check Steve's post for the full details!

I just uploaded a new release of the SmartTools for SharePoint to the CodePlex site. Currently the SmartTools project has two components:

Changes in this release:

  • What's New v1.1
    • Fixed issue with Link items
    • Added option to Excluded or Include a list of content types
  • Autocomplete Text Field v1.1
    • Fixed an issue if the field was used as a Site Column
    • Added configurable delimiter characters to allow multiple lookups
Technorati Tags: ,,,

A while ago I posted an article about how you could build custom Application Pages for SharePoint that display the breadcrumb navigation, just like all the out-of-the-box Application Pages do. The trick was to add add a siteMapNode element in the layouts.sitemap located in the _app_bin folder of the SharePoint site. It's no problem to do this manually; just open the file in Notepad/Visual Studio add the siteMapNode in the desired parent node (e.g. Site Settings) and you're done. But in a production environment (especially with multiple front end web servers in the farm) you don't want to do this manually! Of course this can be done from a Feature handler; open the layouts.sitemap XML file in an XMLDocument, add the siteMapNode element and save it again. It sounds easy, but it gets complex again when you have multiple front end web servers; the code to change the layouts.sitemap should be updated on all those servers. A solution for this problem is to create a job definition that executes a job on all the servers. An example of this approach can be found over here.

The scenario described above is still quite complex; but a reader of my blog discovered that SharePoint actually has a built-in mechanism which is much easier to implement! First of all you need to create a file with a name formatted like layouts.sitemap.*.xml (the * can be anything), e.g. layouts.sitemap.demoapppages.xml. This file should be copied to the C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS folder. In this file you can put siteMapNode elements that should be added to the layouts.sitemap file, for example:

<?xml version="1.0" encoding="utf-8"?>
<siteMap>
    <siteMapNode url="/_layouts/demopage.aspx"
    parentUrl="/_layouts/settings.aspx" title="Demo App Page"/>
</siteMap>

The parentUrl attribute determines where the siteMapNode will be added in the hierarchy of the original layouts.sitemap file (in this case beneath the Site Settings page). SharePoint will merge the contents of layouts.sitemap.demoapppages.xml when a new Web Application is created (thus the layouts.sitemap file is created in the _app_bin folder). To force the layouts.sitemap file to be recreated for the existing Web Applications as well, you can use the copyappbincontent operation of the STSADM tool:

STSADM -o copyappbincontent

Or you can use the ApplyApplicationContentToLocalServer method of the SPWebService class (typically in a Feature Receiver):

public class FeatureHandler : SPFeatureReceiver
{
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
       SPFarm.Local.Services.GetValue<SPWebService>().
                    ApplyApplicationContentToLocalServer();
    }

    public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {}

    public override void FeatureInstalled(SPFeatureReceiverProperties properties) {}

    public override void FeatureUninstalling(SPFeatureReceiverProperties properties) {}
}

I've created a small sample project on MSDN Code Gallery to show everything in action, that has the following components:

  • Custom Application Page (demopage.aspx), deployed to the _layouts folder
  • Custom SiteMap (layouts.sitemap.demoapppages.xml)
  • Feature, scoped to the web application level, that adds a link to the custom application page in the Site Settings page
  • Feature event handler to trigger the merging of all the sitemap files

So thanks Brian Staton for sharing your tip!

Mijn eerste verjaardag

Time flies when you're having fun; my little girl is already one year old. She's the reason why I don't have that much time to blog anymore as I used to have; and I love it. :-)

Yesterday I finally had some time to finish a project I've been working on for some time: the Autocomplete Text Field for SharePoint 2007. Click here for a small demo screencast on Soapbox, or download the high resolution video from the CodePlex site.

The idea is pretty simple: you've got a SharePoint list (or document library) that contains some interesting lookup data, now you can make use of the Autocomplete Text Field to display a textbox to the user that will show a dropdown list of items that start with the text the user already entered. When the user types more (or less) text, the dropdown list will adapt to that and update the contents. All of this is made available as a new column type (aka custom field type) in SharePoint 2007. The beauty of this field is that it doesn't need to do a page postback to refresh the data, the ASP.NET AJAX extensions are used to fetch the data in the background.

When the column is added to a SharePoint list or document library, the user can customize by defining various settings:

  • Column name: the name of the column
  • Description: the description of the column
  • Required: if the column should contain text or if it can stay empty
  • Lookup list: the list in which the column should do the lookup, this list can be selected from a dropdown
  • Autocomplete interval: the number of milliseconds after which the lookup list will appear
  • Items to display: the maximum number of items to display in the lookup list
  • Minimum prefix length: the minimum number of charactes which should be typed before the lookup list will appear
  • Show animations: enable or disable the fading effects when the lookup list is shown or hidden

For more information, the download and the source code; visit the SmartTools for SharePoint Codeplex site. Be aware that if you want to make use of this column, the ASP.NET AJAX extensions must be installed and configured on your SharePoint sites!! (more info here)

A long, long time ago, back in the SharePoint 2003 days, I created some pretty popular web parts which filled in some gaps the out-of-the-box functionality left open. In SharePoint 2007 most of those web parts are obsolete; for example the Breadcrumbs web part is not necessary anymore since SharePoint 2007 has breadcrumbs by default. But a lot of people contacted me to ask for a SharePoint 2007 version of the What's New web part. This web part displayed a list of new and changed items on site. It's arguable that this functionality is not needed anymore because in SharePoint 2007 we have RSS feeds, the Content Query Web Part (MOSS only) etc. But apparently some people like the simplicity of the original What's New web part so much ... and just for those people I've create a new SharePoint 2007 What's New web part! :-)

Of course the new version is better and improved! Internally it's making use of the SPSiteDataQuery class so it can also aggregate new and changed items from multiple sites (recursive from the current level, or the complete site collection). The web part has following configuration parameters:

  • Settings group
    • Number of items to show: determines the maximum number of items to show in the What's New web part.
    • Scope of the Query: determines where the What's New web part will check for new or changed items, possible values:
      • Site: the current site only
      • Recursive: the current site plus all the sub sites of the current site
      • Site Collection: the entire site collection of which the current site is a member
    • Cache interval: the number of seconds the results shown in the What's New web part will be cached. This cache is per user. After a change to the properties of the What's New web part, the cache is cleared automatically to reflect the changes.
    • Excluded Content Types: a list of content types which will be excluded from the results shown in the What's New web part. The list is separated with the ; character. For example "Folder;Task" will excluded all changes and additions of Folder and Task items.
    • Show header row: enables or disables the header row of the results list.
    • Group items on date: enables or disables grouping of the results based on their date
    • Allow group collapse: enables or disables the ability to collapse the groups if the Group items on date setting is enabled.
  • Columns to show: you can choose which columns you want to show in the results list
    • Modified: the Modified timestamp, including the date and time
    • Time: the modified time (excluding the date part)
    • Date: the modified date (excluding the time part)
    • List: a link to list or document library containing the item
    • Site: a link to the site of the list or document library containing the item
    • Modified By: the account who changed or added the item

The installation is very easy (and completely documented), there is a setup wizard that will guide you through the process (thank you WSPBuilder and SharePoint Solution Installer!). For more information, download and source code; visit the SmartTools for SharePoint CodePlex site.

[Cross posted from my photo blog] My dear friend and esteemed colleague Kevin DeRudder is hosting a photowalk in his home town: Gent (Belgium), next Saturday (22th of March). And of course everyone is invited: geeks, non-geeks, hobbyists, amateurs, professionals ... Kevin has created a nice outline of the day that starts at 2pm, you can find more details in the Photowalk Belgium group on Flickr (discussion here). The agenda is still open so feel free to comment and contribute. When you want to join, just drop a line in the Flickr group discussion (or on this blog if you don’t have a Flickr account). If you miss the 2pm start time: I'll do my best to post some updates on our location on my twitter account. If you want to join but don't know any of us, we'll be the geeky looking group with a higher-than-average-number-of-camera's-per-person. I'll bet Kevin will be wearing his famous "I'm blogging this" t-shirt:

I'm Blogging This

If you are wondering; Kevin does have a head. :-) I hope to see you all next Saturday in Gent!

The SPWebConfigModification class allows developers to write code that will make modifications to the web.config files of SharePoint sites. This is quite often necessary when you want to deply SharePoint customizations together with configuration settings. Using the SPWebModification class is not without any danger! :-) You can mess up your web.config files especially if you don't think about how you want to be able to undo your changes. Mark Wagner wrote an excellent article about the best practices related to the SPWebConfigModification class; required reading for every SharePoint developer. Mark explains some very important things you should know to get started:

  • To save the modifications, you must use of the following code:
    myWebApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
    myWebApp.Update();
  • Only call this code once in your feature handler, otherwise you get the error "A web configuration modification operation is already running."

Great info Mark, and please do create an complete example of the best practices, packaged in a feature!

Did you ever want to integrated Silverlight with SharePoint? Check out the brand new Silverlight Blueprint for SharePoint site: http://www.ssblueprints.net/sharepoint/ !

At U2U we've created the six samples of the Blueprint that illustrate the integration options. You can read more details on Patrick's blog and Karine's blog (she posted some screenshots). The Blueprint will also be announced by Bill Gates during the SharePoint Conference keynote later today, the SharePoint team blogged about the other announcements as well (SharePoint Online and Microsoft Search Server 2008 Epxress).

On a personal note I would like to congratulate Karine, she has worked very hard to get everything done on time. Karine, you can be proud of this one!

More Posts Next page »