use this base class
public class DynamicContentBase : TranslateUserControl, EPiServer.DynamicContent.IDynamicContent, IDynamicContentDisplayType
{
public bool RenderAsBlockElement { get { return true; } }
public string Add2Style = "";
public string PreviewText = "";
public virtual bool DebugMode { get { return true; } }
public string DebugText = "";
#region IDynamicContent Members
public virtual System.Web.UI.Control GetControl(EPiServer.PageBase hostPage)
{
throw new NotImplementedException();
}
protected PropertyDataCollection _properties;
public void SetProperties(PropertyDataCollection props)
{
_properties = props;
}
public virtual EPiServer.Core.PropertyDataCollection Properties
{
get { return _properties; }
}
public virtual string Render(EPiServer.PageBase hostPage)
{
throw new NotImplementedException();
}
public virtual bool RendersWithControl
{
get { return true; }
}
#region State (64 encoded)
private string _state;
public string State
{
get
{
if (Value == null)
return null;
return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Value));
}
set
{
if (value != null)
{
_state = value;
byte[] toDecodeByte = Convert.FromBase64String(value);
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length);
char[] decodedChar = new char[charCount];
utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0);
string result = new String(decodedChar);
Value = result;
}
}
}
#endregion
#region Value
public string MakeStringFromCollection(PropertyDataCollection properties, bool debug)
{
if (properties == null)
return null;
string result = "";
XmlDocument doc = new XmlDocument();
string xml = "<data>";
foreach (PropertyData prop in properties)
{
if (DebugMode && prop.Name.Equals("Debug")) { }
else
{
result += "adding " + prop.Name + System.Environment.NewLine;
xml += "<" + prop.Name + " />";
}
}
xml += "</data>";
doc.LoadXml(xml);
foreach (XmlNode node in doc.FirstChild.ChildNodes)
{
if (properties[node.Name] is Itera.Property.PropertyMulitBase)
{
node.InnerText = (properties[node.Name] as Itera.Property.PropertyMulitBase).CreateXml();
}
else
node.InnerText = properties[node.Name].ToString();
}
result += doc.FirstChild.InnerXml;
return result;
}
public string Value_Set = "";
public string Value
{
get
{
return MakeStringFromCollection(Properties, false);
}
set
{
if (value != null)
{
Value_Set += value + "<hr />";
}
if (Properties == null)
return;
XmlDocument doc = new XmlDocument();
string xml = "<data>" + value + "</data>";
doc.LoadXml(xml);
foreach (PropertyData prop in Properties)
{
if (doc.FirstChild[prop.Name] != null)
{
prop.ParseToSelf(doc.FirstChild[prop.Name].InnerText);
if (DebugMode)
DebugText += "set" + prop.Name + "=(" + doc.FirstChild[prop.Name].ChildNodes + ")" + doc.FirstChild[prop.Name].InnerText + System.Environment.NewLine;
}
}
ValueSet(value);
}
}
#endregion
#endregion
public virtual void ValueSet()
{
}
public virtual void ValueSet(string xml)
{
ValueSet();
}
}
Thank you very much!
But if I replace "EPiServer.UserControlBase" with "MyPage.Classes.DynamicContentBase" my propertied disappear. I'm not sure how to implement you class the right way.
Regards
Karl
Hi
This base class you had to register the properties by override the Properties method
but if you use this class I quess it will work as you are used to
public class DynamicContentBaseWithAuto : EPiServer.UserControlBase, EPiServer.DynamicContent.IDynamicContent, IDynamicContentDisplayType
{
public bool RenderAsBlockElement { get { return true; } }
public string Add2Style = "";
public string PreviewText = "";
public virtual bool DebugMode { get { return true; } }
public string DebugText = "";
#region IDynamicContent Members
public virtual System.Web.UI.Control GetControl(EPiServer.PageBase hostPage)
{
throw new NotImplementedException();
}
protected PropertyDataCollection _properties;
public virtual EPiServer.Core.PropertyDataCollection Properties
{
get {
if (_properties == null)
{
var _new = new PropertyDataCollection();
var type = this.GetType();
var _propInfo = (
from pi in type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty)
where pi.PropertyType.IsSubclassOf(typeof(PropertyData)) || pi.PropertyType == typeof(string) || pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(PageReference) || pi.PropertyType == typeof(int)
select pi into p
where p.CanRead && p.CanWrite
select p).ToList<PropertyInfo>();
foreach (PropertyInfo current in _propInfo)
{
PropertyData propertyData = null;
if (current.PropertyType.IsSubclassOf(typeof(PropertyData)))
{
propertyData = (Activator.CreateInstance(current.PropertyType) as PropertyData);
}
else
{
if (current.PropertyType == typeof(string))
{
propertyData = new PropertyString();
}
else
{
if (current.PropertyType == typeof(int))
{
propertyData = new PropertyNumber();
}
else
{
if (current.PropertyType == typeof(bool))
{
propertyData = new PropertyBoolean();
}
else
{
if (current.PropertyType == typeof(PageReference))
{
propertyData = new PropertyPageReference();
}
}
}
}
}
if (propertyData != null)
{
propertyData.Name = current.Name;
_new.Add(propertyData);
}
}
_properties = _new;
}
return _properties;
}
}
public virtual string Render(EPiServer.PageBase hostPage)
{
throw new NotImplementedException();
}
public virtual bool RendersWithControl
{
get { return true; }
}
#region State (64 encoded)
private string _state;
public string State
{
get
{
if (Value == null)
return null;
return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Value));
}
set
{
if (value != null)
{
_state = value;
byte[] toDecodeByte = Convert.FromBase64String(value);
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length);
char[] decodedChar = new char[charCount];
utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0);
string result = new String(decodedChar);
Value = result;
}
}
}
#endregion
#region Value
public string MakeStringFromCollection(PropertyDataCollection properties, bool debug)
{
if (properties == null)
return null;
string result = "";
XmlDocument doc = new XmlDocument();
string xml = "<data>";
foreach (PropertyData prop in properties)
{
if (DebugMode && prop.Name.Equals("Debug")) { }
else
{
result += "adding " + prop.Name + System.Environment.NewLine;
xml += "<" + prop.Name + " />";
}
}
xml += "</data>";
doc.LoadXml(xml);
foreach (XmlNode node in doc.FirstChild.ChildNodes)
{
if (properties[node.Name] is Itera.Property.PropertyMulitBase)
{
node.InnerText = (properties[node.Name] as Itera.Property.PropertyMulitBase).CreateXml();
}
else
node.InnerText = properties[node.Name].ToString();
}
result += doc.FirstChild.InnerXml;
return result;
}
public string Value_Set = "";
public string Value
{
get
{
return MakeStringFromCollection(Properties, false);
}
set
{
if (value != null)
{
Value_Set += value + "<hr />";
}
if (Properties == null)
return;
XmlDocument doc = new XmlDocument();
string xml = "<data>" + value + "</data>";
doc.LoadXml(xml);
foreach (PropertyData prop in Properties)
{
if (doc.FirstChild[prop.Name] != null)
{
prop.ParseToSelf(doc.FirstChild[prop.Name].InnerText);
if (DebugMode)
DebugText += "set" + prop.Name + "=(" + doc.FirstChild[prop.Name].ChildNodes + ")" + doc.FirstChild[prop.Name].InnerText + System.Environment.NewLine;
}
}
ValueSet(value);
}
}
#endregion
#endregion
public virtual void ValueSet()
{
}
public virtual void ValueSet(string xml)
{
ValueSet();
}
}
And it's a bug in the base class. Or more like bad handy work. Since they use | as seperator and the position of the property to map it back.
My code saves the data down with the name of the property.
One more question:
Are you using DynamicContentPlugIn or do you register the control in web.config?
I get this error message: "The method or operation is not implemented" on
public virtual System.Web.UI.Control GetControl(EPiServer.PageBase hostPage) { throw new NotImplementedException(); }
Then i get the same error message on :
public virtual string Render(EPiServer.PageBase hostPage) { throw new NotImplementedException(); }
What i did to solve the above problem was to add:
public override System.Web.UI.Control GetControl(EPiServer.PageBase hostPage) {
var userControl = (MagazineItem)hostPage.LoadControl("~/Templates/DynamicContent/MagazineItem.ascx"); userControl.Title = Properties["Title"].Value as string;
return userControl;
}
It takes alot of extra code to write out all the properties again but it works.
I have not used that base class you are using before, but if you modify above code to some thing like this I quess that mapping will be done fore you
public class DynamicContentBaseWithAuto : EPiServer.UserControlBase, EPiServer.DynamicContent.IDynamicContent, IDynamicContentDisplayType
{
public bool RenderAsBlockElement { get { return true; } }
public string Add2Style = "";
public string PreviewText = "";
public virtual bool DebugMode { get { return true; } }
public string DebugText = "";
#region IDynamicContent Members
protected PropertyDataCollection _properties;
public virtual EPiServer.Core.PropertyDataCollection Properties
{
get
{
if (_properties == null)
{
var _new = new PropertyDataCollection();
foreach (PropertyInfo current in PropertyItems)
{
PropertyData propertyData = null;
if (current.PropertyType.IsSubclassOf(typeof(PropertyData)))
{
propertyData = (Activator.CreateInstance(current.PropertyType) as PropertyData);
}
else
{
if (current.PropertyType == typeof(string))
{
propertyData = new PropertyString();
}
else
{
if (current.PropertyType == typeof(int))
{
propertyData = new PropertyNumber();
}
else
{
if (current.PropertyType == typeof(bool))
{
propertyData = new PropertyBoolean();
}
else
{
if (current.PropertyType == typeof(PageReference))
{
propertyData = new PropertyPageReference();
}
}
}
}
}
if (propertyData != null)
{
propertyData.Name = current.Name;
_new.Add(propertyData);
}
}
_properties = _new;
}
return _properties;
}
}
public virtual string Render(EPiServer.PageBase hostPage)
{
throw new NotImplementedException();
}
public virtual bool RendersWithControl
{
get { return true; }
}
#region State (64 encoded)
private string _state;
public string State
{
get
{
if (Value == null)
return null;
return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Value));
}
set
{
if (value != null)
{
_state = value;
byte[] toDecodeByte = Convert.FromBase64String(value);
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length);
char[] decodedChar = new char[charCount];
utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0);
string result = new String(decodedChar);
Value = result;
}
}
}
#endregion
#region Value
public string MakeStringFromCollection(PropertyDataCollection properties, bool debug)
{
if (properties == null)
return null;
string result = "";
XmlDocument doc = new XmlDocument();
string xml = "<data>";
foreach (PropertyData prop in properties)
{
if (DebugMode && prop.Name.Equals("Debug")) { }
else
{
result += "adding " + prop.Name + System.Environment.NewLine;
xml += "<" + prop.Name + " />";
}
}
xml += "</data>";
doc.LoadXml(xml);
foreach (XmlNode node in doc.FirstChild.ChildNodes)
{
if (properties[node.Name] is Itera.Property.PropertyMulitBase)
{
node.InnerText = (properties[node.Name] as Itera.Property.PropertyMulitBase).CreateXml();
}
else
node.InnerText = properties[node.Name].ToString();
}
result += doc.FirstChild.InnerXml;
return result;
}
public string Value_Set = "";
public string Value
{
get
{
return MakeStringFromCollection(Properties, false);
}
set
{
if (value != null)
{
Value_Set += value + "<hr />";
}
if (Properties == null)
return;
XmlDocument doc = new XmlDocument();
string xml = "<data>" + value + "</data>";
doc.LoadXml(xml);
foreach (PropertyData prop in Properties)
{
if (doc.FirstChild[prop.Name] != null)
{
prop.ParseToSelf(doc.FirstChild[prop.Name].InnerText);
if (DebugMode)
DebugText += "set" + prop.Name + "=(" + doc.FirstChild[prop.Name].ChildNodes + ")" + doc.FirstChild[prop.Name].InnerText + System.Environment.NewLine;
}
}
ValueSet(value);
}
}
#endregion
#endregion
public virtual void ValueSet()
{
}
public override Control GetControl(PageBase hostPage)
{
Control control;
if (string.IsNullOrEmpty(ControlUrl))
{
throw new ArgumentException("No ViewUrl has been set for this dynamic content user control. The ViewUrl must be set explicitly, e.g.: [DynamicContentPlugIn(ViewUrl = \"~/Path/To/My/UserControl.ascx\")]");
}
control = hostPage.LoadControl(UriSupport.ResolveUrlBySettings(ControlUrl));
this.InitializeControlState(control);
return control;
}
List<PropertyInfo> _propertyItems;
List<PropertyInfo> PropertyItems
{
get
{
if (_propertyItems == null)
{
var type = this.GetType();
_propertyItems = (
from pi in type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty)
where pi.PropertyType.IsSubclassOf(typeof(PropertyData)) || pi.PropertyType == typeof(string) || pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(PageReference) || pi.PropertyType == typeof(int)
select pi into p
where p.CanRead && p.CanWrite
select p).ToList<PropertyInfo>();
}
return _propertyItems;
}
}
string _controlUrl;
public string ControlUrl
{
get
{
if (_controlUrl == null)
{
var type = this.GetType();
DynamicContentPlugInAttribute dynamicContentPlugInAttribute = (DynamicContentPlugInAttribute)type.GetCustomAttributes(typeof(DynamicContentPlugInAttribute), true).First<object>();
_controlUrl = dynamicContentPlugInAttribute.ViewUrl;
}
return _controlUrl;
}
}
protected virtual void InitializeControlState(Control control)
{
foreach (PropertyInfo current in PropertyItems)
{
PropertyData propertyData = Properties[current.Name];
if (propertyData != null && propertyData.Value != null)
{
try
{
if (current.PropertyType.IsSubclassOf(typeof(PropertyData)))
{
current.SetValue(control, propertyData, null);
}
else
{
current.SetValue(control, propertyData.Value, null);
}
}
catch
{
}
}
}
}
public virtual void ValueSet(string xml)
{
ValueSet();
}
}
I'm creating DC-controls with DynamicContentPlugIn and I use Page type builder and ETF to create editor controls with DynamicContentEditControl. But I have a very annoying bug now with the values in the fields of the control. When I'm using the crontrol and leave a field empty or don't check a checkbox it uses the value from the property below. In other words, the value can't be null because then it uses the value from the next propery in line.
I am aware of the issue with moving around the order of the properties once they have values, but now the values moves around by them themselves.
Any help solving this would be much appreciated.