RadGrid for ASP.NET

Custom edit forms Send comments on this topic.
Insert/Update/Delete records > Edit mode > Custom edit forms

Glossary Item Box

1. UserControls as Edit Form

You have two options with regard to the implementation of the web user control, depending on the desired mode of exchanging data between Telerik RadGrid and the UserControl instances:

  • binding directly to RadGrid's Item
  • declaring and binding to DataItem property of the UserControl

Binding to RadGrid Item

In order to access data from the object the edit form is binding to, the binding expression used in the UserControl should be implemented in a slightly different than the traditional way. The problem is that the controls are inside UserControl. And the UserControl is in turn a binding container. You have to bind to GridEditFormItem instead of UserControl. That is why the binding expression should be designed to calculate properties for the parent's binding container.

Here is an example of declaration of a TextBox server control that should be bound to the Region property of the DataItem in RadGrid

ASPX/ASCX Copy Code
<asp:TextBox
 
id="TextBox1"
 
runat="server"
 
Text='<%# DataBinder.Eval( Container, "Parent.BindingContainer.DataItem.Region") %>'
        


Using the DataItem Property

If using this kind of expression seems uncomfortable in some way, you have another option. Your user control should implement a property with name DataItem. This property should be public and assignable from the type of the object that constructs the datasource for RadGrid.

For example, if you bind to a DataSet, the DataItem can be declared as:

C# Copy Code
  private object _dataItem = null;

  
public object DataItem
  {
   get
   {
    
return this._dataItem;
   }
   set
   {
    
this._dataItem = value;
   }
  }
VB.NET Copy Code
   private _dataItem As Object = Nothing

   Public Property DataItem As Object
    Get
     Return Me._dataItem
    End Get
    Set (ByVal value As Object)
     Me._dataItem = value
    End Set
   End Property

 

Note that DataItem should be declared as of type object. After loading the UserControl, RadGrid will try to assign the value of the DataItem property. This allows you to write in the user control code an expression binding the text of a TextBox control to the Country property of the datasource item:

ASPX/ASCX Copy Code
<asp:TextBox
    
id="TextBox1"
    
runat="server"
    
Text='<%# DataBinder.Eval( Container, "DataItem.Country" ) %>'>
</
asp:TextBox>
        

and the same TextBox using ASP.NET 2.0 syntax

ASPX/ASCX Copy Code
<asp:TextBox
    
id="TextBox1"
    
runat="server"
    
Text='<%# Eval( "Country" ) %>'>
</
asp:TextBox>
        

 

 Referring UserControl in EditForms

In some scenarios you may need to have a reference to the UserControl when the Update button is pressed. Having in mind that the UserControl is a Container placed in a Container (EditFormCell), you should refer to the control this way:

C# Copy Code
UserControl MyUserControl = editFormItem.FindControl(GridEditFormItem.EditFormUserControlID) as UserControl;
        
VB.NET Copy Code
Dim MyUserControl As UserControl = CType(editFormItem.FindControl(GridEditFormItem.EditFormUserControlID), UserControl)


Accessing the edited grid item from the user control

When Telerik RadGrid loads the UserControl Edit Form, the UserControl has full access to the properties of the grid item it is loaded in:

Me.Parent.NamingContainer  would reference the currently edited item:

C# Copy Code
GridEditableItem editedItem = this.Parent.NamingContainer
        
VB.NET Copy Code
Dim editedItem As GridEditableItem = Me.Parent.NamingContainer

Then you have access to all properties of the item - cell text values, DataItem object (available in DataBinding event handler), etc.

 

Accessing the page

You can access the Page which holds the grid instance from within the user control. In the example below Page is a reference to the page object:

C# Copy Code
MyPageClassName myPage = this.Page
        
VB.NET Copy Code
Dim myPage as MyPageClassName = Me.Page

Now you can reference all properties of the actual Page.

Binding selected values for MS DropDownLists when having user control custom edit form

In order to select the proper item in dropdown editor (part of user control custom edit form) when grid item is switched in edit mode, you can wire the DataBinding event of the user control. Then inside its handler you can bind the dropdown list and set its SelectedIndex accordingly.

Below is the code used in the user control edit form from online demo of the product:


VB.NET Copy Code
Private Sub EmployeeDetails_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.DataBinding

  Dim tocs As New ArrayList(New String() {"Dr.", "Mr.", "Mrs.", "Ms."})
  ddlTOC.DataSource = tocs
  ddlTOC.DataBind()

  ddlTOC.SelectedIndex = tocs.IndexOf(DataBinder.Eval(DataItem, "TitleOfCourtesy").ToString())
  ddlTOC.DataSource = Nothing

End Sub 'EmployeeDetails_DataBinding

 

 

C# Copy Code
private void EmployeeDetails_DataBinding(object sender, System.EventArgs e)
{
 String [] tocs =
new string[] {"Dr.", "Mr.", "Mrs.", "Ms."};    
 ddlTOC.DataSource = tocs;    
 ddlTOC.DataBind();    
   
 ddlTOC.SelectedIndex = tocs.IndexOf(DataBinder.Eval(DataItem,
"TitleOfCourtesy").ToString());    
 ddlTOC.DataSource =
null;    
}


Note: An important detail is to assign empty data source for the combo in order to prevent binding it again at a later stage (when the rest of the edited item content is bound). The same conventions stand for nested user controls inside WebUserControl custom edit form or other controls such as listboxes, radiobutton lists, checkbox lists, etc.

 

Setting properties without the usage of binding expressions

You can hook the ItemDataBound event of the grid to access the controls/properties of the user control edit form. In the respective handler, you should check whether the type of item is GridEditFormItem and also whether the item is in edit mode. Then you can locate the user control inside the GridEditFormItem and make the modifications you wish. Here is an example which will set text for TextBox with ID = "TextBox1" which resides inside the user control:

C# Copy Code
private void RadGrid1_ItemDataBound(object sender, Telerik.WebControls.GridItemEventArgs e)
{
  
if(e.Item is GridEditFormItem && e.Item.IsInEditMode)
  {
   UserControl MyUserControl = e.Item.FindControl
  (GridEditFormItem.EditFormUserControlID)
as
   
UserControl;
   TextBox box = (TextBox)MyUserControl.FindControl(
"TextBox1");
   box.Text =
"default text";
  }
}
        
VB.NET Copy Code
Private Sub RadGrid1_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.WebControls.GridItemEventArgs) Handles RadGrid1.ItemDataBound
 If (TypeOf e.Item Is GridEditFormItem AndAlso e.Item.IsInEditMode) Then
  Dim MyUserControl As UserControl = CType(e.Item.FindControl(GridEditFormItem.EditFormUserControlID),UserControl)
  Dim box As TextBox = CType(MyUserControl.FindControl("TextBox1"),TextBox)
  box.Text = "default text"
 End If
End Sub

 

2. FormTemplate

   
Binding to RadGrid Item

In order to access data from the object to which the edit form is binding to, you can use the standard binding expression syntax for .NET 1.x:

ASPX/ASCX Copy Code
<editformsettings editformtype="Template">

   
<editcolumn uniquename="EditCommandColumn1"></editcolumn>

      
<formtemplate>
           
------------------------
          
<asp:textbox id="TextBox7" runat="server" text='<%# DataBinder.Eval( Container, "DataItem.Country" ) %>'>

          
</asp:textbox>

          
-------------------------

     
</formtemplate>

<
editformsettings>

Or the newly introduced Bind() syntax available under ASP.NET 2.0:

<editformsettings editformtype="Template">

   
<editcolumn uniquename="EditCommandColumn1"></editcolumn>

      
<formtemplate>
           
------------------------
          
<asp:textbox id="TextBox7" runat="server" text='<%# Bind(“%>'>

          
</asp:textbox>

          
-------------------------

     
</formtemplate>

<
editformsettings>
        

Here are two online examples (in C# and VB.NET) which demonstrate this approach:

http://www.telerik.com/demos/aspnet/Grid/Examples/DataEditing/TemplateFormUpdate/DefaultCS.aspx

http://www.telerik.com/demos/aspnet/Grid/Examples/DataEditing/TemplateFormUpdate/DefaultVB.aspx


 

Note: with the Bind() syntax mentioned above you will be able to extract the updated by the user value from the FormTemplate (without any additional code) and pass it directly for the Automatic update operation through the DataSource control. See also Automatic DataSource operations

Setting properties without the usage of binding expressions

You can hook the ItemDataBound event of the grid to access the controls/properties of the FormTemplate edit form. In the respective handler, you should check whether the type of item is GridEditFormItem and also whether it is in edit mode. Then you can locate the control inside the GridEditFormItem and make the modifications you wish. Here is an example which will set text for TextBox with ID = "TextBox1" which resides inside the FormTemplate:

C# Copy Code
private void RadGrid1_ItemDataBound(object sender, Telerik.WebControls.GridItemEventArgs e)
{
 
if (e.Item Is GridEditFormItem && e.Item.IsInEditMode)
 {
    GridEditFormItem editFormItem = e.Item
as GridEditFormItem;
    TextBox box = editFormItem.FindControl(
"TextBox1") as TextBox;
    box.Text =
"default text";
 }
}
        
VB.NET Copy Code
Private Sub RadGrid1_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.WebControls.GridItemEventArgs) Handles RadGrid1.ItemDataBound
  If (TypeOf e.Item Is GridEditFormItem AndAlso e.Item.IsInEditMode) Then
     Dim editFormItem As GridEditFormItem = CType(e.Item, GridEditFormItem)
     Dim box As TextBox = CType(editFormItem.FindControl("TextBox1"), TextBox)
     box.Text = "default text"
  End If
End Sub

Access to the parent item of the GridEditFormItem (FormTemplate)

C# Copy Code
GridEditableItem parentItem = editFormItem.ParentItem as GridEditableItem;
        
VB.NET Copy Code
Dim parentItem as GridEditableItem = CType(editFormItem.ParentItem, GridEditableItem)

Then through the parentItem object you will have access to all properties of the item (cell text values or other).

 

Creating FormTemplate custom edit form programmatically


Basically, you will need to design a class which implements the IBindableTemplate interface and assign an instance of that class to the EditFormSettings.FormTemplate property of the master/detail table. Additionally, you can expose ExtractValues method for that class which to extract the data from the edit form on update/insert operation.

Below are the code snippets of a sample approach:

C# Copy Code
using System;  
using System.Data;  
using System.Configuration;  
using System.Web;  
using System.Web.Security;  
using System.Web.UI;  
using System.Web.UI.WebControls;  
using System.Web.UI.WebControls.WebParts;  
using System.Web.UI.HtmlControls;  
using Telerik.WebControls;  
using System.Collections.Specialized;  
using System.Collections;  
 
public partial class Default2 : System.Web.UI.Page {  
     
   
private RadGrid grid1;  
     
   
protected void Page_Init(object sender, EventArgs e) {  
       grid1 =
new RadGrid();  
       grid1.DataSourceID =
"SqlDataSource1";  
       grid1.MasterTableView.EditFormSettings.EditFormType = GridEditFormType.Template;  
       grid1.MasterTableView.EditFormSettings.FormTemplate =
new MyEditFormTemplate();  
       grid1.MasterTableView.Columns.Add(
new GridEditCommandColumn());  
       grid1.MasterTableView.DataKeyNames =
new string[] {  
               
"ProviderName"};  
       placeholder1.Controls.Add(grid1);  
   }  
     
   
private void grid1_UpdateCommand(object source, GridCommandEventArgs e) {  
       GridEditableItem ei = ((GridEditableItem)(e.Item));  
       Hashtable t1 =
new Hashtable();  
       ei.ExtractValues(t1);  
   }  
     
   
public class MyEditFormTemplate : IBindableTemplate {  
         
       
public void InstantiateIn(Control container) {  
           GridEditFormItem item = ((GridEditFormItem)(container.NamingContainer));  
           Button btn1 =
new Button();  
           btn1.CommandName =
"Update";  
           TextBox tb1 =
new TextBox();  
           tb1.ID =
"MyTextBox";  
           tb1.Text = item.ParentItem.OwnerTableView.DataKeyValues(((GridDataItem)(item.ParentItem)).ItemIndex)[
"ProviderName"].ToString();  
           container.Controls.Add(tb1);  
           container.Controls.Add(btn1);  
       }  
         
       
public System.Collections.Specialized.IOrderedDictionary ExtractValues(System.Web.UI.Control container) {  
           OrderedDictionary od =
new OrderedDictionary();  
           od.Add(
"ProviderName", ((TextBox)(((GridEditFormItem)(container)).FindControl("MyTextBox"))).Text);  
           
return od;  
       }  
   }  
}   

 

 

VB.NET Copy Code
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports Telerik.WebControls
Imports System.Collections.Specialized
Imports System.Collections
Public Partial Class Default2
 Inherits System.Web.UI.Page
 Private grid1 As RadGrid
 Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)
  grid1 = New RadGrid()
  grid1.DataSourceID = "SqlDataSource1"
  grid1.MasterTableView.EditFormSettings.EditFormType = GridEditFormType.Template
  grid1.MasterTableView.EditFormSettings.FormTemplate = New MyEditFormTemplate()
  grid1.MasterTableView.Columns.Add(New GridEditCommandColumn())
  grid1.MasterTableView.DataKeyNames = New String() {"ProviderName"}
  placeholder1.Controls.Add(grid1)
 End Sub
 Private Sub grid1_UpdateCommand(ByVal source As Object, ByVal e As GridCommandEventArgs)
  Dim ei As GridEditableItem = (DirectCast((e.Item), GridEditableItem))
  Dim t1 As New Hashtable()
  ei.ExtractValues(t1)
 End Sub
 Public Class MyEditFormTemplate
  Implements IBindableTemplate
  Public Sub InstantiateIn(ByVal container As Control)
   Dim item As GridEditFormItem = (DirectCast((container.NamingContainer), GridEditFormItem))
   Dim btn1 As New Button()
   btn1.CommandName = "Update"
   Dim tb1 As New TextBox()
   tb1.ID = "MyTextBox"
   tb1.Text = item.ParentItem.OwnerTableView.DataKeyValues((DirectCast((item.ParentItem), GridDataItem)).ItemIndex)("ProviderName").ToString()
   container.Controls.Add(tb1)
   container.Controls.Add(btn1)
  End Sub
  Public Function ExtractValues(ByVal container As System.Web.UI.Control) As System.Collections.Specialized.IOrderedDictionary
   Dim od As New OrderedDictionary()
   od.Add("ProviderName", (DirectCast(((DirectCast((container), GridEditFormItem)).FindControl("MyTextBox")), TextBox)).Text)
   Return od
  End Function
 End Class
End Class