diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListDataEditor.cs b/components/editorControls/XPathDropDownList/XPathDropDownListDataEditor.cs
new file mode 100644
index 0000000000..fe7078c8ed
--- /dev/null
+++ b/components/editorControls/XPathDropDownList/XPathDropDownListDataEditor.cs
@@ -0,0 +1,149 @@
+using System;
+using System.Linq;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using umbraco;
+using umbraco.BusinessLogic;
+using umbraco.cms.businesslogic;
+using umbraco.cms.businesslogic.datatype;
+using umbraco.cms.businesslogic.property;
+using umbraco.cms.businesslogic.web;
+using umbraco.interfaces;
+
+namespace umbraco.editorControls.XPathDropDownList
+{
+ ///
+ /// XPath configurabale DropDownList Data Type
+ ///
+ public class XPathDropDownListDataEditor : CompositeControl, IDataEditor
+ {
+ ///
+ /// Field for the data.
+ ///
+ private IData m_Data;
+
+ ///
+ /// Field for the options.
+ ///
+ private XPathDropDownListOptions m_Options;
+
+ ///
+ /// Field for the CustomValidator.
+ ///
+ private CustomValidator m_CustomValidator = new CustomValidator();
+
+ ///
+ /// Field for the DropDownList.
+ ///
+ private DropDownList m_DropDownList = new DropDownList();
+
+ ///
+ /// Gets a value indicating whether [treat as rich text editor].
+ ///
+ ///
+ /// true if [treat as rich text editor]; otherwise, false.
+ ///
+ public virtual bool TreatAsRichTextEditor
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether [show label].
+ ///
+ /// true if [show label]; otherwise, false.
+ public virtual bool ShowLabel
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets the editor.
+ ///
+ /// The editor.
+ public Control Editor
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of XPathCheckBoxListDataEditor
+ ///
+ ///
+ ///
+ internal XPathDropDownListDataEditor(IData data, XPathDropDownListOptions options)
+ {
+ this.m_Data = data;
+ this.m_Options = options;
+ }
+
+ ///
+ /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
+ ///
+ protected override void CreateChildControls()
+ {
+ this.m_DropDownList.DataSource = uQuery.GetNodesByXPath(this.m_Options.XPath).ToNameIds();
+ this.m_DropDownList.DataTextField = "Value";
+ this.m_DropDownList.DataValueField = this.m_Options.UseId ? "Key" : "Value";
+ this.m_DropDownList.DataBind();
+
+ // Add a default please select value
+ this.m_DropDownList.Items.Insert(0, new ListItem(string.Empty, "-1"));
+
+ this.Controls.Add(this.m_CustomValidator);
+ this.Controls.Add(this.m_DropDownList);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The object that contains the event data.
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+ this.EnsureChildControls();
+
+ if (!this.Page.IsPostBack)
+ {
+ // Get selected items from Node Name or Node Id
+ var dropDownListItem = this.m_DropDownList.Items.FindByValue(this.m_Data.Value.ToString());
+ if (dropDownListItem != null)
+ {
+ dropDownListItem.Selected = true;
+ }
+ }
+ }
+
+ ///
+ /// Called by Umbraco when saving the node
+ ///
+ public void Save()
+ {
+ Property property = new Property(((DefaultData)this.m_Data).PropertyId);
+ if (property.PropertyType.Mandatory && this.m_DropDownList.SelectedValue == "-1")
+ {
+ // Property is mandatory, but no value selected in the DropDownList
+ this.m_CustomValidator.IsValid = false;
+
+ DocumentType documentType = new DocumentType(property.PropertyType.ContentTypeId);
+ ContentType.TabI tab = documentType.getVirtualTabs.Where(x => x.Id == property.PropertyType.TabId).FirstOrDefault();
+
+ if (tab != null)
+ {
+ this.m_CustomValidator.ErrorMessage = ui.Text("errorHandling", "errorMandatory", new string[] { property.PropertyType.Alias, tab.Caption }, User.GetCurrent());
+ }
+ }
+
+ this.m_Data.Value = this.m_DropDownList.SelectedValue;
+ }
+ }
+}
diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListDataType.cs b/components/editorControls/XPathDropDownList/XPathDropDownListDataType.cs
new file mode 100644
index 0000000000..6426b171d3
--- /dev/null
+++ b/components/editorControls/XPathDropDownList/XPathDropDownListDataType.cs
@@ -0,0 +1,101 @@
+using System;
+using umbraco.cms.businesslogic.datatype;
+using umbraco.interfaces;
+
+namespace umbraco.editorControls.XPathDropDownList
+{
+ ///
+ ///
+ ///
+ public class XPathDropDownListDataType : umbraco.cms.businesslogic.datatype.BaseDataType, IDataType
+ {
+ ///
+ ///
+ ///
+ private XPathDropDownListPreValueEditor preValueEditor;
+
+ ///
+ ///
+ ///
+ private IDataEditor dataEditor;
+
+ ///
+ ///
+ ///
+ private IData data;
+
+ ///
+ /// Gets the name of the data type.
+ ///
+ /// The name of the data type.
+ public override string DataTypeName
+ {
+ get
+ {
+ return "XPath DropDownList";
+ }
+ }
+
+ ///
+ /// Gets the id.
+ ///
+ /// The id.
+ public override Guid Id
+ {
+ get
+ {
+ return new Guid(DataTypeGuids.XPathDropDownListId);
+ }
+ }
+
+ ///
+ /// Lazy load the associated PreValueEditor instance,
+ /// this is constructed supplying 'this'
+ ///
+ public override IDataPrevalue PrevalueEditor
+ {
+ get
+ {
+ if (this.preValueEditor == null)
+ {
+ this.preValueEditor = new XPathDropDownListPreValueEditor(this);
+ }
+
+ return this.preValueEditor;
+ }
+ }
+
+ ///
+ /// Lazy load the assocated DataEditor,
+ /// this is constructed supplying the data value stored by the PreValueEditor, and also the configuration settings of the PreValueEditor
+ ///
+ public override IDataEditor DataEditor
+ {
+ get
+ {
+ if (this.dataEditor == null)
+ {
+ this.dataEditor = new XPathDropDownListDataEditor(this.Data, ((XPathDropDownListPreValueEditor)this.PrevalueEditor).Options);
+ }
+
+ return this.dataEditor;
+ }
+ }
+
+ ///
+ /// Lazy load an empty DefaultData object, this is used to pass data between the PreValueEditor and the DataEditor
+ ///
+ public override IData Data
+ {
+ get
+ {
+ if (this.data == null)
+ {
+ this.data = new umbraco.cms.businesslogic.datatype.DefaultData(this);
+ }
+
+ return this.data;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListOptions.cs b/components/editorControls/XPathDropDownList/XPathDropDownListOptions.cs
new file mode 100644
index 0000000000..514fbfca90
--- /dev/null
+++ b/components/editorControls/XPathDropDownList/XPathDropDownListOptions.cs
@@ -0,0 +1,25 @@
+
+namespace umbraco.editorControls.XPathDropDownList
+{
+ internal class XPathDropDownListOptions
+ {
+ ///
+ /// XPath string used to get Nodes to be used as CheckBox options in a CheckBoxList
+ ///
+ public string XPath { get; set; }
+
+ ///
+ /// Defaults to true, where property value is a csv of NodeIds, else if false, then csv of Node names is stored
+ ///
+ public bool UseId { get; set; }
+
+ ///
+ /// Initializes an instance of XPathDropDownListOptions
+ ///
+ public XPathDropDownListOptions()
+ {
+ this.XPath = string.Empty;
+ this.UseId = true; // Default to storing Node Id
+ }
+ }
+}
diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListPreValueEditor.cs b/components/editorControls/XPathDropDownList/XPathDropDownListPreValueEditor.cs
new file mode 100644
index 0000000000..ea64d8f4a4
--- /dev/null
+++ b/components/editorControls/XPathDropDownList/XPathDropDownListPreValueEditor.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Xml.XPath;
+// using uComponents.DataTypes.Shared.Extensions;
+// using uComponents.DataTypes.Shared.PrevalueEditors;
+using umbraco.cms.businesslogic.datatype;
+
+namespace umbraco.editorControls.XPathDropDownList
+{
+ class XPathDropDownListPreValueEditor : AbstractJsonPrevalueEditor
+ {
+ ///
+ /// TextBox control to get the XPath expression
+ ///
+ private TextBox xPathTextBox = new TextBox();
+
+ ///
+ /// RequiredFieldValidator to ensure an XPath expression has been entered
+ ///
+ private RequiredFieldValidator xPathRequiredFieldValidator = new RequiredFieldValidator();
+
+ ///
+ /// Server side validation of XPath expression, to ensure some nodes are returned
+ ///
+ private CustomValidator xPathCustomValidator = new CustomValidator();
+
+ ///
+ /// Drop Down List to pick either Node Name or Node Id
+ ///
+ private DropDownList valueTypeDropDownList = new DropDownList();
+
+ ///
+ /// Data object used to define the configuration status of this PreValueEditor
+ ///
+ private XPathDropDownListOptions options = null;
+
+ ///
+ /// Gets the options data object that represents the current state of this datatypes configuration
+ ///
+ internal XPathDropDownListOptions Options
+ {
+ get
+ {
+ if (this.options == null)
+ {
+ // Deserialize any stored settings for this PreValueEditor instance
+ this.options = this.GetPreValueOptions();
+
+ // If still null, ie, object couldn't be de-serialized from PreValue[0] string value
+ if (this.options == null)
+ {
+ // Create a new Options data object with the default values
+ this.options = new XPathDropDownListOptions();
+ }
+ }
+ return this.options;
+ }
+ }
+
+ ///
+ /// Initialize a new instance of XPathCheckBoxlistPreValueEditor
+ ///
+ /// XPathCheckBoxListDataType
+ public XPathDropDownListPreValueEditor(umbraco.cms.businesslogic.datatype.BaseDataType dataType)
+ : base(dataType, umbraco.cms.businesslogic.datatype.DBTypes.Nvarchar)
+ {
+ }
+
+ ///
+ /// Creates all of the controls and assigns all of their properties
+ ///
+ protected override void CreateChildControls()
+ {
+ this.xPathTextBox.ID = "xPathTextBox";
+ this.xPathTextBox.CssClass = "umbEditorTextField";
+
+ this.xPathRequiredFieldValidator.ControlToValidate = this.xPathTextBox.ID;
+ this.xPathRequiredFieldValidator.Display = ValidatorDisplay.Dynamic;
+ this.xPathRequiredFieldValidator.ErrorMessage = " XPath expression required";
+
+ this.xPathCustomValidator.ControlToValidate = this.xPathTextBox.ID;
+ this.xPathCustomValidator.Display = ValidatorDisplay.Dynamic;
+ this.xPathCustomValidator.ServerValidate += new ServerValidateEventHandler(XPathCustomValidator_ServerValidate);
+
+ this.valueTypeDropDownList.ID = "valueTypeDropDownList";
+ this.valueTypeDropDownList.Items.Add(new ListItem("Node Id", bool.TrueString));
+ this.valueTypeDropDownList.Items.Add(new ListItem("Node Name", bool.FalseString));
+
+ this.Controls.Add(this.xPathTextBox);
+ this.Controls.Add(this.xPathRequiredFieldValidator);
+ this.Controls.Add(this.xPathCustomValidator);
+ this.Controls.Add(this.valueTypeDropDownList);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+
+ //if (!this.Page.IsPostBack)
+ //{
+ // Read in stored configuration values
+ this.xPathTextBox.Text = this.Options.XPath;
+ this.valueTypeDropDownList.SelectedValue = this.Options.UseId.ToString();
+ //}
+ }
+
+ ///
+ /// Will run the entered XPath expression to ensure it returns at least 1 node
+ ///
+ /// xPathCustomValidator
+ ///
+ private void XPathCustomValidator_ServerValidate(object source, ServerValidateEventArgs args)
+ {
+ string xPath = args.Value;
+ bool isValid = false;
+
+ try
+ {
+ if (uQuery.GetNodesByXPath(xPath).Count >= 0)
+ {
+ isValid = true;
+ }
+ }
+ catch (XPathException)
+ {
+ this.xPathCustomValidator.ErrorMessage = " Syntax error in XPath expression";
+ }
+
+ args.IsValid = isValid;
+ }
+
+ ///
+ /// Saves the pre value data to Umbraco
+ ///
+ public override void Save()
+ {
+ if (this.Page.IsValid)
+ {
+ this.Options.XPath = this.xPathTextBox.Text;
+ this.Options.UseId = bool.Parse(this.valueTypeDropDownList.SelectedValue);
+
+ this.SaveAsJson(this.Options); // Serialize to Umbraco database field
+ }
+ }
+
+ ///
+ /// Replaces the base class writer and instead uses the shared uComponents extension method, to inject consistant markup
+ ///
+ ///
+ protected override void RenderContents(HtmlTextWriter writer)
+ {
+ writer.AddPrevalueRow("XPath Expression", this.xPathTextBox, this.xPathRequiredFieldValidator, this.xPathCustomValidator);
+ writer.AddPrevalueRow("Value", this.valueTypeDropDownList);
+ }
+
+ }
+}
\ No newline at end of file