Click here to Skip to main content
Click here to Skip to main content

SharePoint List Parent / Child Relationship

, 23 Sep 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
SharePoint Custom Field Type: ParentChildrenField for parent/child list relationships.

Introduction

Parent-child relationship pattern is very common in the real world. In SharePoint, it is represented with two SharePoint lists, linked with a Lookup Field contained in the child list. That way, the Parent-Child relationship is established between the Lists.

We need a way to present child items in Parent List Forms (DisplayForm.aspx, EditForm.aspx, NewForm.aspx). For that purpose, I created a SharePoint Custom Field Type: "ParentChildrenField".

Description

To make a custom tab-dialog navigation instead of the standard SharePoint site top navigation, I created two SharePoint lists: Tabs and Sub-Tabs. I created the site column "Parent Tab", type Lookup on the table Tabs, showing the column Title. That column is added to the "Sub-Tabs" list.

Parent-Child Relationship

Create "My Child Items" Field

To present child items (sub-tabs) in the Tab Forms (Display, Edit, and New), I created a new SharePoint Site Column "My Child Items", type of the previously defined "ParentChildrenField". That column is added to the parent list "Tabs". Generally, it is much better to add columns to the list Content Types instead of directly to the List.

Parent-Child Relationship

Source Code

public class ParentChildrenFieldControl : TextField
{
    int NumOfChildren = 0;
    LiteralControl literalCtrl;
    SPList childList = null;
    string listID = SPContext.Current.List.ID.ToString();
    HyperLink linkAddNew = new HyperLink();
    
    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        if (this.ControlMode == SPControlMode.Display ||
            this.ControlMode == SPControlMode.Edit ||
            this.ControlMode == SPControlMode.New)
        {
            literalCtrl = new LiteralControl();
            base.Controls.Add(literalCtrl);
            base.Controls.Add(linkAddNew);
        }
    }


    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        string childListname = this.Field.GetCustomProperty("ChildListName").ToString();
        childList = SPContext.Current.Web.Lists[childListname];
        StringBuilder sb = new StringBuilder();
        SPQuery query = new SPQuery(childList.DefaultView);
        query.Query = string.Format(@"
        <Where>
           <Eq>
              <FieldRef Name='{0}' LookupId='true' />
              <Value Type='Integer'>{1}</Value>
           </Eq>
        </Where>", LookupField.InternalName, this.Item.ID.ToString()); 
            sb.Append(childList.RenderAsHtml(query));

        literalCtrl.Text = sb.ToString();

        // Add new
        linkAddNew.Text = "Add New";
        string navigateUrl = string.Format("/NewForm.aspx?{0}={1}&Source={2}", 
                      SPEncode.UrlEncode(LookupField.Title), 
                      SPContext.Current.ListItem.ID.ToString(), 
                      SPEncode.UrlEncode(this.Page.Request.Url.ToString()));
        linkAddNew.NavigateUrl = childList.RootFolder.ServerRelativeUrl + navigateUrl; 
    }

    SPField _LookupField = null;
    SPField LookupField    
    {
        get {
            if (_LookupField == null) 
            {
                foreach (SPField field in childList.Fields) 
                {
                    if (field is SPFieldLookup && 
                        ((SPFieldLookup)field).LookupList == listID) 
                    {
                        _LookupField = field;
                        break;
                    }
                }
            }
            return _LookupField;
        }
    }

    protected override void Render(HtmlTextWriter output)
    {
        literalCtrl.RenderControl(output);
        // Add New link
        if (this.ControlMode == SPControlMode.Display ||
            this.ControlMode == SPControlMode.Edit)
            linkAddNew.RenderControl(output);
    }

    public override void UpdateFieldValueInItem()
    {
        this.EnsureChildControls();
        this.Value = NumOfChildren;
        this.ItemFieldValue = this.Value;
    }
}

Add a New Child Item

When the user adds new child items, we want ot automatically select the item of the "Parent Tab" dropdown list in the NewForm.aspx form. That's why we add the Lookup Field Name and Value in the request query string: "NewForm.aspx?Parent%20Tab=1&Source=..." .

Parent-Child Relationship

Put the following JavaScript block to the Child List NewForm.aspx. The best place is in "PlaceHolderBodyAreaClass".

<script type="text/javascript">
var qs = location.search.substring(1, location.search.length);  
var nameVal = qs.split("&")[0].split("=");  
SetLookupFieldValue(unescape(nameVal[0]), nameVal[1]);
    
function SetLookupFieldValue(fieldName, val) {
    var theSelect = getTagFromIdentifierAndTitle("select", 
                    "Lookup", fieldName);
    if (theSelect != null) {
        theSelect.value = val;
        return;
    }
    // if theSelect is null, 
    // it means that the target list has more than 20 items, 
    // and the Lookup is being rendered with an input element
    var theInput = getTagFromIdentifierAndTitle("input", 
                                                "", fieldName);
    theInput.value = val;
}

function getTagFromIdentifierAndTitle(tagName, identifier, title) {
    var len = identifier.length;
    var tags = document.getElementsByTagName(tagName);
    for (var i = 0; i < tags.length; i++) {
        var tempString = tags[i].id;
        if (tags[i].title == title && (identifier == "" || 
            tempString.indexOf(identifier) == tempString.length - len))
            return tags[i];
    }
    return null;
}    
</script>

Installation

The Solution Package "ParentChildListRelationship.wsp" was developed using Visual Studio Extensions VSeWSS v1.3. Open "Setup.bat" and set your Site and Web URLs:

set DefaultWebUrl=http://YourWeb 
set DefaultSiteUrl=http://YourSite

To install, run setup.bat. To uninstall, run setup.bat -u.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Slavko.Parezanin
Software Developer (Senior) Freelancer
Serbia Serbia
June 2011. – Present, Freelancer
• Took part in development of Web Platform for automated trading.
Thanks to Lightstreamer.com as the real-time bi-directional data delivery we realized Long Polling Push pattern. Also, thanks to ASP.NET MVC 4 mobile features, application renders different HTML markups for different display devices, mobile specific or agent specific (i.e. iPhone).
As the Data Access Layer, we used SQL Server and Entity Framework Repository Pattern.
At client side intensive usage of jQuery, Bootstrap, Knockout.js and Widgets developed by custom bindings of Knockout.js.

September 2010. – May 2011. TekNuvo

• Developed application for coupon and promotional data for advertisers. Technologies: ASP.NET MVC 3, C#, LINQ, Entity Framework 4.0, Code-First, Scaffolding …
• Extracted and integrated Lucene Search Modules from Orchard CMS Project Source.
• Using Unity as Dependency Injection Container, and Interfaces instead of specific classes, i.e. accessing data through an abstract repository interface, we enabled easy way of unit testing. Used TDD as the method of a design, specifying desired behaviors in the form of unit tests, and then provided implementations to fit.
• Developed several jQuery plugins.
• Developed Shopping Cart application using “ASP.NET MVC 2”, “LINQ to SQL” and NUnit.

March 2008. – August 2010. Mogul Balkan

• Developed Windows Service for integration of Active Directory Groups and Users with SharePoint Groups and Users.
• Integration of InfoPath Forms services with SharePoint.
Developed PowerShell script for automatic unpacking, modifying and packaging of the InfoPath Forms.
• Created custom Moss 2007 Publishing Portal Site Definition with automatic creation of sites structure for extranet project.
• Developed Publishing Feature for WSS 3.0 only.
• Customization and extension of Content Query Web Part.
• Customization of CQWP XSLT files.
• Deployment of SharePoint packages using VSeWSS 1.3 and WSPBuilder
• Deploymen
Follow on   Google+   LinkedIn

Comments and Discussions

 
QuestionAnyone have the version that works on WSS 3.0 ? PinmemberMember 101837421-Aug-13 13:19 
QuestionSharePoint List Parent / Child Relationship with Sharepoint 2010 Pinmemberecolle4-Nov-10 5:18 
AnswerRe: SharePoint List Parent / Child Relationship with Sharepoint 2010 PinmemberSlavko.Parezanin4-Nov-10 11:25 
QuestionHow to select columns of child list that will be presented? PinmemberSlavko.Parezanin1-Oct-10 0:09 
GeneralMy vote of 1 PinmemberBoci28-Sep-10 13:00 
GeneralRe: My vote of 1 PinmemberSlavko.Parezanin29-Sep-10 0:44 
QuestionHow to use component PinmemberSlavko.Parezanin21-Sep-10 22:52 
GeneralObject reference not set to an instance of an object error Pinmemberfakhteh amani22-Feb-10 21:49 
GeneralRe: Object reference not set to an instance of an object error PinmemberEric Taylor5-Mar-10 5:35 
GeneralRe: Object reference not set to an instance of an object error Pinmemberelmocha1-Aug-10 22:44 
GeneralRe: Object reference not set to an instance of an object error PinmemberSlavko.Parezanin21-Sep-10 22:45 
GeneralRe: Object reference not set to an instance of an object error PinmemberWWare0115-Sep-11 9:11 
GeneralRe: Object reference not set to an instance of an object error PinmemberSlavko.Parezanin15-Sep-11 21:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150414.1 | Last Updated 23 Sep 2010
Article Copyright 2010 by Slavko.Parezanin
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid