Properties in CMS 5

by: Anders Hattestad

Problem:

How to create a EPiServer property which contains other EpiServer properties.

Why:

Most properties in EPiServer are pretty specialized and are often depended on each other to make the page show correctly.

some uses of a MultiProperty  are:

  • Links with user defined link name
  • Images with width, height & alt text
  • All type of lists containing one or more EPiServer property
  • Group properties that are needed for on specific function together
  • Dynamic list of pages/links/(or whatever) which could be managed by the editor (in edit modus)

How:

Itera.MultiProperty - the holy grail of EPiServer :)

The main idea is to represent an EPiServer property as xml.  Our MultiProperty stores all his children as xml and when it is used it unpacks this xml and creates each child property. Therefor the MultiProperty itself's is extended from PropertyString which is good for storing text :) Since the MultiyProperty is an property itself's it can contain any number of other multi properties in any nested levels.

In EPiServer 4 you could do the same, but you only had the function CreateChildControls, and the ParseValidation to work with. That gave a problem with who to retrive to value of the child properties. With EPiServer 5 and the introduction of the Control class this have changed, and the retriving of child properties values can easy be done with the ApplyEditChange().

One important thing to remember is that the property class is a part of the PageData instance. And all objecte inside will be shared between all request for that page and property. I did forget this once time and had a Literal inside the property class, and added it to the Control class. That did give a lot of unexpected errors :(

If you want on a project page structured contact information to the project leader you had to add name, street 1, street 2, zip code, town and email as separate properties. That sure worked, but was a bit tiresome. And if I wanted to have the project participants also as a list I would have to add a lot of properties, or use a text property. Or wonder why this information isn’t coming from AD or user data :(

Multi property can be divided in 2 different usages.

  1. Static list of properties
  2. Dynamic list of properties

1) Static list of properties

I made a property (ContactData) that had a InnerPropertyCollection.

PropertyDataCollection _new = new PropertyDataCollection();
_new.Add("Street1", new PropertyString());
_new.Add("Street2", new PropertyString());
_new.Add("ZipCode", new PropertyString());
_new.Add("City", new PropertyString());
_new.Add("Email", new PropertyString());
_new.Add("Phone", new PropertyString());
innerPropertyCollection = _new;
clip_image002

In my base Control class I loop through this collection and add the sub controls as part of this control. The whole trick is then to save the sub properties inside the owner property. That can be done with apply ApplyEditChanges() on each children before retriving the value from them.

To extend this property so it was able also to make a addable list of properties I had to add a base type collection. This is the template for stored properties created in the list.

 

2) Dynamic list of properties

clip_image002[5]

If there is only one property in the base collection there is only possible to add that property to the list. Move up, down and delete is also possible, and is parameters that can be overridden in the property.

The text I store inside the owner property is on form. The property name for properties in a list is based on Guids.

<p name=”[propname1]” type=”[propname_to_base]” isxml=”true”>[prop content1]</p>

<p name=”[propname2]” type=”[propname_to_base]” isxml=”true”>[prop content2]</p>

And is one tag for each property in the list. As you can see there is no root tag. That’s because it is easier to embed this content inside another property, and a root tag is easy to add when you convert to Xml. Else you have to check against empty values.

When I want to generate the property list from the xml I found out that ParseToObject(txt) didn’t do the trix. It seems that it will sometimes give you the base type of the property. I therefore used the Copy() and ParseToSelf(txt) methods.

Extend edit display mode

Then I started to make some logical properties. They will change the behavior of the edit display of the properties.

I made a new logical property PropertyTab

PropertyDataCollection _new = new PropertyDataCollection();
 _new.Add("NameTab", new PropertyTab("Name"));
_new.Add("Name", new PropertyString());
_new.Add("About",new PropertyTextBox("",250,60));
_new.Add("WorkTab", new PropertyTab("Work"));
_new.Add("WorkAdr", new PropertyContactData());
_new.Add("HomeTab", new PropertyTab("Home"));
_new.Add("HomeAdr", new PropertyContactData());
_innerPropertyCollection = _new;

If I would create a property (Contact) with name and some information and two address fields 

imageThe propertyTab property will the base property understand as tabs and will generate the standard episerver tabs.

As stated before this property type can have a list of inner properties. One or more of these can be a dynamic addable list. 

 

Combine static list with dynamic list

PropertyDataCollection _new = new PropertyDataCollection();
_new.Add("Contact", new PropertyContact());
basePropertys = _new;

image

Make property names language depended

The trick to make the property names depend on language is to make a lang file

<?xml version="1.0" encoding="utf-8" ?>
<languages>
  <language name="norsk" id="no">
    <pagetypes>
      <common>
        <property name="Name">
          <caption>Navn</caption>
          <help> </help>
        </property>
      </common>
    </pagetypes>
  </language>
</languages>
  

More to come

I will in a couple of weeks try to add code:

  • Enable Itera.MultiProperty to work as a dynamic property
  • Enable Inner properties to be languages depended
  • Enable usercontrol to act as property

Where to find

I have uploaded this project on EPiCode. And are working on a project page that needs some love :)

 

 

20 October 2008


Comments

  1. Very nice thanks you! I couldn't delete rows though. In propertyMulitbase I changed : if (!isParesed || InnerPropertyCollection == null) { if (InnerPropertyCollection==null) InnerPropertyCollection = new PropertyDataCollection(); ParseToSelf(ToString(), InnerPropertyCollection, BasePropertys); isParesed = true; } To : if (InnerPropertyCollection == null) InnerPropertyCollection = new PropertyDataCollection(); if (!isParesed ) { ParseToSelf(ToString(), InnerPropertyCollection, BasePropertys); isParesed = true; } Now it rocks!
  2. Was a bug with deleting. Was linked to that the state was preserved in the parent property. Your fix will do the trix but are some issues with other usages of the property. I recomand download the latest source code from coderesort. But good catch btw.
  3. This is really, really cool! I can see a lot of potential uses for this. Can wait to play around with it! Thanks for sharing.
  4. Very cool stuff Anders. But how do u access the inner properties from aspx page? Do you have a waye of displaying the inner property "WorkAdr"?
  5. Very cool stuff Anders. But how do u access the inner properties from aspx page? Do you have a waye of displaying the inner property "WorkAdr"?
  6. Hi Anders! This looks really great and I think it's perfect for solving several issues I've run into :) What I need to create is a list of linkcollections, where each linkcollection can have a title. So I created a PropertyLinkCollectionWithTitle that extended PropertySingleBase (and contains a propertystring and a propertylinkcollection), then I created a PropertyCollectionOfLinkCollections that extends PropertyMultiBase. Now I'm having trouble putting these to use. When registering the new property in admin-mode, I have to set a base type... I tried using string but then in editmode, my property turns out as a textbox. None of the basetypes fits. Should PropertyMultiBase be registered as a basetype somehow? Or have I misunderstood completely? :)
  7. Hi

    If you take a look in the example folder you will see PropertyListLinkAndName.cs

    This will self register as a new base type named ListLinkAndName

  8. That code looks like yours but with different names :)

    Trick is to make some properties and then on the property you want to use add [PageDefinitionTypePlugIn] public class PropertyListLinkAndName : PropertyMulitBase

  9. My mistake :) I thought I had to register the property manually, but obviously I didn't. So it works perfectly! Thanks!
  10. Thats good news. Hope the code will helo you to solve your problem
  11. And check out my blog post about how to access properties
  12. http://labs.episerver.com/en/Blogs/Anders-Hattestad/Dates/2008/11/ltEPiServerProperty-on-steroidsgt/
  13. I got the project from coderesort on november 7th. I can't delete rows from MultiBase-properties. I tested with Fred's code, but that didn't change anything.
  14. Hi Will take a look at this in the weekend.
  15. Hi Had implementet some other edit views and had to clear the contols selection and build it up again. It works now :)
  16. Hm... I still have the same problem after downloading the new source. The row seems to be deleted, it disappears when clicking the delete-button, but on saving the page the row returns. Seems there's some stateinformation that is not being updated on delete. The same goes for moving rows up and down. When saving the page, the rows return to original index.
  17. Hi Sorry, didnt test enought. Was a problem with some of the interfaces multiprop implements that resultet in that the property collection existed before the control class called the property collection. Added some code to handle this.
  18. You have amazing responsetime :) Thank you so much, this is great!
  19. Hi Anders! Have you tried to use the PropertyLinkCollection in a PropertyMultiBase after the hotfix for multiple linkcollections (http://world.episerver.com/Forum/Pages/Thread.aspx?id=24739&epslanguage=en) came? I have a Property inheriting your PropertyMultiBase that contains PropertyLinkCollections. It worked fine before, but after installing the hotfix (which I needed because I have several regular LinkCollections other places, they now work fine), my custom property no longer works. In editmode, when I click to add a new Link in a LinkCollection within my custom property (adding the LinkCollections is no problem), I get two javascript-errors saying "Expected '('" and "Expected ';'". Do you think this is something that can be solved in your project, or is it something episerver must fix in their LinkCollection?
  20. I was adding the PropertyLinkCollection to my PropertyDataCollection with a name, that didn't work. I had to add it to my PropertyDataCollection without a name, then it worked :)
  21. Hi I have one question Is it possible to have the rich text editor displayed in edit mode? For example lets say that in PropertyLinkAndName.cs I add this line innerPropertyCollection.Add("urldescription", new PropertyXhtmlString()); But from what i see I only get a textbox for this property... Any ideas if this is possible? Thanks
  22. Hi Thats possible, but you have to set the EditorToolOptions on the property before adding it. There is also an issue with the html and the tools. They are added in a table and the td inherit the width from the outer table. therfore it looks a bit crappy.... PropertyTextBox box = new PropertyTextBox(); box.EditorToolOptions = EditorToolOption.InsertUrl; box.Width = 400; box.Height = 500; box.RowLayout = TableRowLayout.Wide;
  23. There is also a new override you can use to set different style and stuff on your sub properties. Sorry for crappy formating, but new line dosnt work in here: public override void EditSetPanelStyle(Panel panel) { panel.Attributes.CssStyle.Add("float", "left"); //panel.Attributes.CssStyle.Add("border", "1px solid black"); panel.Attributes.CssStyle.Add("width", "200px"); panel.CssClass = "nopadding"; Literal l = new Literal(); l.Text = @" .nopadding td {padding:0 0 0 0;margin:0 0 0 0;border-bottom:none;} .nopadding .episize500 {width:200px;} "; panel.Controls.Add(l); }
  24. Heres the property with 2 text box'es public class TwoBoxContainer : PropertySingleBase { public TwoBoxContainer() { this.EditOption[EditOptions.ShowWideLayout] = true; this.EditOption[EditOptions.EachItemInDiv] = true; } public override void EditSetPanelStyle(Panel panel) { panel.Attributes.CssStyle.Add("float", "left"); //panel.Attributes.CssStyle.Add("border", "1px solid black"); panel.Attributes.CssStyle.Add("width", "200px"); panel.CssClass = "nopadding"; Literal l = new Literal(); l.Text = @" .nopadding td {padding:0 0 0 0;margin:0 0 0 0;border-bottom:none;} .nopadding .episize500 {width:200px;} "; panel.Controls.Add(l); } PropertyTextBox CreateBox() { PropertyTextBox box = new PropertyTextBox(); box.EditorToolOptions = EditorToolOption.InsertUrl | EditorToolOption.InsertImage | EditorToolOption.DynamicContent; box.Width = 200; box.Height = 130; box.RowLayout = TableRowLayout.Wide; return box; } protected override PropertyDataCollection InnerPropertyCollection { get { if (base.InnerPropertyCollection == null) { PropertyDataCollection _new = new PropertyDataCollection(); _new.Add("box1", CreateBox()); _new.Add("box2", CreateBox()); base.InnerPropertyCollection = _new; } return base.InnerPropertyCollection; } set { base.InnerPropertyCollection = value; } } }
  25. thanks for the answer i was able to add the editor
  26. I'm using the "Combine static list with dynamic list" and I'm trying to fill the list programatically. What is the easiest way? I can't seem to figure it out. Excellent work, by the way :)
  27. if there is a dynamic list called Contacts (see example above) you can add elements by using Contacts.PropertyCollection.Add(new Contact());
  28. The retrive property values take a look at the the code here http://labs.episerver.com/en/Blogs/Anders-Hattestad/Dates/2008/11/ltEPiServerProperty-on-steroidsgt/
  29. Heya, Been sitting here playing abit around with this, and it really looks amazing.. But one thing have been causing me a bit of troubles.. hehe As i couldnt get my own DynamicMultiProperty to Store data, i falled back on the Contac and Contacts properties - Seemed like only the first defined Property(in the ProperyDataCollection) would be saved when clicking "Save".. How ever when clicing "Save and Publish" all seem to be saved fine Any idea what is going on ? got the .dll from 2009-20-19. Regards, Klaus
  30. Have you downloaded the latest source?
  31. Hmm.. What is the latest build date ? I got one from 2008-10-19, but I imagine that is a old one(miss wrote date in previous post). Downloaded it at: https://www.coderesort.com/p/epicode/raw-attachment/wiki/Itera.MultiProperty/Itera.MultiProperty.zip
  32. Hi! I saw in the earlier comments that there should be some example files somewhere, where can I find them? All I get see in the zipped dll-file. Thanks
  33. there is a blog post here http://labs.episerver.com/en/Blogs/Anders-Hattestad/Dates/2008/11/ltEPiServerProperty-on-steroidsgt/ where there are some examples of usages
  34. I am using Itera Multiproperty to set up a simple property which consists of Tilte (PropertyString) and Link Collection (PropertyLinkCollection). The problem is when adding a new link to link collection from the site. It throws the following error: '=' is an unexpected token. The expected token is ';'. If an external link is added, i.e. google.com all is good and no errors. I think it something to do with multiple query strings being added separated with the ‘&’ sign. Any help is much appreciated. Dmitri
  35. Hi Anders. I've got the itera module but I don't really understand how to implement it in on my solution. I am trying to implement PropertyContact.cs however I don't know what to add to ApplyEditChanges and CreateEditControls do you have a full mini sample I can check? Many thanks for your help
Post a comment    
User verification Image for user verification  
EPiTrace logger