Topic
This
is maybe my last post about the Team Site Wiki Page customization with
the aim of exceeding its limitations. This time we are going to customize the
unique template ( wkpstd.aspx) by replacing the control that renders the
editable content by a custom one.
In this post example, we will take
advantage of the use of this custom control to render not editable additional
contents, for instance, a header and a footer that could be the same for a
specific Wiki Page Library. Of course, we are not going to really customize the template, but we are going to use a delegate control to replace the control at runtime.
Here are the screen shots of the result:
We can see a non editable Header and Footer on the Team Site Wiki Page
In edit mode these additional contents are not rendered, but we can add new content as usual
And of course, after having saved the page, the new content is rendered wtih the non editable Header and Footer.
Steps required
If you look at the Team Site Wiki Page template, wkpstd.aspx, you can see the control that is rendering the editable content/
<SharePoint:EmbeddedFormField ID="WikiField" FieldName="WikiField" ControlMode="Display" runat="server" />We are first going to create a custom EmbeddedFormField control
Then, we are going to use a delegate control to replace the native EmbeddedFormField control by the custom one in order to have the control on the wiki page content rendering.
1 - Creating a custom EmbeddedFormField control
Here is the screen shot of the Visual Studio solution:
and the custom control source code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using
System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using
Microsoft.SharePoint.Security;
using System.Security.Permissions;
using System.Diagnostics;
namespace CustomControls
{
[SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel =
true), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class EmbeddedFormFieldCustom : FormField
{
public
EmbeddedFormFieldCustom()
{
Debug.WriteLine("EmbeddedFormFieldCustom: " + "constructor...");
}
private string _header = "";
private string _footer = "";
public string Footer
{
get { return _footer; }
set { _footer = value; }
}
public string Header
{
get { return _header; }
set { _header = value; }
}
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public string Content
{
get
{
SPFieldMultiLineText field = base.Field as SPFieldMultiLineText;
if (field != null)
{
Debug.WriteLine("EmbeddedFormFieldCustom: " + "SPFieldMultiLineText ok");
return field.GetFieldValueAsHtml(this.ItemFieldValue, base.ListItem);
}
Debug.WriteLine("EmbeddedFormFieldCustom: " + "SPFieldMultiLineText non
ok");
return base.Field.GetFieldValueAsHtml(this.ItemFieldValue);
}
set
{
Debug.WriteLine("EmbeddedFormFieldCustom: " + "set Content");
this.ItemFieldValue = value;
}
}
[SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
protected override void
Render(HtmlTextWriter
output)
{
Debug.WriteLine("EmbeddedFormFieldCustom: " + "rendering..");
output.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
output.Write(_header);
output.RenderBeginTag(HtmlTextWriterTag.Div);
base.Render(output);
output.Write(_footer);
output.RenderEndTag();
}
}
}
2 - Replacing the standard control by the custom one by using a delegate control
Here is the delegate control source code:
<%@ Control Language="C#" ClassName="WikiPageCustomLink" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" %>
<%@ Assembly Name="CustomControls,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=0f4e5a441a5ac20c" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="System.Diagnostics" %>
<!--delegate control begin
-->
<script runat="server">
Control ctrlTofind = null;
CustomControls.EmbeddedFormFieldCustom myCustomEmbeddedFormField = null;
protected void
FindControl(Control aControl, string ID)
{
if
(aControl.HasControls())
{
foreach (Control aControl2 in aControl.Controls)
{
if (aControl2.ID ==
ID)
{
ctrlTofind = aControl2;
}
else
{
FindControl(aControl2, ID);
}
}
}
else
{
if (aControl.ID ==
ID)
{
ctrlTofind = aControl;
}
}
}
protected override
void OnInit(EventArgs e)
{
if (!IsPostBack)
{
Debug.WriteLine("onInit");
if
(Page.TemplateControl.ToString().Contains("ASP.WKPSTD_ASPX"))
{
try
{
int ctrlNumber = this.Page.Controls.Count;
foreach (Control aControl in this.Page.Controls)
{
FindControl(aControl, "WikiField");
}
myCustomEmbeddedFormField = new
CustomControls.EmbeddedFormFieldCustom();
myCustomEmbeddedFormField.Header = "<span
style='color:red;font-size:12pt' >This is my Custom header, not
editable</span>";
myCustomEmbeddedFormField.Footer = "<span
style='color:red;font-size:12pt' >This is my Custom footer, not
editable</span>";
Control
updatePannelContentTemplateContainer = ctrlTofind.Parent;
UpdatePanel myUpdatepannel = (UpdatePanel)updatePannelContentTemplateContainer.Parent;
int index = 0;
for (int i = 0; i <
updatePannelContentTemplateContainer.Controls.Count; i++)
{
if
(updatePannelContentTemplateContainer.Controls[i].ID == "WikiField")
{
index = i;
}
}
updatePannelContentTemplateContainer.Controls.Remove(ctrlTofind);
updatePannelContentTemplateContainer.Controls.AddAt(index,
myCustomEmbeddedFormField);
myCustomEmbeddedFormField.FieldName = "WikiField";
myCustomEmbeddedFormField.ID = "WikiField";
myCustomEmbeddedFormField.ControlMode =
Microsoft.SharePoint.WebControls.SPControlMode.Display;
}
catch (Exception ex)
{
Response.Write("<br>error :
<br>" + ex.Message);
Response.Write("<br>error :
<br>" + ex.StackTrace);
}
}
}
base.OnInit(e);
}
</script>
<!--delegate control end
-->
The secret is to load the custom control only if it is not a post back, since the embedded control itself seems to be used only for displaying the content.
Conclusion
Of course this trick could be used to add an additional custom control, a web part zone, etc... to no more be limited by the unique wkpstd.aspx template features. I let you explore the possibilities...
This
is maybe my last post on the Team Site Wiki Page customization.
- We have already explored the customizations linked to the CSS, and
the way to add a delegate control in these posts:
Managing the Styles and the Markup Styles Menus for the Wiki Pages of a SharePoint 2010 Team Site
Themable CSS Registration and Rendering for SharePoint 2010
- We have explained how to provision custom content in a Wiki Page in this
one:
Provisioning a custom Wiki Page within a SharePoint 2010 Team Site - And this is the general post on the SharePoint 2010 Team Site Wiki Pages
Branding and Customizations that also shows how to debug the Ribbon
Customizing and branding the SharePoint 2010 wiki pages
I
think I can now keep exploring the SharePoint 2010 wiki cuztomizations, but in
the SharePoint 2010 Server version and try to use a custom
SPFieldMultiLineText.
4 comments:
Hey mate -
How do you get your delegate control in? - ie - which delegate control place holder do you register it against? additionalpagehead?
PS -
Awesome idea there - thinking out of the box at its best!
Hi Chris,
thank you !!!
I think, yes, I used AdditionalPageHead as in my previous post :
http://mosshowto.blogspot.com/2009/12/sharepoint-2010-wiki-styles.html
<Control Id="AdditionalPageHead" Sequence="90" ControlSrc="~/_ControlTemplates/WikiPageCustomCSSLink.ascx" />
Does anyone else have this solution cause your entire page to be uneditable? I am the administrator and can go into edit mode, but cannot actually edit anything.
Post a Comment