Updating Values Using InPlace and EditForms Modes
There are three common techniques for updating a grid row when the user edits it using an inplace editor or edit form:
Enable automatic data source operations for the grid: This approach requires no code on your part. For a live example illustrating this approach, see Automatic Operations.
Use the table view's ExtractValuesFromItem(dictonaryObject, editedItem) method: For this approach, create an empty dictionary object and pass it as the first parameter of the ExtractValuesFromItem method. Pass the edited item as the second parameter. The ExtractValuesFromItem method fills the dictionary object with key/value pairs where each key is the DataField of an edited field column and the corresponding value is the new data entered by the user.
Fetch the data from each edited field individually through the auto-generated column editors: For this approach, you need to iterate through the editable fields of the edited row and modify the grid source on every iteration.
When using the second or third approach, you can refresh the grid content inside an UpdateCommand event handler. The following examples illustrate these techniques. They both use the same grid declaration:
<telerik:RadGrid RenderMode="Lightweight" ID="RadGrid1" runat="server" OnNeedDataSource="RadGrid1_NeedDataSource"
OnUpdateCommand="RadGrid1_UpdateCommand">
<MasterTableView AutoGenerateColumns="False" DataKeyNames="OrderID">
<Columns>
<telerik:GridBoundColumn HeaderText="OrderID" DataField="OrderID" ReadOnly="True"
UniqueName="OrderID" Display="False" />
<telerik:GridBoundColumn HeaderText="EmployeeID" DataField="EmployeeID" UniqueName="EmployeeID" />
<telerik:GridBoundColumn HeaderText="OrderDate" DataField="OrderDate" UniqueName="OrderDate" />
<telerik:GridBoundColumn HeaderText="ShipName" DataField="ShipName" UniqueName="ShipName" />
<telerik:GridEditCommandColumn UniqueName="EditCommandColumn" />
</Columns>
</MasterTableView></telerik:RadGrid><asp:Label ID="Label1" runat="server" />
Both examples also use a ViewState property (named "GridSource") for maintaining the grid's data source, and have the same NeedDataSource event handler:
private DataTable GridSource
{
get
{
Object obj = this.ViewState["_gds"];
if(obj != null)
{
return (DataTable)obj;
}
else
{
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" +
System.Web.HttpContext.Current.Server.MapPath( "~/App_Data/Nwind.mdb"));
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.SelectCommand = new OleDbCommand("SELECT TOP 10 OrderID, EmployeeID, OrderDate, ShipName FROM Orders", conn);
DataTable table = new DataTable();
conn.Open();
try
{
adapter.Fill(table);
}
finally
{
conn.Close();
}
this.ViewState[ "_gds"] = table;
return table;
}
}
}
protected void RadGrid1_NeedDataSource(object source,
Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
RadGrid1.DataSource = this.GridSource;
}
Private ReadOnly Property GridSource As DataTable
Get
Dim obj As Object = Me.ViewState("_gds")
If (Not obj Is Nothing) Then
Return CType(obj, DataTable)
Else
Dim conn As New OleDbConnection"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Nwind.mdb")
Dim conn As New OleDbConnection(cnctnString)
Dim adapter As New OleDbDataAdapter()
adapter.SelectCommand = New OleDbCommand("SELECT TOP 10 OrderID, EmployeeID, OrderDate, ShipName FROM Orders", conn)
Dim table As New DataTable()
conn.Open()
Try
adapter.Fill(table)
Finally
conn.Close()
End Try
Me.ViewState("_gds") = table
Return table
End If
End Get
End Property
Private Sub RadGrid1_NeedDataSource(ByVal source As Object, ByVal e As Telerik.Web.UI.GridNeedDataSourceEventArgs) Handles RadGrid1.NeedDataSource
RadGrid1.DataSource = Me.GridSource
End Sub
Example 1: Using ExtractValuesFromItem
protected void RadGrid1_UpdateCommand(object source,
Telerik.Web.UI.GridCommandEventArgs e)
{
GridEditableItem editedItem = e.Item as GridEditableItem;
DataTable ordersTable = this.GridSource;
//Locate the changed row in the DataSource
DataRow[] changedRows = ordersTable.Select("OrderID = " +
editedItem.OwnerTableView.DataKeyValues[editedItem.ItemIndex]["OrderID"].ToString());
if (changedRows.Length != 1)
{
this.Label1.Text += "Unable to locate the Order for updating.";
e.Canceled = true;
return;
}
//Update new values
Hashtable newValues = new Hashtable();
e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem);
changedRows[0].BeginEdit();
try
{
foreach (DictionaryEntry entry in newValues)
{
changedRows[0][(string)entry.Key] = entry.Value;
}
changedRows[0].EndEdit();
}
catch (Exception ex)
{
changedRows[0].CancelEdit();
Label1.Text += "Unable to update Orders. Reason: " + ex.Message;
e.Canceled = true;
}
}
Protected Sub RadGrid1_UpdateCommand(ByVal source As Object, ByVal e As Telerik.Web.UI.GridCommandEventArgs)
Dim editedItem As GridEditableItem = TryCast(e.Item, GridEditableItem)
Dim ordersTable As DataTable = Me.GridSource
'Locate the changed row in the DataSource
Dim changedRows As DataRow() = ordersTable.Select("OrderID = " + editedItem.OwnerTableView.DataKeyValues(editedItem.ItemIndex)("OrderID").ToString())
If changedRows.Length <> 1 Then
Me.Label1.Text += "Unable to locate the Order for updating."
e.Canceled = True
Return
End If
'Update new values
Dim newValues As New Hashtable()
e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem)
changedRows(0).BeginEdit()
Try
For Each entry As DictionaryEntry In newValues
changedRows(0)(DirectCast(entry.Key, String)) = entry.Value
Next
changedRows(0).EndEdit()
Catch ex As Exception
changedRows(0).CancelEdit()
Label1.Text += "Unable to update Orders. Reason: " + ex.Message
e.Canceled = True
End Try
End Sub
Example 2: Using the auto-generated column editors
private void RadGrid1_UpdateCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
{
Label1.Text += " Table to be updated: " + e.Item.OwnerTableView.DataMember + "<br>";
GridEditableItem editedItem = e.Item as GridEditableItem;
GridEditManager editMan = editedItem.EditManager;
foreach( GridColumn column in e.Item.OwnerTableView.RenderColumns )
{
if ( column is IGridEditableColumn )
{
IGridEditableColumn editableCol = (column as IGridEditableColumn);
if ( editableCol.IsEditable )
{
IGridColumnEditor editor = editMan.GetColumnEditor( editableCol );
string editorText = "unknown";
object editorValue = null;
if ( editor is GridTextColumnEditor )
{
editorText = (editor as GridTextColumnEditor).Text;
editorValue = (editor as GridTextColumnEditor).Text;
}
if ( editor is GridBoolColumnEditor )
{
editorText = (editor as GridBoolColumnEditor).Value.ToString();
editorValue = (editor as GridBoolColumnEditor).Value;
}
if ( editor is GridDropDownColumnEditor )
{
editorText = (editor as GridDropDownColumnEditor).SelectedText + "; " +
(editor as GridDropDownColumnEditor).SelectedValue;
editorValue = (editor as GridDropDownColumnEditor).SelectedValue;
}
try
{
DataRow[] changedRows = this.GridSource.Select( "OrderID = " + editedItem.OwnerTableView.DataKeyValues[editedItem.ItemIndex]["OrderID"].ToString());
changedRows[0][column.UniqueName] = editorValue;
this.GridSource.AcceptChanges();
}
catch(Exception ex)
{
Label1.Text = "<strong>Unable to set value of column '" + column.UniqueName + "'</strong> - " + ex.Message;
e.Canceled = true;
break;
}
}
}
}
}
Private Sub RadGrid1_UpdateCommand(ByVal source As System.Object, ByVal e As Telerik.Web.UI.GridCommandEventArgs) Handles RadGrid1.UpdateCommand
Label1.Text += " Table to be updated: " + e.Item.OwnerTableView.DataMember + "<br>"
Dim editedItem As GridEditableItem = CType(e.Item, GridEditableItem)
Dim editMan As GridEditManager = editedItem.EditManager
Dim column As GridColumn
For Each column In e.Item.OwnerTableView.RenderColumns
If TypeOf column Is IGridEditableColumn Then
Dim editableCol As IGridEditableColumn = CType(column, IGridEditableColumn)
If (editableCol.IsEditable) Then
Dim editor As IGridColumnEditor = editMan.GetColumnEditor(editableCol)
Dim editorText As String = "unknown"
Dim editorValue As Object = Nothing
If (TypeOf editor Is GridTextColumnEditor) Then
editorText = CType(editor, GridTextColumnEditor).Text
editorValue = CType(editor, GridTextColumnEditor).Text
End If
If (TypeOf editor Is GridBoolColumnEditor) Then
editorText = CType(editor, GridBoolColumnEditor).Value.ToString()
editorValue = CType(editor, GridBoolColumnEditor).Value
End If
If (TypeOf editor Is GridDropDownColumnEditor) Then
editorText = CType(editor, GridDropDownColumnEditor).SelectedText + "; " + CType(editor, GridDropDownColumnEditor).SelectedValue
editorValue = CType(editor, GridDropDownColumnEditor).SelectedValue
End If
Try
Dim changedRows As DataRow() = Me.GridSource.Select("OrderID = " + editedItem.OwnerTableView.DataKeyValues(editedItem.ItemIndex)("OrderID").ToString())
changedRows(0)(column.UniqueName) = editorValue
Me.GridSource.AcceptChanges()
Catch ex As Exception
Label1.Text = "<strong>Unable to set value of column '" + column.UniqueName + "'</strong> - " + ex.Message
e.Canceled = True
End Try
End If
End If
Next
End Sub
Extracting data from a Template Column
For GridTemplateColumn instances, the ExtractValues()
method will provide data in case there is a <%#Bind("someColumn") %>
expression in the EditItemTemplate
or InsertItemTemplate
. The key in the hashtable will be the field from the binding expression.
For example, the columns below will populate the hash table with data for the "someField" and "moreData" respectively, even though both have the same DataField
setting.
<telerik:GridTemplateColumn HeaderText="template column" DataField="someColumn" UniqueName="myTemplateColumn">
<ItemTemplate>
<%#Eval("someColumn") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="textbox1" Text='<%#Bind("someColumn") %>' />
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox runat="server" ID="textbox1" Text='<%#Bind("someColumn") %>' />
</InsertItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridTemplateColumn HeaderText="second template column" DataField="someColumn" UniqueName="myTemplateColumn2">
<ItemTemplate>
<%#Eval("moreData") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="textbox2" Text='<%#Bind("moreData") %>' />
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox runat="server" ID="textbox2" Text='<%#Bind("moreData") %>' />
</InsertItemTemplate>
</telerik:GridTemplateColumn>
For more complex scenarios or when you cannot use binding expressions, you need to use .FindControl()
to access the custom controls and extract data: Accessing Controls in Template Column.