Widget with a custom designer and string[] property

Posted by Community Admin on 03-Aug-2018 18:37

Widget with a custom designer and string[] property

All Replies

Posted by Community Admin on 24-Mar-2011 00:00
Hi.
How can I manage widget string[] property by a custom designer? I've tried to do following:

Widget:
[Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesigner(typeof(TextControlDesigner))]
 public class TextControl : TextControlBase
 
     private const string TemplateName = "Controls.Resources.Templates.TextControl.ascx";
     protected override void InitializeControls(GenericContainer container)
     
         TextBox1.Text = this.Text;
         if (this.Test != null)
         
             TextBox2.Text = this.Test[0];
         
     
 
    public string Text get; set;
 
     public string[] Test get; set;
 
     protected override string LayoutTemplateName
     
         get
         
             return TemplateName;
         
     
     protected virtual TextBox TextBox1
     
         get
         
             return base.Container.GetControl<TextBox>("TextBox1", true);
         
     
     protected virtual TextBox TextBox2
     
         get
         
             return base.Container.GetControl<TextBox>("TextBox2", true);
         
     
 


Widget's Template:
<%@ Control Language="C#" %>
<asp:TextBox runat="server" ID="TextBox1" />
<asp:TextBox runat="server" ID="TextBox2" />

Custom Designer:
public class TextControlDesigner : ControlDesignerBase
   
       private const string TemplateName = "Controls.Resources.Templates.TextControlDesigner.ascx";
       private const string ScriptReference = "Controls.Resources.JavaScript.TextControlDesigner.js";
       protected override void InitializeControls(GenericContainer container)
       
           base.DesignerMode = ControlDesignerModes.Simple;
       
 
       protected override string LayoutTemplateName
       
           get
           
               return TemplateName;
           
       
       public override IEnumerable<System.Web.UI.ScriptReference> GetScriptReferences()
       
           var res = new List<ScriptReference>(base.GetScriptReferences());
           var assemblyName = this.GetType().Assembly.GetName().ToString();
           res.Add(new ScriptReference(ScriptReference, assemblyName));
           return res.ToArray();
             
 
   

Control designer's template:
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI"
    TagPrefix="sitefinity" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<div class="sfContentViews">
    <div id="TextControlOptions">
        <h2>
            Fine tune your Text control
        </h2>
        <div>
            <label for="text">
                Text</label>
            <input type="text" id="text" class="sfTxt" />
            <label for="test">
                Text</label>
            <input type="text" id="test" class="sfTxt" />        
        </div>
    </div>
</div>

and custom designer's .js file:
Type.registerNamespace("Controls.Navigation");
 
Controls.Navigation.TextControlDesigner = function (element)
   Controls.Navigation.TextControlDesigner.initializeBase(this, [element]);
    this._parentDesigner = null;
    this._googleAnalyticsCodeTextField = null;
    this._scriptEmbedPositionChoiceField = null;
    this._toogleGroupSettingsDelegate = null;
 
 
Controls.Navigation.TextControlDesigner.prototype =
    initialize: function ()
        this.refreshUI();
        Controls.Navigation.TextControlDesigner.callBaseMethod(this, 'initialize');
        this._toogleGroupSettingsDelegate = Function.createDelegate(this, function ()
            dialogBase.resizeToContent();
        )
    ,
    dispose: function ()
       Controls.Navigation.TextControlDesigner.callBaseMethod(this, 'dispose');
    ,
    refreshUI: function ()
        var data = this._propertyEditor.get_control();
        jQuery("#text").val(data.Text);
        if ((data.Test !== null) && (typeof (data.Test) !== 'undefined'))
            jQuery("#test").val(data.Test[0]);
        
    ,
    applyChanges: function ()
 
        var controlData = this._propertyEditor.get_control();
        controlData.Text = jQuery("#text").val();
        controlData.Test = new Array();
        controlData.Test[0] = '1';
    
Controls.Navigation.TextControlDesigner.registerClass('Controls.Navigation.TextControlDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
* I've removed the assembly name from a code.

When I had only a string Text property, I was able to save it by pressing a Save button. But when I added the string[] Test property every attempt to save is finished by following message at Firebug's console:

Error Status Code: 'InternalServerError'
 
Details: There was an error deserializing the object of type Telerik.Sitefinity.Modules.Pages.Web.Services.Model.WcfControlProperty[]. End element 'PropertyValue' from namespace '' expected. Found element 'item' from namespace ''.
Posted by Community Admin on 28-Mar-2011 00:00
Hi Vyacheslav,

Generally you should deserialize and serialize the object on the client using  Sys.Serialization.JavaScriptSerializer

All the best,
Ivan Dimitrov
the Telerik team
Posted by Community Admin on 30-Mar-2011 00:00
Hi Ivan,
Thank you for your answer.
I've tried to do following at the designer's js code:

applyChanges: function ()
      var controlData = this._propertyEditor.get_control();
      controlData.Text = jQuery("#text").val();
      var test = new Array();
      test[0] = '1';
      test[1] = '2';
      console.log("test: %o", test);
      controlData.Test = Sys.Serialization.JavaScriptSerializer.serialize(test);
      console.log("serialized test: %o", Sys.Serialization.JavaScriptSerializer.serialize(test));
  

Also, I've added the [TypeConverter(typeof(StringArrayConverter))] attribute of the TextControl.Test property and saving is working properly now. My widget base class:

namespace HEH.WebSite.EducationalPortal.Controls.ControlBase

    using System.ComponentModel;
    using Converters;
    using Telerik.Sitefinity.Web.UI;


    public abstract class TextControlBase : SimpleView
    
        public string Text get; set;


        [TypeConverter(typeof(StringArrayConverter))]
        public string[] Test get; set;
    

StringArrayConverter:
Controls.Converters
    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design.Serialization;
    using System.Globalization;
    using Newtonsoft.Json;
 
    public class StringArrayConverter : TypeConverter
    
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        
            return ((sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType));
        
 
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        
            return ((destinationType == typeof(InstanceDescriptor)) || base.CanConvertTo(context, destinationType));
        
 
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        
            if (value is string)
            
                return JsonConvert.DeserializeObject<string[]>(value as string);
            
            return base.ConvertFrom(context, culture, value);
        
 
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,
                                         Type destinationType)
        
            if (value is string[])
            
                return JsonConvert.SerializeObject(value);
            
            return base.ConvertTo(context, culture, value, destinationType);
        
    

Thank you for your help.
This thread is closed