Referencing and Linking: Using Custom Fields to Display Relationships in SharePoint Server 2007

Summary:  Learn how to use a field control to extend a custom Relationship field in Microsoft Office SharePoint Server 2007 to retrieve and display document relationships from a secondary list.

Office Visual How To

Applies to:  2007 Microsoft Office System, Microsoft Office SharePoint Server 2007

Microsoft Corporation

March 2008

Overview

This Microsoft Office Visual How To demonstrates how you can extend a custom Relationship field in Microsoft Office SharePoint Server 2007 to retrieve and display document relationships from a secondary list by using a field control.

For information about how to create the custom Relationship field and the secondary list for defining and storing document relationships, see the following Office Visual How Tos:

Code It

When the control is in display mode, the relationship information is retrieved from the Relationship Lookup list, formatted, and displayed in the control. Retrieval and display of the relationship information is done in the Render method.

The first step is to retrieve the relationship information for this document from the Relationship Lookup list. The Relationship Lookup list stores the GUIDs for each document in the item 1 and item 2 fields. A query is used to retrieve all items in a list item collection from the Relationship Lookup list where the value in item 1 or item 2 equals the GUID of the current document.

The next step is to obtain the related document and list GUIDs from the list item collection. A check is made to see whether the value for item 1 or item 2 equals the GUID for the current document. If it matches, the other item contains the GUID that represents the related document.

The final step is to obtain the display information for the related document and output it in the control. In this example, you display the document name and relationship type as a hyperlink to the related document display page.

  protected override void Render(HtmlTextWriter output)
    {

      // If this is edit mode and has a value then set the picker.
      if (base.ControlMode.Equals(SPControlMode.Edit) 
        && this.ListItemFieldValue != null)
      {
         this.urlSelector.AssetUrl = this.ListItemFieldValue.ToString();
      }
      else if (base.ControlMode.Equals(SPControlMode.Display))
      {

         // Get all corresponding relationships.
         SPList list = this.Web.Lists["Relationship Lookup"];
         SPQuery query = new SPQuery();
         string queryFormat = "<Where><Or><Eq><FieldRef 
         Name='item_x0020_1'/><Value 
           Type='Text'>{0}</Value></Eq><Eq><FieldRef 
         Name='item_x0020_2'/><Value 
           Type='Text'>{0}</Value></Eq></Or></Where>";
         query.Query = string.Format(queryFormat, 
         this.ListItem.UniqueId.ToString());
         SPListItemCollection listItems 
           = list.GetItems(query);

         output.WriteLine("Related Documents:");

         foreach (SPListItem item in listItems)
         {
            string relatedItemUniqueId = string.Empty;
            string relatedListId = string.Empty;
            string relationship = string.Empty;

            // Get the related list and item IDs.
            if (item["item_x0020_1"].ToString().Equals(this.ListItem.UniqueId.ToString()))
            {
               relatedItemUniqueId 
                 = item["item_x0020_2"].ToString();
               relatedListId 
                 = item["list_x0020_2"].ToString();
            }
            else
            {
               relatedItemUniqueId 
                 = item["item_x0020_1"].ToString();
               relatedListId 
                 = item["list_x0020_1"].ToString();
            }
            if (!(item["Relationship_x0020_Type"] == null))
            {
               SPFieldLookupValue relationshipType 
                 = new SPFieldLookupValue(item["Relationship_x0020_Type"].ToString());
               relationship 
                 = relationshipType.LookupValue;
            }

            // Get the related item title and URL.
            SPList relatedList = this.Web.Lists[new Guid(relatedListId)];
            SPListItem relatedItem 
              = relatedList.Items[new Guid(relatedItemUniqueId)];
            string relatedItemUrl 
              = relatedList.Forms[PAGETYPE.PAGE_DISPLAYFORM].ServerRelativeUrl 
            + "?ID=" + relatedItem.ID.ToString();

            // Output the link.
            output.WriteLine("<li><a href='" 
              + this.Web.Url + relatedItemUrl + "'>" 
              + relatedItem.Name + "(" + relationship + ")" + "</a>");
         }
      }
      base.Render(output);
   }
   Protected Overrides Sub Render(ByVal output As HtmlTextWriter)
      If MyBase.ControlMode.Equals(SPControlMode.Display) Then
         ' Get all corresponding relationships.
         Dim list As SPList = Me.Web.Lists("Relationship Lookup")
         Dim query As SPQuery = New SPQuery()
         Dim queryFormat As String = "<Where>" & _
              "<Or>" & _
              "<Eq><FieldRef Name='item_x0020_1'/><Value Type='Text'>{0}</Value></Eq>" & _
              "<Eq><FieldRef Name='item_x0020_2'/><Value Type='Text'>{0}</Value></Eq>" & _
              "</Or>" & _
              "</Where>"
         query.Query = String.Format(queryFormat, Me.ListItem.UniqueId.ToString())
         Dim listItems As SPListItemCollection = list.GetItems(query)
         output.WriteLine("Related Documents:")
         Dim item As SPListItem
         For Each item In listItems
            Dim relatedItemUniqueId As String = String.Empty
            Dim relatedListId As String = String.Empty
            Dim relationship As String = String.Empty
            ' Get the relationship type.
            If Not (item("Relationship_x0020_Type") = Nothing) Then
               Dim relationshipType As SPFieldLookupValue &_
                 = New SPFieldLookupValue(item("Relationship_x0020_Type").ToString())
               relationship = relationshipType.LookupValue
            End If
            ' Get the related list and item IDs.
            If item("item_x0020_1").ToString().Equals(& _
              Me.ListItem.UniqueId.ToString()) Then
               relatedItemUniqueId = item("item_x0020_2").ToString()
               relatedListId = item("list_x0020_2").ToString()
            Else
               relatedItemUniqueId = item("item_x0020_1").ToString()
               relatedListId = item("list_x0020_1").ToString()
            End If
            ' Get the related item title and URL.
            Dim relatedList As SPList &_
              = Me.Web.Lists(New Guid(relatedListId))
            Dim relatedItem As SPListItem &_
              = relatedList.Items(New Guid(relatedItemUniqueId))
            Dim relatedItemUrl As String = Me.Web.Url & _
              relatedList.Forms(PAGETYPE.PAGE_DISPLAYFORM).ServerRelativeUrl & _
              "?ID=" + relatedItem.ID.ToString()
            ' Output the link.
            output.WriteLine("<li><a href='" + relatedItemUrl + "'>" & _
              relatedItem.Name & "(" & relationship & ")" & "</a>")
         Next
      End If
      MyBase.Render(output)
   End Sub
Read It

Because the values are stored in a secondary list and not within the field value, you can dynamically retrieve and display them after the relationship is created without having to update the related document. The field control gives you great flexibility in how you format and display this information, whether it is contained within the field, in a separate list, or a combination of both.

You can further modify this example to extend the edit mode of the control and let users edit and manage existing relationship information.

In an implementation, one scenario that you should account for is when one of the documents in the relationship is deleted, resulting in a dead link and the requirement to clean up the relationship information in the lookup list. One solution would be to validate and clean up the relationship information within the custom field control. This would ensure that only the existing relationships are displayed. You could also use the ItemDeleted event handler to perform the cleanup when a document is deleted. Additionally, you should apply indexes to the columns that are used in the query to optimize performance.

See It Using Custom Fields to Display Relationships

Watch the Video

Video Length: 00:08:15

File Size: 6.01 MB WMV

Explore It