Using RadGrid inside Sitefinity Form Widget
Hi!
I'm trying to embed a RadGrid in a Sitefinity Form Widget, so i can add a field to a form which allows users to create a collection of attendees that will attend a specific event. The process works fine, until I try to integrate the code into a FieldControl, then neither the insert or update command events will fire, meaning i can never add or update rows.
I've attached code, any ideas? I'm fresh out!
Attendees.ascx
<%@ Control %>
<%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" %>
<
asp:Label
runat
=
"server"
ID
=
"titleLabel"
CssClass
=
"sfTxtLbl"
Text
=
"title label"
AssociatedControlID
=
"TextBox1"
/>
<
div
class
=
"sfFieldWrp"
>
<
asp:TextBox
ID
=
"TextBox1"
CssClass
=
"sfTxt"
runat
=
"server"
/>
<
telerik:RadAjaxManager
ID
=
"RadAjaxManager1"
runat
=
"server"
>
<
AjaxSettings
>
<
telerik:AjaxSetting
AjaxControlID
=
"RadGrid1"
>
<
UpdatedControls
>
<
telerik:AjaxUpdatedControl
ControlID
=
"RadGrid1"
LoadingPanelID
=
"RadAjaxLoadingPanel1"
>
</
telerik:AjaxUpdatedControl
>
</
UpdatedControls
>
</
telerik:AjaxSetting
>
</
AjaxSettings
>
</
telerik:RadAjaxManager
>
<
telerik:RadGrid
ID
=
"attendees"
runat
=
"server"
AutoGenerateColumns
=
"False"
AllowSorting
=
"false"
AllowFilteringByColumn
=
"false"
>
<
ItemStyle
HorizontalAlign
=
"Center"
></
ItemStyle
>
<
AlternatingItemStyle
HorizontalAlign
=
"Center"
></
AlternatingItemStyle
>
<
HeaderStyle
HorizontalAlign
=
"Center"
></
HeaderStyle
>
<
MasterTableView
CommandItemDisplay
=
"Top"
EditMode
=
"InPlace"
DataKeyNames
=
"ID"
>
<
Columns
>
<
telerik:GridTemplateColumn
UniqueName
=
"FirstName"
HeaderText
=
"First Name"
SortExpression
=
"FirstName"
>
<
ItemTemplate
>
<%# DataBinder.Eval(Container.DataItem, "FirstName") %>
</
ItemTemplate
>
<
EditItemTemplate
>
<
telerik:RadTextBox
ID
=
"firstName"
runat
=
"server"
Skin
=
"Web20"
Width
=
"100px"
Text='<%# Bind("FirstName")%>'>
</
telerik:RadTextBox
>
</
EditItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"LastName"
HeaderText
=
"Last Name"
SortExpression
=
"LastName"
>
<
ItemTemplate
>
<%# DataBinder.Eval(Container.DataItem, "LastName")%>
</
ItemTemplate
>
<
EditItemTemplate
>
<
telerik:RadTextBox
ID
=
"lastName"
runat
=
"server"
Skin
=
"Web20"
Width
=
"100px"
Text='<%# Bind("LastName")%>'>
</
telerik:RadTextBox
>
</
EditItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"DateOfBirth"
HeaderText
=
"Date of Birth"
SortExpression
=
"DateOfBirth"
>
<
ItemTemplate
>
<%# (DataBinder.Eval(Container.DataItem, "DateOfBirth")) %>
</
ItemTemplate
>
<
EditItemTemplate
>
<
telerik:RadDateInput
ID
=
"dateOfBirth"
runat
=
"server"
Skin
=
"Web20"
Culture
=
"(Default)"
DbSelectedDate='<%# Bind("DateOfBirth")%>' DateFormat="dd/MM/yyyy" MinDate="01/01/1920"
Width="120px"></
telerik:RadDateInput
>
</
EditItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"Gender"
HeaderText
=
"Gender"
SortExpression
=
"Gender"
>
<
ItemTemplate
>
<%# DataBinder.Eval(Container.DataItem, "Gender")%>
</
ItemTemplate
>
<
EditItemTemplate
>
<
telerik:RadMaskedTextBox
ID
=
"gender"
Width
=
"60px"
runat
=
"server"
Skin
=
"Web20"
Text='<%# Bind("Gender")%>' Mask="<
M
|F|m|f>" PromptChar="_"></
telerik:RadMaskedTextBox
>
</
EditItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridEditCommandColumn
ButtonType
=
"ImageButton"
UpdateText
=
"Update"
CancelText
=
"Cancel"
EditText
=
"Edit"
>
</
telerik:GridEditCommandColumn
>
</
Columns
>
</
MasterTableView
>
</
telerik:RadGrid
>
<
sf:SitefinityLabel
runat
=
"server"
ID
=
"descriptionLabel"
WrapperTagName
=
"div"
CssClass
=
"sfDescription"
/>
<
sf:SitefinityLabel
runat
=
"server"
ID
=
"exampleLabel"
WrapperTagName
=
"div"
CssClass
=
"sfExample"
/>
</
div
>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using Telerik.Sitefinity.Data.Metadata;
using Telerik.Sitefinity.Metadata.Model;
using Telerik.Sitefinity.Model;
using Telerik.Sitefinity.Modules.Forms.Web.UI.Fields;
using Telerik.Sitefinity.Security;
using Telerik.Sitefinity.Web.UI;
using Telerik.Sitefinity.Web.UI.ControlDesign;
using Telerik.Sitefinity.Web.UI.Fields;
using Telerik.Sitefinity.Web.UI.Fields.Enums;
using System.Data;
using Telerik.Web.UI;
using System.Collections;
using System.Text;
using System.Web;
namespace SitefinityWebApp.Custom.Forms.Atendees
/// <
summary
>
/// Class used to create custom control for Form Builder
/// </
summary
>
/// <
remarks
>
/// If this form widget is a part of a Sitefinity module,
/// you can register it in the site's toolbox by adding this to the module's Install/Upgrade method(s):
/// initializer.Installer
/// .Toolbox(CommonToolbox.FormWidgets)
/// .LoadOrAddSection(SectionName) // "TwoColumns" is Sitefinity's default
/// .SetTitle(SectionTitle) // When creating a new section
/// .SetDescription(SectionDescription) // When creating a new section
/// .LoadOrAddWidget<
Attendees
>("Attendees")
/// .SetTitle("Attendees")
/// .SetDescription("Attendees")
/// .LocalizeUsing<
ModuleResourceClass
>() // Optional
/// .SetCssClass(WidgetCssClass) // You can use a css class to add an icon (this is optional)
/// .Done()
/// .Done()
/// .Done();
/// </
remarks
>
/// <
see
cref
=
"http://www.sitefinity.com/documentation/gettingstarted/creating-custom-form-field-controls"
/>
[DatabaseMapping(UserFriendlyDataType.ShortText)]
[PropertyEditorTitle("Attendees Properties"), Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesigner(typeof(SitefinityWebApp.Custom.Forms.Atendees.Designer.AttendeesDesigner))]
public class Attendees : FieldControl, IFormFieldControl
#region Constructor
/// <
summary
>
/// Initializes a new instance of the Attendees class.
/// </
summary
>
public Attendees()
this.Title = "Attendees";
#endregion
#region Public properties (will show up in dialog)
/// <
summary
>
/// Example string
/// </
summary
>
public override string Example get; set;
/// <
summary
>
/// Title string
/// </
summary
>
public override string Title get; set;
/// <
summary
>
/// Description string
/// </
summary
>
public override string Description get; set;
#endregion
#region IFormFieldControl members
/// <
summary
>
/// Gets or sets MetaField property to persist data from control to the DB when form is submitted
/// </
summary
>
[TypeConverter(typeof(ExpandableObjectConverter))]
public IMetaField MetaField
get
if (this.metaField == null)
this.metaField = this.LoadDefaultMetaField();
return this.metaField;
set
this.metaField = value;
#endregion
#region Value method
/// <
summary
>
/// Get and set the value of the field.
/// </
summary
>
public override object Value
get
return this.TextBox1.Text;
set
this.TextBox1.Text = value.ToString();
#endregion
#region Template
/// <
summary
>
/// Obsolete. Use LayoutTemplatePath instead.
/// </
summary
>
protected override string LayoutTemplateName
get
return string.Empty;
/// <
summary
>
/// Gets the layout template's relative or virtual path.
/// </
summary
>
public override string LayoutTemplatePath
get
if (string.IsNullOrEmpty(base.LayoutTemplatePath))
return Attendees.layoutTemplatePath;
return base.LayoutTemplatePath;
set
base.LayoutTemplatePath = value;
#endregion
#region Labels on control template
/// <
summary
>
/// Gets reference to the TitleLabel
/// </
summary
>
protected internal virtual Label TitleLabel
get
return this.Container.GetControl<
Label
>("titleLabel", true);
/// <
summary
>
/// Gets reference to the DescriptionLabel
/// </
summary
>
protected internal virtual Label DescriptionLabel
get
return Container.GetControl<
Label
>("descriptionLabel", true);
/// <
summary
>
/// Gets reference to the ExampleLabel
/// </
summary
>
protected internal virtual Label ExampleLabel
get
return this.Container.GetControl<
Label
>("exampleLabel", this.DisplayMode == FieldDisplayMode.Write);
/// <
summary
>
/// Reference to the TitleControl
/// </
summary
>
protected override WebControl TitleControl
get
return this.TitleLabel;
/// <
summary
>
/// Reference to the DescriptionControl
/// </
summary
>
protected override WebControl DescriptionControl
get
return this.DescriptionLabel;
/// <
summary
>
/// Gets the reference to the control that represents the example of the field control.
/// Return null if no such control exists in the template.
/// </
summary
>
/// <
value
></
value
>
protected override WebControl ExampleControl
get
return this.ExampleLabel;
#endregion
#region Textbox on control
/// <
summary
>
/// Gets reference to the TextBox1 control
/// </
summary
>
protected virtual TextBox TextBox1
get
return this.Container.GetControl<
TextBox
>("TextBox1", true);
#endregion
#region InitializeControls method
/// <
summary
>
/// Initializes the controls.
/// </
summary
>
/// <
remarks
>
/// Initialize your controls in this method. Do not override CreateChildControls method.
/// </
remarks
>
protected override void InitializeControls(GenericContainer container)
// Set the label values
this.ExampleLabel.Text = this.Example;
this.TitleLabel.Text = this.Title;
this.DescriptionLabel.Text = this.Description;
this.Grid.NeedDataSource += new GridNeedDataSourceEventHandler(Grid_NeedDataSource);
this.Grid.UpdateCommand += new GridCommandEventHandler(Grid_UpdateCommand);
this.Grid.InsertCommand += new GridCommandEventHandler(Grid_InsertCommand);
this.TextBox1.Text = GetCurrentSitefinityUser();
#endregion
#region Get Current User
/// <
summary
>
/// Get the full name for the currently logged-in Sitefinity user.
/// </
summary
>
/// <
returns
>String with full name of current user, or empty string if user not logged in.</
returns
>
private static string GetCurrentSitefinityUser()
Telerik.Sitefinity.Security.Web.UI.ProfileView pv = new Telerik.Sitefinity.Security.Web.UI.ProfileView();
Guid currentUserGuid = pv.CurrentUser.UserId;
if (currentUserGuid != Guid.Empty)
var userProfile = UserProfileManager.GetManager().GetUserProfiles(currentUserGuid).FirstOrDefault() as Telerik.Sitefinity.Security.Model.SitefinityProfile;
if (userProfile != null)
return userProfile.FirstName + " " + userProfile.LastName;
return String.Empty;
#endregion
#region Script methods
/// <
summary
>
/// Get list of all scripts used by control
/// </
summary
>
/// <
returns
>List of all scripts used by control</
returns
>
public override IEnumerable<
ScriptDescriptor
> GetScriptDescriptors()
var descriptor = new ScriptControlDescriptor(typeof(Attendees).FullName, this.ClientID);
descriptor.AddElementProperty("textbox", this.TextBox1.ClientID);
descriptor.AddProperty("dataFieldName", this.MetaField.FieldName); //the field name of the corresponding widget
return new[] descriptor ;
/// <
summary
>
/// Get reference to all scripts
/// </
summary
>
/// <
returns
>Reference to all scripts</
returns
>
public override IEnumerable<
System.Web.UI.ScriptReference
> GetScriptReferences()
var scripts = new List<
ScriptReference
>(base.GetScriptReferences())
new ScriptReference(Attendees.scriptReference),
new ScriptReference("Telerik.Sitefinity.Web.UI.Fields.Scripts.FieldDisplayMode.js", "Telerik.Sitefinity"),
;
return scripts;
#endregion
#region Private fields and constants
private IMetaField metaField = null;
public static readonly string layoutTemplatePath = "~/Custom/Forms/Atendees/Attendees.ascx";
public const string scriptReference = "~/Custom/Forms/Atendees/Attendees.js";
#endregion
#region RadGrid
private List<
int
> IDS
get
if (HttpContext.Current.Session["IDS" + Grid.ClientID] == null)
HttpContext.Current.Session["IDS" + Grid.ClientID] = new List<
int
>();
return (List<
int
>)HttpContext.Current.Session["IDS" + Grid.ClientID];
/// <
summary
>
/// Gets reference to the TextBox1 control
/// </
summary
>
protected virtual RadGrid Grid
get
return this.Container.GetControl<
RadGrid
>("attendees", true);
private DataTable DataSource
get
if (HttpContext.Current.Session["RadGridCS" + Grid.ClientID] == null)
DataTable data = new DataTable();
data.Columns.Add("ID", typeof(int));
data.Columns.Add("FirstName");
data.Columns.Add("LastName");
data.Columns.Add("DateOfBirth", typeof(DateTime));
data.Columns.Add("Gender");
data.Rows.Add(new object[] GenerateNewId(), "Mr.", "John Smith", new DateTime(1998, 01, 01), "M" );
data.Rows.Add(new object[] GenerateNewId(), "Mrs.", "Jane Brown", new DateTime(2003, 01, 01), "F" );
data.Rows.Add(new object[] GenerateNewId(), "Mr.", "Peter Johnson", new DateTime(2001, 01, 01), "M" );
data.Rows.Add(new object[] GenerateNewId(), "Ms.", "Diane Klive", new DateTime(1999, 01, 01), "F" );
data.Rows.Add(new object[] GenerateNewId(), "Mrs.", "Megan Hammer", new DateTime(1997, 01, 01), "F" );
HttpContext.Current.Session["RadGridCS" + Grid.ClientID] = data;
return (DataTable)HttpContext.Current.Session["RadGridCS" + Grid.ClientID];
private int GenerateNewId()
int id = 0;
if (IDS.Count > 0)
id = IDS.Max() + 1;
IDS.Add(id);
return id;
protected void Grid_UpdateCommand(object source, GridCommandEventArgs e)
GridEditableItem editedItem = e.Item as GridEditableItem;
//Locate the changed row in the DataSource
DataRow[] changedRows = DataSource.Select("ID = " + editedItem.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["ID"]);
Hashtable newValues = new Hashtable();
//The GridTableView will fill the values from all editable columns in the hash
e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem);
DataRow changedRow = changedRows[0];
changedRow.BeginEdit();
try
foreach (DictionaryEntry entry in newValues)
changedRow[(string)entry.Key] = entry.Value;
changedRow.EndEdit();
catch (Exception ex)
changedRow.CancelEdit();
Grid.Controls.Add(new LiteralControl("Unable to update the data. Reason: " + ex.Message));
e.Canceled = true;
protected void Grid_NeedDataSource(object source, GridNeedDataSourceEventArgs e)
Grid.DataSource = DataSource;
protected void Grid_InsertCommand(object source, GridCommandEventArgs e)
//Create new row in the DataSource
DataRow newRow = this.DataSource.NewRow();
GridDataInsertItem item = (GridDataInsertItem)e.Item;
//Insert new values
Hashtable newValues = new Hashtable();
newValues["FirstName"] = ((RadTextBox)item["FirstName"].FindControl("firstName")).Text;
newValues["LastName"] = ((RadTextBox)item["LastName"].FindControl("lastName")).Text;
newValues["DateOfBirth"] = ((RadDateInput)item["DateOfBirth"].FindControl("dateOfBirth")).SelectedDate;
newValues["Gender"] = ((RadMaskedTextBox)item["Gender"].FindControl("gender")).Text;
//make sure that unique primary key value is generated for the inserted row
newValues["ID"] = GenerateNewId();
try
foreach (DictionaryEntry entry in newValues)
newRow[(string)entry.Key] = entry.Value;
this.DataSource.Rows.Add(newRow);
this.DataSource.AcceptChanges();
catch (Exception ex)
Grid.Controls.Add(new LiteralControl("Unable to update the data. Reason: " + ex.Message));
e.Canceled = true;
private string DataSourceAsCSV()
var result = new StringBuilder();
for (int i = 0; i < DataSource.Columns.Count; i++)
result.Append(DataSource.Columns[i].ColumnName);
result.Append(i == DataSource.Columns.Count - 1 ? "\n" : ",");
foreach (DataRow row in DataSource.Rows)
for (int i = 0; i < DataSource.Columns.Count; i++)
result.Append(row[i].ToString());
result.Append(i == DataSource.Columns.Count - 1 ? "\n" : ",");
string s = result.ToString();
s = s.TrimEnd(new char[] '\r', '\n' );
return s;
#endregion
Hello,
The code for handling grid events have to be integrated into Attendees.js which is the client side functionality for the form control and it will get executed when the form control renders in the frontend. To subscribe and handle grid events implement event handlers for the client side events of the grid in Attendees.js initializeBase function.
SitefinityWebApp.Custom.Forms.Atendees.Attendees.initializeBase(this, [element]);