Custom Widget Provider

Make your custom widget available for selection in the data field editor

You can quickly replace the default widget on a data form with a custom one by modifying the data from markup.

However, if you want to make it available for selection as a standard widget in the data field editor, you should make and register a provider for the custom widget in C1 CMS.

The sample widget provider created below works specifically with these two sample text boxes:

Note: Add and register these custom text boxes to C1 CMS before taking the following steps.

Creating a custom widget provider

  1. In Visual Studio, create a Class Library project (e.g. “Composite.Samples.CustomWidgetProvider”).
  2. Add references to:
    1. System.Configuration
    2. ~\Bin\Composite.dll
    3. ~\Bin\Microsoft.Practices.EnterpriseLibrary.Common.dll
    4. ~\Bin\Microsoft.Practices.ObjectBuilder.dll
  3. Create a class for the widget function (e.g. ” SimpleTextWidgetFunction.cs”)
  4. Add the following code:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml.Linq;
    using Composite.C1Console.Elements;
    using Composite.C1Console.Security;
    using Composite.C1Console.Trees;
    using Composite.Core.Xml;
    using Composite.Functions;
    
    namespace Composite.Samples.CustomWidgetProvider
    {
    	public class SimpleTextWidgetFunction : IWidgetFunction
    	{
    
    
    		public SimpleTextWidgetFunction(string name, string description)
    		{
    			Name = name;
    			Description = description;
    		}
    
    		public XElement GetWidgetMarkup(ParameterList parameters, string label, HelpDefinition helpDefinition, string bindingSourceName)
    		{
    			return new XElement(Namespaces.BindingFormsStdUiControls10 + Name,
    					new XAttribute("Label", label),
    					new XAttribute("Help", helpDefinition.HelpText),
    							new XElement(Namespaces.BindingForms10 + "bind",
    									new XAttribute("source", bindingSourceName)));
    		}
    
    		public string Description { get; private set; }
    
    		public EntityToken EntityToken
    		{
    			get { return new SimpleWidgetFunctionEntityToken(string.Format("{0}.{1}", Namespace, Name)); }
    		}
    
    		public string Name { get; private set; }
    
    		public string Namespace
    		{
    			get { return "Composite.Samples.String"; }
    		}
    
    		public IEnumerable<ParameterProfile> ParameterProfiles
    		{
    			get { yield break; }
    		}
    
    		public Type ReturnType
    		{
    			get { return typeof(string); }
    		}
    
    
    	}
    
    	[SecurityAncestorProvider(typeof(SimpleAncestorSecurityAncestorProvider))]
    	public class SimpleWidgetFunctionEntityToken : EntityToken
    	{
    		private string _id;
    
    		internal SimpleWidgetFunctionEntityToken(string id)
    		{
    			_id = id;
    		}
    
    		public override string Id { get { return _id; } }
    		public override string Source { get { return ""; } }
    		public override string Type { get { return ""; } }
    
    		// Responsible for serializing the state of this EntityToken as a string
    		public override string Serialize()
    		{
    			return _id;
    		}
    
    		// Respinsible for deserializing the string return by the serializer above
    		public static EntityToken Deserialize(string serializedEntityToken)
    		{
    			return new SimpleWidgetFunctionEntityToken(serializedEntityToken);
    		}
    	}
    
    	internal sealed class SimpleAncestorSecurityAncestorProvider : ISecurityAncestorProvider
    	{
    		public IEnumerable<EntityToken> GetParents(EntityToken entityToken)
    		{
    			yield return AttachingPoint.PerspectivesRoot.EntityToken;
    		}
    	}
    
    }
    


    Download SimpleTextWidgetFunction.cs
  5. Create a class for the widget provider (e.g. “CustomWidgetFunctionProvider.cs”)
  6. Add the following code:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Composite.Functions;
    using Composite.Functions.Plugins.WidgetFunctionProvider;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
    using Microsoft.Practices.ObjectBuilder;
    
    namespace Composite.Samples.CustomWidgetProvider
    {
    	[ConfigurationElementType(typeof(MyWidgetFunctionProviderData))]
    	public class CustomWidgetFunctionProvider : IWidgetFunctionProvider
    	{
    
    		public IEnumerable<IWidgetFunction> Functions
    		{
    			get
    			{
    				yield return new SimpleTextWidgetFunction("CustomTreeInput", "Sample input widget with a tree picker");
    				yield return new SimpleTextWidgetFunction("CustomFormInput", "Sample input widget with a form picker");
    			}
    		}
    
    		public WidgetFunctionNotifier WidgetFunctionNotifier
    		{
    			set { }
    		}
    	}
    
    	[Assembler(typeof(MyWidgetFunctionProviderAssembler))]
    	public class MyWidgetFunctionProviderData : WidgetFunctionProviderData
    	{
    		// No custom configuration in this sample...
    	}
    
    	public sealed class MyWidgetFunctionProviderAssembler
    			: IAssembler<IWidgetFunctionProvider, WidgetFunctionProviderData>
    	{
    		public IWidgetFunctionProvider Assemble(IBuilderContext context,
    				WidgetFunctionProviderData objectConfiguration, IConfigurationSource configurationSource,
    				ConfigurationReflectionCache reflectionCache)
    		{
    			return new CustomWidgetFunctionProvider();
    		}
    	}
    
    }
    


    Download CustomWidgetFunctionProvider.cs
  7. Build the solution.
  8. Copy the output DLL (e.g. “Composite.Samples.CustomWidgetProvider.dll”) to ~/Bin/ on your website.

Here, in the ‘Functions’ property, both custom controls are specified.

yield return new SimpleTextWidgetFunction("CustomTreeInput", "Sample input widget with a tree picker");
yield return new SimpleTextWidgetFunction("CustomFormInput", "Sample input widget with a form picker");

Comment out the corresponding line if the control is not in use.

Registering the custom control in Composite.config

  1. Edit ~/App_Data/Composite/Composite.config
  2. Locate this configuration element:
    /configuration/Composite.Functions.Plugins.WidgetFunctionProviderConfiguration/WidgetFunctionProviderPlugins
  3. Add this element below after the last ‘Add’ element:
    <add 
    type="Composite.Samples.CustomWidgetProvider.CustomWidgetFunctionProvider, Composite.Samples.CustomWidgetProvider" 
    name="Composite.Samples.CustomWidgetProvider" />
  4. Save the file.

Using the custom control with the tree control on a data form

  1. Create a global data type.
  2. Add fields making sure at least one of which is of the String type (to be used for the custom control).
  3. On the Advanced tab of the field, change the default widget to the custom widget (“CustomFormInput” or “CustomTreeInput”).
  4. Save the changes.