1

I have 2 custom fields that are associated to the publishing features Page content type. While looking at the page, in the ribbon, I can click on Edit Properties to view all of the properties of my page. My 2 custom properties show up and save fine.

I'd like to have my 2 custom properties show up when you click on 'Edit Page', in the same manner that Page Title has a editable field. I have found the <PublishingWebControls:EditModePanel> within the page layouts. I assume I can edit the page layout and be done with it.

How can I create this as a deployable feature so that I don't have to manually edit each page layout associated to these content type?

Edit 1

I'm able to see a textbox for my 2 custom properties in edit mode when I add 2 text fields inside of the EditModePanel. I can see and update my text just fine. But I need to be able to provide a deployable solution.

Edit 2

I'm basically trying to recreate what you visually see here in the screenshot. Custom properties in the edit mode of the page. I opened up the attached wsp and it appears that a feature is being delegated to the AdditionalPageHead. So the assembly must have some sort of logic in it to determine the type and state of the page.

Edit 3

I ended up writing a blog post with the final solution that can be found here

3
  • @Edit 3 - excellent, nicely done!
    – James Love
    Jun 7, 2011 at 16:53
  • Thanks! It's long with a lot of moving parts, but it was a great topic I hope others will find useful. Jun 7, 2011 at 18:09
  • If you think that's a lot of moving parts, open up the Publishing assembly in Reflector/ILSpy and have a look at some of the application pages ;) Your solution is actually rather elegant.
    – James Love
    Jun 7, 2011 at 18:39

2 Answers 2

1

The way I've done this is to have a Feature (Site-collection scoped) which has:

  • Your two new Fields
  • A Content Type which inherits from Page, which includes your two Fields as FieldRefs
  • A Module to deploy your customised Page Layout, and associates the content type.

Chris O'Brien has covered this in this blog post. Also here is how to deploy Content Types in features too. You can have all of this in the same feature.

Update: @webdes03 asked a question today where he was deploying his Page Layout, has a prefect example of the Elements.xml code for this.

10
  • I don't believe that this would work for my situation, because I want these edit fields to be applied to all page layouts, not just a custom one. Jun 2, 2011 at 18:12
  • 1
    You could have Feature Receiver could that would add two fields to the Page Content Type, but for adding them to all Page Layouts, that won't be possible unless you opened the file and added the field controls at the right places (in code, very messy, wouldn't recommend it).
    – James Love
    Jun 2, 2011 at 18:15
  • 1
    Sure :) Assuming you know how delegate controls work, we have one added into additional page head. This control looks at the current page's content type, through SPContext.Current.ListItem.ContentType. Here you can get the fields in the content type. Each SPField has a FieldRenderingControl property. Add this to a collection. Next, you want to locate the control on the page (this.Page in your delegate control) for page content ("PlaceHolderMain", not sure exactly how to get this from this.Page.Controls though), and add to this control every FieldRenderingControl for your custom fields.
    – James Love
    Jun 2, 2011 at 18:42
  • 1
    There's a few things to watch out for, as it's a delegate control it'll be added to EVERY page in your site, so your delegate control must check to ensure that the current page being loaded is indeed a Publishing Page (PublishingPage.IsPublishingPage() method, passing in SPContext.Current.ListItem).
    – James Love
    Jun 2, 2011 at 18:44
  • 1
    Yep, the FieldRenderingControl which you get for each of the SPFields should have all the logic required for loading & saving of the field contents.
    – James Love
    Jun 2, 2011 at 18:51
1

I've already accepted James' answer as it provided me the information I needed to get the solution. But for future reference, here's a workable code solution. I don't know if it could be optimized to run more efficiently (such as checking the content type), as it is appended to every page.

The process is as follows

  1. Check that the current page is a list item
  2. If it is, is the content type inherits from "Page"?
  3. If we are in edit mode or this is a new form
  4. Find PlaceHolderMain in the master page
  5. Get our FieldRenderingControl's and add them to PlaceHolderMain

Sorry, but I can't figure out the damn code block. The first if statement is not in it Fixed - James Love

if (SPContext.Current != null && SPContext.Current.ListItem != null)
{
    SPContentTypeId pageContentType = SPContext.Current.Web.ContentTypes["Page"].Id;
    if (SPContext.Current.ListItem.ContentType.Id.Equals(pageContentType) ||
    SPContext.Current.ListItem.ContentType.Parent.Id.Equals(pageContentType))
    {
        if (PublishingPage.IsPublishingPage(SPContext.Current.ListItem))
        {
            if (SPContext.Current.FormContext.FormMode == SPControlMode.Edit || SPContext.Current.FormContext.FormMode == SPControlMode.New)
            {
                ContentPlaceHolder placeHolderMain = (ContentPlaceHolder)this.Page.Master.FindControl("PlaceHolderMain");
                if (placeHolderMain != null)
                {
                    SPField seoDescription;
                    try {
                        seoDescription = SPContext.Current.ListItem.Fields["seoDescription"];
                    }
                    catch {
                        seoDescription = null;
                    }
                    if (seoDescription != null)
                    {
                        BaseFieldControl seoDescriptionControl = seoDescription.FieldRenderingControl;
                        if (seoDescriptionControl != null)
                        {
                            seoDescriptionControl.ID = seoDescription.InternalName;
                            placeHolderMain.Controls.Add(seoDescriptionControl);
                        }
                    }
                    SPField seoKeywords;
                    try {
                        seoKeywords = SPContext.Current.ListItem.Fields["seoKeywords"];
                    }
                    catch {
                        seoKeywords = null;
                    }
                    if (seoKeywords != null)
                    {
                        BaseFieldControl seoKeywordsControl = seoKeywords.FieldRenderingControl;
                        if (seoKeywordsControl != null)
                        {
                            seoKeywordsControl.ID = seoKeywords.InternalName;
                            placeHolderMain.Controls.Add(seoKeywordsControl);
                        }
                    }
                }
            }
        }
    }
}

And magic! The 2 fields are added under the existing edit fields and appear as if they are out of the box! We could either re-style them or leave as is.

Edit

Shameless plug: Wrote a blog post to this solution here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.