I've just uploaded a new extensions to the SmartTools for SharePoint project on CodePlex. This extension adds Copy and Paste functionality to SharePoint Document Libraries. You can download the extension from the Releases section. For more info and screenshots see the CopyPaste Wiki page on CodePlex.

Weblogs are a great way to keep up with the latest SharePoint Buzz and I get quite a lot of questions from people who are just dipping their toes in the SharePoint pool for some good reading material. Well if you don't want to go after every interesting SharePoint blog individually or if you want to add blogs to your list that you didn't know yet, check out following links:

If you really want to read every bit related to SharePoint, you can use following sites (quality of the content is not guaranteed!):

Technorati Tags: ,,,,

My colleague Karine has released a new version of her Caml Query Builder Tool! Version 3.1.0.0 has some great new features:

  • Query fields by ID
  • GetListItemChanges (method of the Lists.asmx web service)
  • GetListItemChangesSinceToken (method of the Lists.asmx web service)
  • extra options of the QueryOptions part
  • support for data type ModStat
Download here and check her blog post for the full details.

Pfew, the DevDays 2008 in Amsterdam, The Netherlands are over! I think both of my sessions (Getting your SharePoint Code Deployed & Advanced Web Part Development) went pretty well; no crashes or failing demos. Let's hope the audience thinks the same. :-) I already got quite some requests to get my presentations and demo code. So instead of sending a copy to everybody's email, I've uploaded them to my SkyDrive account.

If you have any questions, comments and/or feedback; feel free to post them as a comment on this blog and I'll try to do my best to answer them. :-)

For the third year in a row I'll be speaking at the Dutch Developer Days in Amsterdam. The event starts tomorrow and I've got two sessions on Friday (Getting your SharePoint Code Deployed and Advanced Web Part Development). Speaking in Amsterdam is always lots of fun, so I hope to meet you there!

By the way, if you can't make it to the event, you can watch a life screen of the keynote.

Micromiel is organizing a cool photo event in Amsterdam this weekend, I whish I could attend it!

This Saturday (the 24th of May), I’m organizing an event for amateur-photographers in downtown Amsterdam. The day starts around 12 noon with a welcome and introduction at ‘De Rode Hoed‘, a pretty classy venue naar the waterside. Around 40 photographers will be divided into 4 groups of 10, and will then board a ship that will be docked right outside the building. Right then, the challenge starts. Every group will take pictures over the course of 2 kilometers, so that in total we’ll span an 8 kilometer route from the boat. All the pictures will be collected and then stitched together using Windows Live Photo Gallery to form the world’s largest panoramic picture. The end result will be put into a DeepZoom viewer so it’ll become scrollable and zoomable and it will be sent to the Guiness Book of World Records. Full post here

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!

More Posts Next page »