added Picker Relations datatype - previously uComponents: MultiPicker Relations (renamed as can work with single item pickers as well as multipickers)

This commit is contained in:
Hendy@Blueberry
2012-05-30 22:13:18 -01:00
parent 8439bafcf4
commit 04267d2c6e
7 changed files with 913 additions and 0 deletions

View File

@@ -0,0 +1,264 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using umbraco.cms.businesslogic.datatype; // DefaultData
using umbraco.cms.businesslogic.property; // Property
using umbraco.cms.businesslogic.relation; // RelationType
using umbraco.interfaces; // IDataEditor
using UmbracoContent = umbraco.cms.businesslogic.Content; // UmbracoContent defined here so as to differentiate with System.Web.UI.WebControls.Content
namespace umbraco.editorControls.PickerRelations
{
/// <summary>
///
/// </summary>
public class PickerRelationsDataEditor : CompositeControl, IDataEditor
{
/// <summary>
/// value stored by a datatype instance
/// </summary>
private IData data;
/// <summary>
/// configuration options for this datatype, as defined by the PreValueEditor
/// </summary>
private PickerRelationsOptions options;
/// <summary>
/// Literal used to render status (Enabled || Disabled)
/// this datatype is only enabled and active if it can find the property alias on the current node (as defined in PreValueEditor) and
/// the relation type parent object type (or child if reverse index used) matches the object type of the current node which this datatype is on
/// </summary>
private Literal statusLiteral = new Literal();
private Literal jsLiteral = new Literal();
/// <summary>
/// Gets a value indicating whether this is an RTE - this Property expected by Umbraco
/// </summary>
public virtual bool TreatAsRichTextEditor
{
get { return false; }
}
/// <summary>
/// Gets a value indicating whether the label should be shown when editing - this Property exected by Umbraco
/// </summary>
public virtual bool ShowLabel
{
get { return true; }
}
/// <summary>
/// Gets the DataEditor - Property expected by Umbraco
/// </summary>
public Control Editor { get { return this; } }
/// <summary>
/// Gets the id of the current (content || media || member) node on which this datatype is a property
/// </summary>
private int CurrentContentId
{
get
{
return ((umbraco.cms.businesslogic.datatype.DefaultData)this.data).NodeId;
}
}
/// <summary>
/// Gets the UmbracoObjectType on which this datatype is a property of
/// </summary>
private uQuery.UmbracoObjectType CurrentContextObjectType
{
get
{
return uQuery.GetUmbracoObjectType(
uQuery.SqlHelper.ExecuteScalar<Guid>(
"SELECT nodeObjectType FROM umbracoNode WHERE id = @id",
uQuery.SqlHelper.CreateParameter("@id", this.CurrentContentId)));
}
}
/////// NOT CURRENTLY USED, BUT MIGHT BE USEFUL TO MARK BIDIRECTIONAL RELATIONS
/////// <summary>
/////// string to identify a particular instance of this datatype
/////// </summary>
////private string InstanceIdentifier
////{
//// get
//// {
//// Property pickerRelationsProperty = new Property(((DefaultData)this.data).PropertyId);
//// return "[" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";
//// }
////}
/// <summary>
/// Initializes a new instance of PickerRelationsDataEditor
/// </summary>
/// <param name="data">data stored by this instance of this datatype (not currently used)</param>
/// <param name="options">configuration options for this datatype as set by the PreValueEditor</param>
internal PickerRelationsDataEditor(IData data, PickerRelationsOptions options)
{
this.data = data;
this.options = options;
}
/// <summary>
/// Creates the child controls
/// </summary>
protected override void CreateChildControls()
{
this.statusLiteral.ID = "pickerRelations";
this.Controls.Add(this.statusLiteral); // displays if this datatype is valid in this context, and if so, which pickerProperty and relationtype it wires up
this.Controls.Add(this.jsLiteral);
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.EnsureChildControls();
this.statusLiteral.Text = "<span id=\"" + this.statusLiteral.ClientID + "\">";
try
{
this.statusLiteral.Text += "Mapping: " + this.GetMappingDetails();
}
catch(Exception ex)
{
this.statusLiteral.Text += "Error: " + ex.Message;
}
this.statusLiteral.Text += "</span>";
if (this.options.HideDataEditor)
{
this.jsLiteral.Text = @"
<script type=""text/javascript"">
jQuery(document).ready(function () {
jQuery('span#" + this.statusLiteral.ClientID + @"').parents('div.propertypane').first().hide();
});
</script>";
}
}
/// <summary>
/// Called by Umbraco when saving the node, this datatype doens't do anythign here, but with an event handler instead,
/// as needs to know the saved values of a sibling pickerProperty
/// </summary>
public void Save()
{
}
/// <summary>
/// returns a string "Property '[propertyAlias]' with RelationType '[relationTypeName]"
/// </summary>
/// <returns></returns>
private string GetMappingDetails()
{
string mappingDetails = string.Empty;
UmbracoContent currentContentNode = new UmbracoContent(this.CurrentContentId);
Property pickerProperty = currentContentNode.getProperty(this.options.PropertyAlias);
if (pickerProperty != null)
{
RelationType relationType = new RelationType(this.options.RelationTypeId); // Does it still exist ? TODO: check
if (this.IsContextUmbracoObjectTypeValid(this.CurrentContextObjectType, relationType))
{
mappingDetails = "Property '<strong>" + pickerProperty.PropertyType.Name + "</strong>' with " +
"Relation Type '<strong>" + relationType.Name + "</strong>'";
if(this.options.ReverseIndexing)
{
mappingDetails += " <i>(Reverse Index)</i>";
}
}
else
{
throw new Exception("Conflict with this Content Object Type and that expected by the Relation Type '" + relationType.Name + "'");
}
}
else
{
throw new Exception("Can't find a Property with the Alias '" + this.options.PropertyAlias + "'");
}
return mappingDetails;
}
/// <summary>
/// returns the UmbracoObjectType associated as defined by the supplied relation type, and if reverse indexing has been enabled
/// </summary>
/// <param name="relationType">associated RealationType</param>
/// <returns></returns>
public uQuery.UmbracoObjectType GetPickerUmbracoObjectType(RelationType relationType)
{
uQuery.UmbracoObjectType pickerUmbracoObjectType = uQuery.UmbracoObjectType.Unknown;
if (!relationType.Dual && this.options.ReverseIndexing)
{
pickerUmbracoObjectType = relationType.GetParentUmbracoObjectType();
}
else
{
pickerUmbracoObjectType = relationType.GetChildUmbracoObjectType();
}
return pickerUmbracoObjectType;
}
/// <summary>
/// Check to see if the content id side of the relation type is valid (doesn't check the node picker id side)
/// </summary>
/// <param name="contextUmbracoObjectType">Type of the content object (content/ media or member)</param>
/// <param name="relationType">Type of the relation.</param>
/// <returns>
/// <c>true</c> if [is content object type valid] [the specified content object type]; otherwise, <c>false</c>.
/// </returns>
public bool IsContextUmbracoObjectTypeValid(uQuery.UmbracoObjectType contextUmbracoObjectType, RelationType relationType)
{
bool isContextObjectTypeValid = false;
if (!relationType.Dual && this.options.ReverseIndexing)
{
// expects the current context to be the child in the relation
if (contextUmbracoObjectType == relationType.GetChildUmbracoObjectType())
{
isContextObjectTypeValid = true;
}
}
else
{
// expects the current context to be the parent in the relation
if (contextUmbracoObjectType == relationType.GetParentUmbracoObjectType())
{
isContextObjectTypeValid = true;
}
}
return isContextObjectTypeValid;
}
///// <summary>
///// Insted of rendering the current name of this property, use a consistant label
///// </summary>
///// <param name="writer"></param>
//protected override void Render(HtmlTextWriter writer)
//{
// writer.WriteLine("<div class='propertyItemheader'>MultiNode Relations</div>");
// writer.WriteLine("<div class='propertyItemContent'>");
// base.Render(writer);
// writer.WriteLine("</div>");
//}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Xml;
using umbraco.cms.businesslogic.datatype;
using umbraco.interfaces;
namespace umbraco.editorControls.PickerRelations
{
/// <summary>
/// This datatype will render a CheckBoxList where the options are defined by an XPath expression,
/// </summary>
public class PickerRelationsDataType : umbraco.cms.businesslogic.datatype.BaseDataType, IDataType
{
/// <summary>
///
/// </summary>
private PickerRelationsPreValueEditor preValueEditor;
/// <summary>
///
/// </summary>
private IDataEditor dataEditor;
/// <summary>
///
/// </summary>
private IData data;
/// <summary>
/// Gets the name of the data type.
/// </summary>
/// <value>The name of the data type.</value>
public override string DataTypeName { get { return "Picker Relations"; } }
/// <summary>
/// Gets the id.
/// </summary>
/// <value>The id.</value>
public override Guid Id { get { return new Guid(DataTypeGuids.PickerRelationsId); } }
/// <summary>
/// Lazy load the associated PreValueEditor instance,
/// this is constructed supplying 'this'
/// </summary>
public override IDataPrevalue PrevalueEditor
{
get
{
if (this.preValueEditor == null)
{
this.preValueEditor = new PickerRelationsPreValueEditor(this);
}
return this.preValueEditor;
}
}
/// <summary>
/// Lazy load the assocated DataEditor,
/// this is constructed supplying the data value stored by the PreValueEditor, and also the configuration settings of the PreValueEditor
/// </summary>
public override IDataEditor DataEditor
{
get
{
if (this.dataEditor == null)
{
this.dataEditor = new PickerRelationsDataEditor(this.Data, ((PickerRelationsPreValueEditor)this.PrevalueEditor).Options);
}
return this.dataEditor;
}
}
/// <summary>
/// Lazy load an empty DefaultData object, this is used to pass data between the PreValueEditor and the DataEditor
/// </summary>
public override IData Data
{
get
{
if (this.data == null)
{
this.data = new umbraco.cms.businesslogic.datatype.DefaultData(this);
}
return this.data;
}
}
}
}

View File

@@ -0,0 +1,267 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using umbraco.BusinessLogic; // ApplicationBase
using umbraco.cms.businesslogic; // SaveEventArgs
using umbraco.cms.businesslogic.media; // Media
using umbraco.cms.businesslogic.member; // Member
using umbraco.cms.businesslogic.web; // Documentusing umbraco.cms.businesslogic.propertytype;
using umbraco.cms.businesslogic.property;
using umbraco.cms.businesslogic.relation;
using umbraco.DataLayer;
namespace umbraco.editorControls.PickerRelations
{
/// <summary>
/// Event handler that will convert a CSV into Relations
/// </summary>
public class PickerRelationsEventHandler : ApplicationBase
{
private enum PickerStorageFormat
{
Csv,
Xml
}
/// <summary>
/// Initializes a new instance of PickerRelationsEventHandler,
/// hooks into the after event of saving a Content node, Media item or a Member
/// </summary>
public PickerRelationsEventHandler()
{
Document.AfterSave += new Document.SaveEventHandler(this.AfterSave);
Media.AfterSave += new Media.SaveEventHandler(this.AfterSave);
Member.AfterSave += new Member.SaveEventHandler(this.AfterSave);
Document.BeforeDelete += new Document.DeleteEventHandler(this.BeforeDelete);
Media.BeforeDelete += new Media.DeleteEventHandler(this.BeforeDelete);
Member.BeforeDelete += new Member.DeleteEventHandler(this.BeforeDelete);
}
/// <summary>
/// Event after all properties have been saved
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AfterSave(Content sender, SaveEventArgs e)
{
Guid pickerRelationsId = new Guid(DataTypeGuids.PickerRelationsId);
// For each PickerRelations datatype
foreach (Property pickerRelationsProperty in from property in sender.GenericProperties
where property.PropertyType.DataTypeDefinition.DataType.Id == pickerRelationsId
select property)
{
// used to identify this datatype instance - relations created are marked with this in the comment field
string instanceIdentifier = "[\"PropertyTypeId\":" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";
// get configuration options for datatype
PickerRelationsOptions options = ((PickerRelationsPreValueEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.PrevalueEditor).Options;
// find Picker source propertyAlias field on sender
Property pickerProperty = sender.getProperty(options.PropertyAlias);
if (pickerProperty != null)
{
// get relationType from options
RelationType relationType = RelationType.GetById(options.RelationTypeId);
if (relationType != null)
{
// validate: 1) check current type of sender matches that expected by the relationType, validation method is in the DataEditor
uQuery.UmbracoObjectType contextObjectType = uQuery.UmbracoObjectType.Unknown;
switch (sender.GetType().ToString())
{
case "umbraco.cms.businesslogic.web.Document": contextObjectType = uQuery.UmbracoObjectType.Document; break;
case "umbraco.cms.businesslogic.media.Media": contextObjectType = uQuery.UmbracoObjectType.Media; break;
case "umbraco.cms.businesslogic.member.Member": contextObjectType = uQuery.UmbracoObjectType.Member; break;
}
if (((PickerRelationsDataEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.DataEditor)
.IsContextUmbracoObjectTypeValid(contextObjectType, relationType))
{
uQuery.UmbracoObjectType pickerUmbracoObjectType = uQuery.UmbracoObjectType.Unknown;
// Get the object type expected by the associated relation type and if this datatype has been configures as a rever index
pickerUmbracoObjectType = ((PickerRelationsDataEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.DataEditor)
.GetPickerUmbracoObjectType(relationType);
// clear all exisitng relations (or look to see previous verion of sender to delete changes ?)
DeleteRelations(relationType, sender.Id, options.ReverseIndexing, instanceIdentifier);
string pickerPropertyValue = pickerProperty.Value.ToString();
var pickerStorageFormat = PickerStorageFormat.Csv; // Assume default of csv
if (xmlHelper.CouldItBeXml(pickerPropertyValue))
{
pickerStorageFormat = PickerStorageFormat.Xml;
}
// Creating instances of Documents / Media / Members ensures the IDs are of a valid type - be quicker to check with GetUmbracoObjectType(int)
Dictionary<int, string> pickerItems = null;
switch (pickerUmbracoObjectType)
{
case uQuery.UmbracoObjectType.Document:
switch (pickerStorageFormat)
{
case PickerStorageFormat.Csv:
pickerItems = uQuery.GetDocumentsByCsv(pickerPropertyValue).ToNameIds();
break;
case PickerStorageFormat.Xml:
pickerItems = uQuery.GetDocumentsByXml(pickerPropertyValue).ToNameIds();
break;
}
break;
case uQuery.UmbracoObjectType.Media:
switch (pickerStorageFormat)
{
case PickerStorageFormat.Csv:
pickerItems = uQuery.GetMediaByCsv(pickerPropertyValue).ToNameIds();
break;
case PickerStorageFormat.Xml:
pickerItems = uQuery.GetMediaByXml(pickerPropertyValue).ToNameIds();
break;
}
break;
case uQuery.UmbracoObjectType.Member:
switch (pickerStorageFormat)
{
case PickerStorageFormat.Csv:
pickerItems = uQuery.GetMembersByCsv(pickerPropertyValue).ToNameIds();
break;
case PickerStorageFormat.Xml:
pickerItems = uQuery.GetMembersByXml(pickerPropertyValue).ToNameIds();
break;
}
break;
}
if (pickerItems != null)
{
foreach (KeyValuePair<int, string> pickerItem in pickerItems)
{
CreateRelation(relationType, sender.Id, pickerItem.Key, options.ReverseIndexing, instanceIdentifier);
}
}
}
else
{
// Error: content object type invalid with relation type
}
}
else
{
// Error: relation type is null
}
}
else
{
// Error: pickerProperty alias not found
}
}
}
/// <summary>
/// Clears any existing relations when deleting a node with a PickerRelations datatype
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.DeleteEventArgs"/> instance containing the event data.</param>
private void BeforeDelete(Content sender, DeleteEventArgs e)
{
Guid pickerRelationsId = new Guid(DataTypeGuids.PickerRelationsId);
// Clean up any relations
// For each PickerRelations datatype
foreach (Property pickerRelationsProperty in from property in sender.GenericProperties
where property.PropertyType.DataTypeDefinition.DataType.Id == pickerRelationsId
select property)
{
// used to identify this datatype instance - relations created are marked with this in the comment field
string instanceIdentifier = "[\"PropertyTypeId\":" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";
// get configuration options for datatype
PickerRelationsOptions options = ((PickerRelationsPreValueEditor)pickerRelationsProperty.PropertyType.DataTypeDefinition.DataType.PrevalueEditor).Options;
// get relationType from options
RelationType relationType = RelationType.GetById(options.RelationTypeId);
if (relationType != null)
{
// clear all exisitng relations
DeleteRelations(relationType, sender.Id, options.ReverseIndexing, instanceIdentifier);
}
}
}
/// <summary>
/// Delete all relations using the content node for a given RelationType
/// </summary>
/// <param name="relationType"></param>
/// <param name="contentNodeId"></param>
/// <param name="reverseIndexing"></param>
/// <param name="instanceIdentifier">NOT USED ATM</param>
private static void DeleteRelations(RelationType relationType, int contentNodeId, bool reverseIndexing, string instanceIdentifier)
{
//if relationType is bi-directional or a reverse index then we can't get at the relations via the API, so using SQL
string getRelationsSql = "SELECT id FROM umbracoRelation WHERE relType = " + relationType.Id.ToString() + " AND ";
if (reverseIndexing || relationType.Dual)
{
getRelationsSql += "childId = " + contentNodeId.ToString();
}
if (relationType.Dual) // need to return relations where content node id is used on both sides
{
getRelationsSql += " OR ";
}
if (!reverseIndexing || relationType.Dual)
{
getRelationsSql += "parentId = " + contentNodeId.ToString();
}
getRelationsSql += " AND comment = '" + instanceIdentifier + "'";
using (IRecordsReader relations = uQuery.SqlHelper.ExecuteReader(getRelationsSql))
{
//clear data
Relation relation;
if (relations.HasRecords)
{
while (relations.Read())
{
relation = new Relation(relations.GetInt("id"));
// TODO: [HR] check to see if an instance identifier is used
relation.Delete();
}
}
}
}
/// <summary>
///
/// </summary>
/// <param name="relationType"></param>
/// <param name="contentNodeId">id sourced from the Content / Media / Member</param>
/// <param name="pickerNodeId">id sourced from the Picker</param>
/// <param name="reverseIndexing">if true, reverses the parentId and child Id</param>
/// <param name="instanceIdentifier">JSON string with id of Picker Relations property instance</param>
private static void CreateRelation(RelationType relationType, int contentNodeId, int pickerNodeId, bool reverseIndexing, string instanceIdentifier)
{
if (reverseIndexing)
{
Relation.MakeNew(pickerNodeId, contentNodeId, relationType, instanceIdentifier);
}
else
{
Relation.MakeNew(contentNodeId, pickerNodeId, relationType, instanceIdentifier);
}
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace umbraco.editorControls.PickerRelations
{
/// <summary>
/// Data Class, used to store the configuration options for the PickerRelationsPreValueEditor
/// </summary>
internal class PickerRelationsOptions
{
/// <summary>
/// Alias of the pickerProperty to get a csv value of IDs from //TODO: a known format for xml fragments would be good too
/// </summary>
public string PropertyAlias { get; set; }
/// <summary>
/// The Id of the RelationType to use
/// </summary>
public int RelationTypeId { get; set; }
/// <summary>
/// only relevant with parent-child
/// </summary>
public bool ReverseIndexing { get; set; }
/// <summary>
/// if true then the property is hidden
/// </summary>
public bool HideDataEditor { get; set; }
/// <summary>
/// Initializes an instance of PickerRelationsOptions
/// </summary>
public PickerRelationsOptions()
{
// Default values
this.PropertyAlias = string.Empty;
this.RelationTypeId = -1;
this.ReverseIndexing = false;
this.HideDataEditor = false;
}
}
}

View File

@@ -0,0 +1,235 @@
using System;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using umbraco.cms.businesslogic.datatype;
using umbraco.cms.businesslogic.relation;
using umbraco.macroRenderings;
namespace umbraco.editorControls.PickerRelations
{
/// <summary>
/// This PreValueEditor will require an XPath expression to define the nodes to pick as CheckBox options,
/// TODO: [HR] min / max selections ?
/// Uses the shared JsonPreValueEditor as nice way of lightweight serializing a config data class object into a single DB field
/// </summary>
public class PickerRelationsPreValueEditor : AbstractJsonPrevalueEditor
{
/// <summary>
/// Prepopulated Umbraco Propery Picker, lists all aliases (could refine this by asking for the context in which this relation wire-up will
/// be used, and then only listing the aliases for that context)
/// </summary>
private propertyTypePicker pickerPropertyAliasPicker = new propertyTypePicker();
/// <summary>
/// RequiredFieldValidator for the ProperyAliasPicker
/// </summary>
private RequiredFieldValidator pickerPropertyAliasRequiredFieldValidator = new RequiredFieldValidator();
/// <summary>
/// drop down list of all relation types
/// </summary>
private DropDownList relationTypeDropDownList = new DropDownList();
/// <summary>
/// RequiredFieldValidator for the RelationType DropDownList
/// </summary>
private RequiredFieldValidator relationTypeRequiredFieldValidator = new RequiredFieldValidator();
/// <summary>
/// If a parent to child relation type is selected, then this checkbox will indicate the direction to use,
/// with reverse indexing the parents are the nodes selected via the picker, and the nodeID on which the
/// this datatype is used, become the child nodes
/// </summary>
private CheckBox reverseIndexingCheckBox = new CheckBox();
/// <summary>
/// if selected, then the property on the data editor is hidden (it's only used as a label)
/// </summary>
private CheckBox hideDataEditorCheckBox = new CheckBox();
/// <summary>
/// Data object used to define the configuration status of this PreValueEditor
/// </summary>
private PickerRelationsOptions options = null;
/// <summary>
/// Currently selected RelationType
/// </summary>
private RelationType relationType = null;
/// <summary>
/// Lazy load the options data object that represents the current state of this datatypes configuration
/// </summary>
internal PickerRelationsOptions Options
{
get
{
if (this.options == null)
{
// Deserialize any stored settings for this PreValueEditor instance
this.options = this.GetPreValueOptions<PickerRelationsOptions>();
// 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 PickerRelationsOptions();
}
}
return this.options;
}
}
/// <summary>
/// Lazy load currently selected RelationType
/// </summary>
private RelationType RelationType
{
get
{
if (this.relationType == null)
{
// Attempt to get RelationType from the selected DropDownList item
int relationTypeId;
if(int.TryParse(this.relationTypeDropDownList.SelectedValue, out relationTypeId))
{
if (relationTypeId != -1)
{
this.relationType = new RelationType(relationTypeId);
}
}
}
return this.relationType;
}
}
/// <summary>
/// Initialize a new instance of PickerRelationsPreValueEditor
/// </summary>
/// <param name="dataType">PickerRelationsDataType</param>
public PickerRelationsPreValueEditor(umbraco.cms.businesslogic.datatype.BaseDataType dataType)
: base(dataType, umbraco.cms.businesslogic.datatype.DBTypes.Nvarchar)
{
}
/// <summary>
/// Creates all of the controls and assigns all of their properties
/// </summary>
protected override void CreateChildControls()
{
this.pickerPropertyAliasPicker.ID = "pickerPropertyAliasPicker";
this.pickerPropertyAliasRequiredFieldValidator.Text = " Required";
this.pickerPropertyAliasRequiredFieldValidator.InitialValue = string.Empty;
this.pickerPropertyAliasRequiredFieldValidator.ControlToValidate = this.pickerPropertyAliasPicker.ID;
this.relationTypeDropDownList.ID = "relationTypeDropDownList";
this.relationTypeDropDownList.AutoPostBack = true;
this.relationTypeDropDownList.DataSource = RelationType.GetAll().OrderBy(x => x.Name);
this.relationTypeDropDownList.DataTextField = "Name";
this.relationTypeDropDownList.DataValueField = "Id";
this.relationTypeDropDownList.DataBind();
this.relationTypeDropDownList.Items.Insert(0, new ListItem(string.Empty, "-1"));
this.relationTypeRequiredFieldValidator.Text = " Required";
this.relationTypeRequiredFieldValidator.InitialValue = "-1";
this.relationTypeRequiredFieldValidator.ControlToValidate = this.relationTypeDropDownList.ID;
this.Controls.Add(this.pickerPropertyAliasPicker);
this.Controls.Add(this.pickerPropertyAliasRequiredFieldValidator);
this.Controls.Add(this.relationTypeDropDownList);
this.Controls.Add(this.relationTypeRequiredFieldValidator);
this.Controls.Add(this.reverseIndexingCheckBox);
this.Controls.Add(this.hideDataEditorCheckBox);
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!this.Page.IsPostBack)
{
// Read in stored configuration values
if (this.pickerPropertyAliasPicker.Items.Contains(new ListItem(this.Options.PropertyAlias)))
{
this.pickerPropertyAliasPicker.SelectedValue = this.Options.PropertyAlias;
}
if (this.relationTypeDropDownList.Items.FindByValue(this.Options.RelationTypeId.ToString()) != null)
{
this.relationTypeDropDownList.SelectedValue = this.Options.RelationTypeId.ToString();
}
this.reverseIndexingCheckBox.Checked = this.Options.ReverseIndexing;
this.hideDataEditorCheckBox.Checked = this.Options.HideDataEditor;
}
}
/// <summary>
/// Saves the pre value data to Umbraco
/// </summary>
public override void Save()
{
if (this.Page.IsValid)
{
this.Options.PropertyAlias = this.pickerPropertyAliasPicker.SelectedValue;
if (this.RelationType != null)
{
this.Options.RelationTypeId = this.RelationType.Id;
}
this.Options.ReverseIndexing = this.reverseIndexingCheckBox.Checked;
this.Options.HideDataEditor = this.hideDataEditorCheckBox.Checked;
// Serialize to Umbraco database field
this.SaveAsJson(this.Options);
}
}
/// <summary>
/// Used to remove styling from the built in pickerProperty alias picker DropDownList
/// </summary>
/// <param name="e"></param>
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
this.pickerPropertyAliasPicker.CssClass = string.Empty; // Remove guiInputTextStandard
// Sort properties in the built in property picker control
ListItem[] propertyAliasListItems = this.pickerPropertyAliasPicker.Items.Cast<ListItem>().OrderBy(x => x.Text).ToArray();
this.pickerPropertyAliasPicker.Items.Clear();
this.pickerPropertyAliasPicker.Items.AddRange(propertyAliasListItems);
}
/// <summary>
/// Replaces the base class writer and instead uses the shared uComponents extension method, to inject consistant markup
/// </summary>
/// <param name="writer"></param>
protected override void RenderContents(HtmlTextWriter writer)
{
writer.AddPrevalueRow("Picker Alias", this.pickerPropertyAliasPicker, this.pickerPropertyAliasRequiredFieldValidator);
writer.AddPrevalueRow("Relation Type", this.relationTypeDropDownList, this.relationTypeRequiredFieldValidator);
// Only show this field if selected RelationType is of Parent to Child
if (this.RelationType != null)
{
if (!this.RelationType.Dual)
{
writer.AddPrevalueRow("Reverse Indexing", this.reverseIndexingCheckBox);
}
}
writer.AddPrevalueRow("Hide Data Editor", this.hideDataEditorCheckBox);
}
}
}