NOTE This article presents a solution to a problem/challenged described in an earlier article. It's intended to be read in context of first having read the earlier article.
Solving a small but tricky problem related to customised rendering of a property in EPiServer 7 with ASP.NET Web Forms.
Starting with the simple stuff we render each of the properties using the Property control.
<EPiServer:Property PropertyName="Heading" CustomTagName="h1" runat="server" /> <EPiServer:Property PropertyName="Intro" CustomTagName="p" runat="server" />
Then we make both properties editable using a text area by adding a UI hint to each of them.
//using EPiServer.Web; [UIHint(UIHint.Textarea)] public virtual string Heading { get; set; } [UIHint(UIHint.Textarea)] public virtual string Intro { get; set; }
Customise the rendering
Moving on to the next requirement, we need to replace line breaks in the Heading property with br tags before rendering it. To do so we can change the rendering of it from using the Property control to using a h1 tag that we turn into a control by adding runat="server" and an ID to it.
<h1 ID="headingControl" runat="server"></h1>
Next, in code behind, we set its InnerHtml to the modified value and make it editable in on-page-editing mode using the ApplyEditAttributes extension method.
//using EPiServer.Web; protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (!string.IsNullOrEmpty(CurrentPage.Heading)) { headingControl.InnerHtml = CurrentPage.Heading.Replace("\n", "<br />"); } headingControl.ApplyEditAttributes<StandardPage>(x => x.Heading); }
At first it may seem like we've solved the challenge. Both properties are editable in on-page-edit mode using text areas and a line break in the Heading property is replaced with a br tag. However, let's look at what happens when we make a change to the Heading property:
The line break in the Heading property isn't replaced with a br when the new value is inserted into the page during editing. We're not meeting the requirement that both properties should offer a realistic preview at all times.
This happens because the CMS has no way of knowing that we're customizing the rendering of the property in our view. Instead it updates the DOM node that represents the property with what would be rendered by the Property control.
Fixing the preview
In order to fix the preview we could go back to rendering the property using the Property control and then modify how either all strings or string properties with a Textarea UI hint are rendered.
That would however violate the requirement that a line break in the Intro property should not be replaced with a br tag. Therefor we'll have to find a way to customize only the rendering of the Heading property. Luckily there are a few ways to do that.
One is to first render it using the Property control and specify a tag using RenderSettings:
<EPiServer:Property PropertyName="Heading" CustomTagName="h1" runat="server"> <RenderSettings Tag="LineBreaked" /> </EPiServer:Property>
Next we create a user control that inherits from PropertyControlBase<string> and add a TemplateDescriptor attribute to it in which we specify the same tag.
[TemplateDescriptor(TagString = "LineBreaked")] public partial class LineBreaked : PropertyControlBase<string> { }
Still in code behind for our custom property control we create a property that exposes the original value, which we can retrieve through the CurrentData property, modified the way we like.
protected string Formated { get { if (string.IsNullOrEmpty(CurrentData)) { return string.Empty; } return CurrentData.Replace("\n", "<br />"); } }
Finally, in the markup part of the user control we output the return value of the property.
<%= Formated %>
And with that the challenge is solved.
Alternative solution
Above we change how the Heading property is rendered by specifying a tag when rendering it with the Property control. This works well but it only modifies how the property is rendered, including preview, in a single place.
If we instead wanted to change how it's rendered everywhere where the Property control is used we could use an alternative approach - using UI hints.
[UIHint("LineBreaked")] [UIHint(UIHint.Textarea, PresentationLayer.Edit)] public virtual string Heading { get; set; }
In the above code we've added a second UIHint attribute to the Heading property. This UI hint has the same value as the tag that our custom property control supports, meaning that it will be rendered using our custom control.
However, we also want the property to be edited using a text area meaning we need to keep the existing UI hint, creating a conflict. To fix that we use an overload of the UIHintAttribute class' constructor and pass it a string representing a "presentation layer". Specifically the string exposed by the Edit constant in EPiServer's PresentationLayer class.
PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.
Similar articles
- EPiServer editing delight challenge - MVC solution
- Custom rendering of content areas
- How EPiServer's HTML helper PropertyFor works
- EPiServer editing delight challenge
- Sweet EPiServer Templating with TypedPageList
- EPiServer 7 and MVC – How to customize rendering of properties
- EPiServer 7 and MVC – Custom tags and CSS classes when rendering properties
- Developing with Page Type Builder – Using Interfaces and Advanced Inheritance
My book
Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!
Comments
comments powered by Disqus