20 tháng 5, 2010

Use Feature to create custom list definition with custom fields and views

Recently I worked a SharePoint project and the client wanted to create some lists with their fields. On a list, they wanted to see items grouped by a particular one of their field. Obviously that the client needed custom list definition with fields and views. At first I thought this project would be not hard but it turned out that there are tricks that I need to know about creating custom list definition. So I'd like to note down those tips here to help out others who may be in trouble like me.

Assume that you looked at How to create custom list definition on MSDN.

1. Custom content type
There is a important note that people usually miss (me too :-) . Let say you create content type ABC which inherits from SharePoint standard Item content type (0x01), you must do two things in your content type definition and list definition
  • In content type ABC definition, remember to include fields which belong to the parent content type (Item) whereas adding custom fields for content type ABC
ContentTypeADefinition.xml

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<ContentType ID="0x01008B7EF87D021E44fbBD83C21212A0B047"
Name="ABC ContentType"
Description="Custom ABC ContentType inherits from Item" >
<FieldRefs>
<!-- IMPORTANT: Remember to include fields that parent content type (Item for this case) uses -->
<Field ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" /> <!-- Title column is required by Item content type so here we include it in definition of ABC content type -->

<!-- Add custom fields here -->
<FieldRef ID="{7FD2A507-E6CB-4516-8C9A-C73E3C747524}" />
</FieldRefs>
</ContentType>
</Elements>
  • Do the same for list definition: include fields required by parent content type
schema.xml

<List xmlns:ows="Microsoft SharePoint" Title="Custom list"
Id="bc53ee2c-46b3-41ea-8deb-e75013c92eed" FolderCreation="FALSE"
Direction="$Resources:Direction;" BaseType="0">
<MetaData>
<Fields>
<!-- IMPORTANT: Add fields required by parent content type (Item) -->
<Field Name="Title" ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" DisplayName="$Resources:core,Last_Name;" Sealed="TRUE" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="Title"><!-- _locID@DisplayName="camlid1" _locComment=" " -->
</Field>

<!-- Add custom fields here -->
<Field ID="{7FD2A507-E6CB-4516-8C9A-C73E3C747524}" DisplayName="Item Name"
Name="ItemName" Type="Text" Group="Custom Columns" Required="TRUE"
SourceID="http://schemas.microsoft.com/sharepoint/v3" />
</Fields>

<!-- Other stuffs -->

</Metadata></List>

You can use SharePoint Manager to browse the SharePoint content types and its fields for getting field info easier.


2. Custom view
In order to define custom view, you probably need to know CAML and View schema . But there is another easier way to make it by making use of SharePoint Manager .
First, you create a custom view on desired list on SharePoint UI.



Second, after the view is created, you use SharePoint Manager to get the view definition by copy value of property HtmlSchemaXml in SharePoint Manager to schema.xml to make a new custom view. And there is one more important step





On the <View> element, make sure that those attributes are inserted

<View BaseViewID="2" Type="HTML" WebPartZoneID="Main" DisplayName="Custom view" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/events.png" Url="CustomView.aspx" >

  • BaseViewID : this is an integer, make the attribute value uniquely with other View in schema.xml
  • WebPartZoneID="Main"
  • SetupPath : should be pages\viewpage.aspx so that the viewpage.aspx (this page is available in \\12\TEMPLATE\Pages\) is called when user uses your view

3. Use standard SharePoint forms in custom list

Normally, a custom list definition template created by WSS 3.0 Tools for Visual Studio usually has several files such as NewForm.aspx, DispForm.aspx, AllItems.aspx , ... And all those files are totally same as standard form in SharePoint. So if you don't have any plan to customize them, you can remove them from definition and tell SharePoint to use its standard form instead. The tip here is to add SetupPath attribute on <Form> element. Look at below xml fragment in schema.xml

schema.xml

<Forms>

<!-- I have a customized Display Form so that I keep the file DispForm.aspx in definition and SharePoint will called my customized DispForm.aspx when it renders Display Form -->
<Form Type="DisplayForm" Url="DispForm.aspx" WebPartZoneID="Main" />

<!-- For other forms, I don't change any on them so I use SetupPath attribute to tell SharePoint that calls its standard forms instead -->
<Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
<Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
</Forms>

4. Use Lookup field on list instance
You're creating two list definition called AL and BL. In AL you have a lookup field that references to Title field in BL. But the problem is that both AL and BL are custom lists and doesn't exist in site. It means you don't have List ID of BL required for lookup field.

SharePoint support another way to solve this problem by allowing user to put an relative URL on lookup field. How nice it is :-). On our AL and BL, the trick is to provide the correct URL of BL instance in lookup field definition in AL. And the safe way to ensure the correctness of URL is that you use <ListInstance> to create a new list instead of letting user do.

ListInstances.xml

<ListInstance Id="InstanceOfBL" Title="BL List" TemplateType="10010" Url="Lists/BLInstance01">

You can see that I instruct SharePoint to create a new instance of BL template with Lists/BLInstance01 URL. So I will provide this value into lookup list definition in AL and that solves our problem

schema.xml in AL

<Field Type="Lookup" DisplayName="Lookup Field 1" Required="FALSE" List="Lists/BLInstance01" ShowField="Title"
EnableLookup="TRUE" UnlimitedLengthInDocumentLibrary="FALSE" ID="{7FD2A507-E6CB-4516-8C9A-C73E3C747523}"
SourceID="http://schemas.microsoft.com/sharepoint/v3" Name="LookupField1" />


The List attribute is supposed to have a GUID but here we use relative URL (because the list instance haven't existed yet) and SharePoint accepts the url too.

Read more here

5. Create custom List Template as document library

If you're creating a document library as list template. Remember adding two attributes in the definition. Look at below xml fragment

<ListTemplate
Name="CustomDocLib"
DisplayName="Custom Document Library"
BaseType="1"
Type="101"
OnQuickLaunch="TRUE"
SecurityBits="11"
Sequence="1004"
DocumentTemplate="101" />

  • BaseType="1" : this attribute announces SharePoint that you're creating a document library, not a list. BaseType="1" means document library, BaseType="0" means list
  • DocumentTemplate="101" : this attribute makes the New Item menu item appear in New menu in toolbar. If you don't include this, you won't see New Item :-)
6. How to get the SharePoint item (SPItem) that is associated with the webpart editor in NewForm.aspx , EditForm.aspx and DispForm.aspx ?

There is sometime you need to customize editor forms so that you want to retrieve the SPItem which is processed within the form (i.e. to support for your business). E.x: every time user creates new item, you want to update the lookup field in other list that refers to newly created SPItem.

So in this case, we need a customized NewForm.aspx. Create NewForm.aspx (via Windows SharePoint Services 3.0 Tool) for the list definition. Then replace the code behind of NewForm.aspx with yours (it's created soon)

<%@ Page language="C#" MasterPageFile="~masterurl/default.master"
Inherits="MyAssembly.Features.NewCustomForm" %>


Then create new class called NewCustomForm that inherits from Microsoft.SharePoint.WebParPages.WebPartPage class

namespace MyAssembly.Features
{
public class NewCustomForm : WebPartPage
{
// This is the web part declared by default in NewForm.aspx
protected global::Microsoft.SharePoint.WebPartPages.WebPartZone Main;
}
}
}
}


Now we have a customized NewForm.aspx, before go on. Let I show you how we can retrieve the SPItem in editor first. Here the snipet code to get the SP item go with this web part and this code is going to put on our NewCustomForm class.

// By default, this page only has one webpart
// If user has customized it, we stop
if (this.Main.WebParts.Count == 1)
{
var webpartForm = this.Main.WebParts[0] as ListFormWebPart;
if (webpartForm != null)
{
var listItem = webpartForm.ItemContext.Item; // Got the SPItem going with the webpart editor
// do any thing here
// ...
}
}

You can put above code in Page_Load for example to get the item fields, or in Page_Unload to get newly created item (Note, because when a new item is saved, the page is redirected to Source param and it doesn't fire next events such as PreRender, Render so we have to use Unload event, another way is to override Dispose() method)

In short, by using ListFormWebPart.ItemContext.Item property, we can get the associated SPItem within editor and this property is very helpful in many scenarios.


Other tips

4 nhận xét:

  1. Hello Duy Lam
    apparently it's required to remove the "Name" Guid attribute from the original list definition. Do you confirm this?

    Trả lờiXóa
  2. Hi Half,

    You may notice that I posted my experience at 2010 (two years ago) and now I'm sorry that I can't verify this issue since I haven't worked on SharePoint for a long time

    Trả lờiXóa
  3. Hi Duy,

    I created a feature for a custom list definition with a custom view and deployed it. On the site, I created a new library based on the custom list definition. It was okay with the custom view. But when I try to modify the default view or create a new view via the browser, I get an error.

    Is this the behavior of custom list definitions? Users can no longer create new views or modify the views? Or the feature was created incorrectly?

    Thanks,

    Newbie

    Trả lờiXóa
  4. Hi uni santiago,

    I'm sorry that I can't support your issue since I no longer worked on SharePoint in a long time . You may seek for help in SharePoint portal in MSDN forum

    Duy

    Trả lờiXóa