On a recent project I had a need to relate one list to another. The first list was a document library which stored project specs and the second was a list that contained user provided scores that were used to rank the projects. One simple requirement I had was to be able to provide a link to enter a score for a given project and have the lookup field corresponding to the project preset with the value of the field passed in. I also had to hide certain fields from from the input form based on certain business rules.
To accomplish these goals I created a custom content type which contained my fields necessary for tracking the scores. The individual fields are not important but note the values of the FormTemplates’ elements:
By specifying a custom value for the "Edit" and "New" elements I was able to use a custom delegate control. To create the custom delegate control I copied the RenderingTemplate control with the ID of ListForm from the 12\Template\ControlTemplates\DefaultTemplates.ascx file and put it into a new file. I then modified it to use a custom ListFieldIterator that I created. The following is the delegate control:
The following is the custom list field iterator that I built (minus the business logic):
Once I had the input forms customized and deployed I then wanted to be able to modify a view to include a link directly to the form with the project ID preset. Note the status bar:
I could have done this several different ways including adding a hidden field with a custom display pattern that can then be added to the view (this would be the better way to go if the same link is needed in multiple places and you want to be able to deploy it easily via a Feature) but because I was looking for a real simple solution and didn’t need reuse of the field I decided to simply modify the CAML of the view (though I may end up changing this later to be a new field). To do this I used SPCAMLEditor (available on CodePlex) to simply change the ViewBody element to the following:
The main point of interest is the last FieldSwitch element which looks for a field named LinkFilenameNoMenu (which is the internal field name for the Project field that I’m using) and then adds some additional HTML if a match is found. In this case I’m using the HttpVDir element and the ID element to construct a simple link tag to the NewForm.aspx file for the scores list (I know, I should be using CSS for the styling). The result is that I can now click straight to the project scores list while looking at the project documents list and have the project I’m interesting in scoring automatically selected.
If I end up changing this to use a hidden field I’ll post the CAML for that in an update.
Update 6/18/2008: Well that didn’t take me long to change my mind – I decided to go ahead and add a list field that contains the link rather than modify the view so I pulled the code that I had in the ViewBody element above and added a new field, LinkFilenameAndScore to the ViewFields element. The LinkFilenameAndScore field is defined as follows:
I then used the following line of code to add the field to the list (where fieldSchema is a local variable containing the above XML and list is an SPList object representing the documents list):
list.Fields.AddFieldAsXml(fieldSchema, false, SPAddFieldOptions.AddToNoContentType | SPAddFieldOptions.AddFieldInternalNameHint);
Note the SPAddFieldOptions.AddFieldInternalNameHint enum value that is passed in – this tells SharePoint to use the value of the Name attribute as the internal name. If you omit this it will use the display name (this took me longer than I’d like to admit to figure out).
One I had this field as part of the list I simply had to add the field to the view and I was done except that now the end-user can easily create a new view that contains this same link.