November Happy Hour will be moved to Thursday December 5th.

How to customise HTML output of XFormStatistics?

Vote:
 
Could anyone with more experience than me in "skinning" EPiServer controls give me some pointers on how I can customise the output of the HTML that XFormStatistics generates? Do I have to try and buffer the output on a pre-render event and then do string manipulation, or is there a better way? The output will be displayed on every page (within the template), so I need an efficient solution. Or, is XFormStatisitics not really suited to customised output, and if so, should I be extracting form results another way? Any ideas appreciated! /\dam
#13090
Jun 26, 2007 13:47
Vote:
 
Hi Adam! I'd use a ControlAdapter to override rendering, either by implementing a custom CreateChildControls() or a RenderChildren() and take care of the rendering myself. The "standard" CreateChildControls() adds childcontrols of type Table / Row / Cell, every voted alternative is represented by one row, where Cell1 holds the option name, Cell2 an array of images, either showing a total number of votes or the percentage and Cell3 the number/percentage. Regards, Johan Olofsson EPiServer AB
#15396
Jun 26, 2007 15:55
Vote:
 
Thanks Johan, I will have a play! Do you think there is any appreciable overhead to using this method? As noted, I'd be doing it for almost every page view across the site. /\dam
#15397
Jun 26, 2007 17:35
Vote:
 
The overhead should be minimal, as your rendering or createchildcontrols will be called _instead_ of the original controls methods. The alternative to parse the generated html and make inline modifications would probably be a lot less efficient performance wise. /johan
#15398
Jun 26, 2007 22:24
Vote:
 
I'm not having much luck implementing this unfortunately :-( Does anyone have a code sample they can point me to, showing how to override child controls of an EPiServer control? Thanks! /\dam
#15399
Jul 04, 2007 13:48
Vote:
 
Nah, you shouldn't have to "override" (technically speaking), rather provide a substitue control to take care of the rendering of another control. Check out the MSDN documentation on Control Adapters. If I can get them time, I'll try and see if I can hack a small sample for you. /johan
#15400
Jul 04, 2007 14:03
Vote:
 
Ok, heres a small sample showing how to overide default rendering of XFormStatistics. 1) Compile the below code to an assembly and put it in the EPiServer's /bin directory Note, you'll need to add references to the following assemblies: EPiServer.dll, EPiServer.XForms.dll andd EPiServer.BaseLibrary.dll using System; using System.Web; using System.Web.UI; using System.Web.UI.Adapters; using System.Web.UI.WebControls; using EPiServer; using EPiServer.WebControls; using EPiServer.XForms; using EPiServer.XForms.WebControls; namespace XFormX { public class RenderSample : ControlAdapter { protected override void CreateChildControls() { XFormStatistics xformStat = Control as XFormStatistics; xformStat.Controls.Add( new LiteralControl("

This is rendered using a ControlAdapter

")); foreach(XFormData formData in xformStat.Statistics) { xformStat.Controls.Add( new LiteralControl(String.Format( "Dateposted: {0}
", formData.DatePosted))); } xformStat.Controls.Add( new LiteralControl( "

" ) ); } } }
2) Then, save the below xml into a file named 'something'.browser into the folder App_Browsers of your EPiServer directory. Create the App_Browsers directory if it doesnt alread exist. Now, all rendering of XFormStatistics is done through our controladapter, which simply lists the dateposted for every post of the form - you may want to change this logic :) Regards, Johan Olofsson EPiServer AB
#15401
Jul 04, 2007 14:29
Vote:
 
This is incredibly helpful, thank you very much for taking the time to post an example! /\dam
#15402
Jul 05, 2007 10:30
Vote:
 
I can pretty much do what I need to do now, so thanks again. I was a little surprised at the internal data structure of XFormStatistics though. From the name, I expected it would store *totals* rather than individual responses. To output the results I am therefore looping through each FormData object, populating a SortedList as I go, and then outputting the totals from my SortedList. Is this a reasonable way of doing it, or am I missing a data structure hidden away somewhere in XFormStatistics?! :-) /\dam
#15403
Jul 05, 2007 13:25
Vote:
 
Yes, thats how XFormStatistics work its magic too :) It however internally uses an dictionary of FormFieldStatistic objects to keep track of votes. Below is a slight modification of the controladapter that presents the vote count for each field in the form: using System; using System.Web; using System.Web.UI; using System.Web.UI.Adapters; using System.Web.UI.WebControls; using System.Collections.Generic; using EPiServer; using EPiServer.WebControls; using EPiServer.XForms; using EPiServer.XForms.WebControls; namespace XFormX { public class RenderSample : ControlAdapter { protected override void CreateChildControls() { XFormStatistics xformStat = Control as XFormStatistics; Dictionary formFields = new Dictionary(); foreach(XFormData d in xformStat.Statistics) { foreach(System.Xml.XmlNode n in d.Data.GetElementsByTagName( "instance" )[0].ChildNodes) { String name = n.LocalName; String val = HttpContext.Current.Server.HtmlEncode( n.InnerText ); if(!formFields.ContainsKey( name )) { FormFieldStatistic tmpStatistic = new FormFieldStatistic( name ); tmpStatistic.AddEmptyVote( val ); formFields.Add( n.LocalName, tmpStatistic ); } ( (FormFieldStatistic)formFields[name] ).AddVote( val ); } } // do something with foreach(string key in formFields.Keys) { FormFieldStatistic ffs = formFields[key]; Control.Controls.Add( new LiteralControl(String.Format("{0} : {1} votes
", ffs.FieldName, ffs.Votes.Count ))); } } } }
/johan
#15404
Jul 05, 2007 14:11
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.