Disclaimer: This post is not about what you should do, it’s just a reason for me to post some freaky code. Check out the comments for more “natural” solutions.
If you’ve ever used Page Type Builder you know that it allows you to access property values in a strongly typed way. That is you can write:
CurrentPage.MyProperty //instead of using a dictionary lookup with a magic string CurrentPage["MyProperty"]
Using that you have an option to using the PropertyControl to render the value of the property in a page or user control. That is you can do:
<%= CurrentPage.MyProperty %> <!-- Instead of --> <EPiServer:Property PropertyName="MyProperty" runat="server" />
For many property types that’s all good but there are times when you need to use the PropertyControl, or rather the magic stuff that it does. Two common examples of this is when you need to render the values of XHtml properties that contain dynamic content and for XForms.
I guess you can live with using the PropertyControl at times but it seems kind of sad to go back to using magic strings. Luckily there are a couple of solutions.
One solution is to set the PropertyControls’ PropertyName in code behind and retrieve the property name using the extension method for PageData named GetPropertyName that ships with Page Type Builder. That is you do something like this:
protected override void OnLoad(System.EventArgs e)
{
MyPropertyControl.PropertyName =
CurrentPage.GetPropertyName(page => page.MyProperty)
base.OnLoad(e);
}
I’ve experimented a little with this and it seems to work fine. But what bugs me is that I have to do stuff both in the markup file and the code behind file to do something as simple as rendering a property. Of course being used to Web Forms I’m used to having to do stuff like that, but I still don’t like it.
Let’s throw a couple of “best practices” out the window (we can bring them back later, I promise) and see if we can find another way! To be on the safe side be sure to head to Spotify or whatever you use to play music and turn on Missy Elliot’s “Get ur freak on” on max volume.
Having done that we’re ready to create a static class:
public static class ViewExtensions
{
}
You can call it whatever you like, mine is called ViewExtensions since I’m using EPiMVP. Next, we create the below small and freaky extension method.
public static void RenderProperty<THandler, TPageData>(this THandler handler, TPageData page, Expression<Func<TPageData, object>> expression)
where TPageData : PageData
where THandler : Control, ICurrentPage, IHttpHandler
{
string propertyName = page.GetPropertyName(expression);
PropertyData propertyData = page.Property[propertyName];
Property propertyControl = new Property(propertyData);
propertyControl.Page =(Page)HttpContext.Current.Handler;
propertyControl.RenderControl(new HtmlTextWriter(HttpContext.Current.Response.Output));
}
Having done that you can now do this in you aspx’s and ascx’s:
<% this.RenderProperty(CurrentPage, page => page.MyProperty); %>
Unfortunately this doesn’t work with XForms but it seems to be working just fine with XHtml strings which I guess covers many of the scenarios where you need to use the PropertyControl.
Of course this is like having the cake, eating it and making love to it, (perhaps) not very realistic and clearly unnatural (unless you’re a cookie yourself longing for little cookie offspring) but at least it’s possible.
If you’ve got an idea of how to make it work with XForms I’d be very interested! My Reflector doesn’t want to talk to me anymore saying I’m “just using it”…
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.
This blog is built with EPiServer Community, EPiServer CMS, ASP.NET MVC and a bunch of other great products. The source code is available for download at the projects page, where you also can read more about this site and my other projects.
read more
Comments
Christer 1 years ago
Cant you just to get your property in your pagetype class insted and do .ToWebString() on your xhtml property instead?
in the getter:
var mainbody = this.Property["MainBody"] as PropertyXhtmlString;
return mainbody != null ? mainbody.ToWebString() : string.Empty;
Joel Abrahamsson 1 years ago
Christer, yeah, you could definitely do that I guess, but what I set out to do was to find a way that would work with all property types. Of course I failed since it doesn't work with XForms :)
Joel Abrahamsson 1 years ago
Also, when it comes to XHtml string you could also do this: