diff --git a/umbraco/cms/businesslogic/datatype/AbstractJsonPrevalueEditor.cs b/umbraco/cms/businesslogic/datatype/AbstractJsonPrevalueEditor.cs
new file mode 100644
index 0000000000..72b91dcb5d
--- /dev/null
+++ b/umbraco/cms/businesslogic/datatype/AbstractJsonPrevalueEditor.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Web.Script.Serialization;
+using umbraco.BusinessLogic;
+using umbraco.cms.businesslogic.datatype;
+
+namespace umbraco.cms.businesslogic.datatype
+{
+ ///
+ /// Abstract class for the PreValue Editor.
+ /// Specifically designed to serialize/deserialize the options as JSON.
+ ///
+ public abstract class AbstractJsonPrevalueEditor : AbstractPrevalueEditor
+ {
+ ///
+ /// The underlying base data-type.
+ ///
+ protected readonly BaseDataType m_DataType;
+
+ ///
+ /// An object to temporarily lock writing to the database.
+ ///
+ private static readonly object m_Locker = new object();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ public AbstractJsonPrevalueEditor(BaseDataType dataType)
+ {
+ this.m_DataType = dataType;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ /// Type of the database field.
+ public AbstractJsonPrevalueEditor(BaseDataType dataType, DBTypes dbType)
+ : base()
+ {
+ this.m_DataType = dataType;
+ this.m_DataType.DBType = dbType;
+ }
+
+ ///
+ /// Gets the PreValue options for the data-type.
+ ///
+ /// The type of the resulting object.
+ ///
+ /// Returns the options for the PreValue Editor
+ ///
+ public T GetPreValueOptions()
+ {
+ var prevalues = PreValues.GetPreValues(this.m_DataType.DataTypeDefinitionId);
+ if (prevalues.Count > 0)
+ {
+ var prevalue = (PreValue)prevalues[0];
+ if (!string.IsNullOrEmpty(prevalue.Value))
+ {
+ try
+ {
+ // deserialize the options
+ var serializer = new JavaScriptSerializer();
+
+ // return the options
+ return serializer.Deserialize(prevalue.Value);
+ }
+ catch (Exception ex)
+ {
+ Log.Add(LogTypes.Error, this.m_DataType.DataTypeDefinitionId, string.Concat("uComponents: Execption thrown: ", ex.Message));
+ }
+ }
+ }
+
+ // if all else fails, return default options
+ return default(T);
+ }
+
+ ///
+ /// Saves the data-type PreValue options.
+ ///
+ public void SaveAsJson(object options)
+ {
+ // serialize the options into JSON
+ var serializer = new JavaScriptSerializer();
+ var json = serializer.Serialize(options);
+
+ lock (m_Locker)
+ {
+ var prevalues = PreValues.GetPreValues(this.m_DataType.DataTypeDefinitionId);
+ if (prevalues.Count > 0)
+ {
+ PreValue prevalue = (PreValue)prevalues[0];
+
+ // update
+ prevalue.Value = json;
+ prevalue.Save();
+ }
+ else
+ {
+ // insert
+ PreValue.MakeNew(this.m_DataType.DataTypeDefinitionId, json);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/datatype/AbstractOptions.cs b/umbraco/cms/businesslogic/datatype/AbstractOptions.cs
new file mode 100644
index 0000000000..13443dda96
--- /dev/null
+++ b/umbraco/cms/businesslogic/datatype/AbstractOptions.cs
@@ -0,0 +1,42 @@
+using System.ComponentModel;
+
+namespace umbraco.cms.businesslogic.datatype
+{
+ ///
+ /// Abstract class for the Prevalue Editor options.
+ ///
+ public abstract class AbstractOptions
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AbstractOptions()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true [load defaults].
+ public AbstractOptions(bool loadDefaults)
+ : this()
+ {
+ if (loadDefaults)
+ {
+ // get the type of the object.
+ var type = this.GetType();
+
+ // iterate through the properties.
+ foreach (var property in type.GetProperties())
+ {
+ // iterate through the DefaultValue attributes.
+ foreach (DefaultValueAttribute attribute in property.GetCustomAttributes(typeof(DefaultValueAttribute), true))
+ {
+ // set the default value of the property.
+ property.SetValue(this, attribute.Value, null);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/datatype/AbstractPrevalueEditor.cs b/umbraco/cms/businesslogic/datatype/AbstractPrevalueEditor.cs
new file mode 100644
index 0000000000..cfe71cd5f1
--- /dev/null
+++ b/umbraco/cms/businesslogic/datatype/AbstractPrevalueEditor.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using ClientDependency.Core;
+using umbraco.interfaces;
+
+namespace umbraco.cms.businesslogic.datatype
+{
+ ///
+ /// Abstract class for the PreValue Editor.
+ ///
+ public abstract class AbstractPrevalueEditor : WebControl, IDataPrevalue
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AbstractPrevalueEditor()
+ : base()
+ {
+ }
+
+ ///
+ /// Gets the editor.
+ ///
+ /// The editor.
+ public virtual Control Editor
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ ///
+ /// Saves this instance.
+ ///
+ public virtual void Save()
+ {
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// An object that contains the event data.
+ protected override void OnInit(EventArgs e)
+ {
+ base.OnInit(e);
+ this.EnsureChildControls();
+
+ // Adds the client dependencies.
+ this.AddResourceToClientDependency("uComponents.DataTypes.Shared.Resources.Styles.PrevalueEditor.css", ClientDependencyType.Css);
+ }
+
+ ///
+ /// Renders the HTML opening tag of the control to the specified writer. This method is used primarily by control developers.
+ ///
+ /// A that represents the output stream to render HTML content on the client.
+ public override void RenderBeginTag(HtmlTextWriter writer)
+ {
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, "uComponents");
+ writer.RenderBeginTag(HtmlTextWriterTag.Div);
+
+ base.RenderBeginTag(writer);
+ }
+
+ ///
+ /// Renders the HTML closing tag of the control into the specified writer. This method is used primarily by control developers.
+ ///
+ /// A that represents the output stream to render HTML content on the client.
+ public override void RenderEndTag(HtmlTextWriter writer)
+ {
+ base.RenderEndTag(writer);
+
+ writer.RenderEndTag();
+ }
+ }
+}
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/datatype/CsvToXmlData.cs b/umbraco/cms/businesslogic/datatype/CsvToXmlData.cs
new file mode 100644
index 0000000000..28545aa912
--- /dev/null
+++ b/umbraco/cms/businesslogic/datatype/CsvToXmlData.cs
@@ -0,0 +1,96 @@
+using System.Xml;
+using umbraco;
+using umbraco.cms.businesslogic.datatype;
+
+namespace umbraco.cms.businesslogic.datatype
+{
+ ///
+ /// Overrides the object to return the value as XML.
+ ///
+ public class CsvToXmlData : DefaultData
+ {
+ ///
+ /// The separators to split the delimited string.
+ ///
+ private string[] separator;
+
+ ///
+ /// Name for the root node.
+ ///
+ private string rootName;
+
+ ///
+ /// Name for the element/node that contains the value.
+ ///
+ private string elementName;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ public CsvToXmlData(BaseDataType dataType)
+ : this(dataType, "values")
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ /// Name of the root.
+ public CsvToXmlData(BaseDataType dataType, string rootName)
+ : this(dataType, rootName, "value")
+ {
+ }
+
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ /// Name of the root.
+ /// Name of the element.
+ public CsvToXmlData(BaseDataType dataType, string rootName, string elementName)
+ : this(dataType, rootName, elementName, new[] { "," })
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ /// Name of the root.
+ /// Name of the element.
+ /// The separator.
+ public CsvToXmlData(BaseDataType dataType, string rootName, string elementName, string[] separator)
+ : base(dataType)
+ {
+ this.rootName = rootName;
+ this.elementName = elementName;
+ this.separator = separator;
+ }
+
+ ///
+ /// Converts the data value to XML.
+ ///
+ /// The data to convert to XML.
+ /// Returns the data value as an XmlNode
+ public override XmlNode ToXMl(XmlDocument data)
+ {
+ // check that the value isn't null
+ if (this.Value != null)
+ {
+ // split the CSV data into an XML document.
+ var xml = xmlHelper.Split(new XmlDocument(), this.Value.ToString(), this.separator, this.rootName, this.elementName);
+
+ // return the XML node.
+ return data.ImportNode(xml.DocumentElement, true);
+ }
+ else
+ {
+ // otherwise render the value as default (in CDATA)
+ return base.ToXMl(data);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/datatype/PrevalueEditorExtensions.cs b/umbraco/cms/businesslogic/datatype/PrevalueEditorExtensions.cs
new file mode 100644
index 0000000000..a704c3b5f6
--- /dev/null
+++ b/umbraco/cms/businesslogic/datatype/PrevalueEditorExtensions.cs
@@ -0,0 +1,105 @@
+using System.Web.UI;
+using System.Web.UI.HtmlControls;
+using System.Web.UI.WebControls;
+
+namespace umbraco.cms.businesslogic.datatype
+{
+ ///
+ /// Extension methods for the Prevalue Editor
+ ///
+ public static class PrevalueEditorExtensions
+ {
+ ///
+ /// Adds the prevalue controls.
+ ///
+ /// The collection.
+ /// The controls.
+ public static void AddPrevalueControls(this ControlCollection collection, params Control[] controls)
+ {
+ foreach (var control in controls)
+ {
+ collection.Add(control);
+ }
+ }
+
+ ///
+ /// Adds the prevalue row heading.
+ ///
+ /// The writer.
+ /// The heading.
+ public static void AddPrevalueHeading(this HtmlTextWriter writer, string heading)
+ {
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, "row clearfix");
+ writer.RenderBeginTag(HtmlTextWriterTag.Div); // start 'row'
+
+ writer.RenderBeginTag(HtmlTextWriterTag.H3); // start 'h3'
+
+ writer.Write(heading);
+
+ writer.RenderEndTag(); // end 'h3'
+
+ writer.RenderEndTag(); // end 'row'
+ }
+
+ ///
+ /// Adds a new row to the Prevalue Editor.
+ ///
+ /// The HtmlTextWriter.
+ /// The label for the field.
+ /// The controls for the field.
+ public static void AddPrevalueRow(this HtmlTextWriter writer, string label, params Control[] controls)
+ {
+ writer.AddPrevalueRow(label, string.Empty, controls);
+ }
+
+ ///
+ /// Adds a new row to the Prevalue Editor, (with an optional description).
+ ///
+ /// The HtmlTextWriter.
+ /// The label for the field.
+ /// The description for the field.
+ /// The controls for the field.
+ public static void AddPrevalueRow(this HtmlTextWriter writer, string label, string description, params Control[] controls)
+ {
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, "row clearfix");
+ writer.RenderBeginTag(HtmlTextWriterTag.Div); // start 'row'
+
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, "label");
+ writer.RenderBeginTag(HtmlTextWriterTag.Div); // start 'label'
+
+ var lbl = new HtmlGenericControl("label") { InnerText = label };
+
+ if (controls.Length > 0 && !string.IsNullOrEmpty(controls[0].ClientID))
+ {
+ lbl.Attributes.Add("for", controls[0].ClientID);
+ }
+
+ lbl.RenderControl(writer);
+
+ writer.RenderEndTag(); // end 'label'
+
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, "field");
+ writer.RenderBeginTag(HtmlTextWriterTag.Div); // start 'field'
+
+ foreach (var control in controls)
+ {
+ control.RenderControl(writer);
+ }
+
+ writer.RenderEndTag(); // end 'field'
+
+ if (!string.IsNullOrEmpty(description))
+ {
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, "description");
+ writer.RenderBeginTag(HtmlTextWriterTag.Div); // start 'description'
+
+ Label desc = new Label() { Text = description };
+ desc.RenderControl(writer);
+
+ writer.RenderEndTag(); // end 'description'
+ }
+
+ writer.RenderEndTag(); // end 'row'
+ }
+ }
+}
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/datatype/XmlData.cs b/umbraco/cms/businesslogic/datatype/XmlData.cs
new file mode 100644
index 0000000000..406dabcb99
--- /dev/null
+++ b/umbraco/cms/businesslogic/datatype/XmlData.cs
@@ -0,0 +1,44 @@
+using System.Xml;
+using umbraco.cms.businesslogic.datatype;
+
+namespace umbraco.cms.businesslogic.datatype
+{
+ ///
+ /// Overrides the object to return the value as XML.
+ ///
+ public class XmlData : DefaultData
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ public XmlData(BaseDataType dataType)
+ : base(dataType)
+ {
+ }
+
+ ///
+ /// Converts the data value to XML.
+ ///
+ /// The data to convert to XML.
+ ///
+ public override XmlNode ToXMl(XmlDocument data)
+ {
+ // check that the value isn't null and starts with an opening angle-bracket.
+ if (this.Value != null && xmlHelper.CouldItBeXml(this.Value.ToString()))
+ {
+ // load the value into an XML document.
+ var xd = new XmlDocument();
+ xd.LoadXml(this.Value.ToString());
+
+ // return the XML node.
+ return data.ImportNode(xd.DocumentElement, true);
+ }
+ else
+ {
+ // otherwise render the value as default (in CDATA)
+ return base.ToXMl(data);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/umbraco/cms/umbraco.cms.csproj b/umbraco/cms/umbraco.cms.csproj
index 8582d789cd..aa08616d8d 100644
--- a/umbraco/cms/umbraco.cms.csproj
+++ b/umbraco/cms/umbraco.cms.csproj
@@ -200,7 +200,11 @@
+
+
+
+
@@ -208,6 +212,9 @@
+
+
+