Performing Batch Updates
A common scenario is to force several grid items in edit mode and then update them on single button click.
In the example below there is UpdateAll button in the grid command item template. The visitor can edit several grid items by pressing the edit button for each item(the Update button will be hidden and only the Cancel button will be present in edit mode). After editing the content of the grid items, a batch update is triggered when hitting the UpdateAll button in the command item template (the update is executed in the ItemCommand event handler when e.CommandName = UpdateAll). The idea is to iterate through all items in the EditItems collection of the grid and update their data with the new values in the grid data source.
<telerik:RadGrid RenderMode="Lightweight" ID="RadGrid1" runat="server" AllowMultiRowEdit="True" DataSourceID="SqlDataSource1"
OnItemCommand="RadGrid1_ItemCommand" OnItemDataBound="RadGrid1_ItemDataBound">
<MasterTableView DataKeyNames="CustomerID" AutoGenerateColumns="false" EditMode="InPlace"
CommandItemDisplay="TopAndBottom">
<Columns>
<telerik:GridBoundColumn ReadOnly="true" DataField="CustomerID" UniqueName="CustomerID"
HeaderText="CustomerID">
</telerik:GridBoundColumn>
<telerik:GridBoundColumn DataField="ContactName" UniqueName="ContactName" HeaderText="ContactName">
</telerik:GridBoundColumn>
<telerik:GridEditCommandColumn UniqueName="EditCommandColumn" />
</Columns>
<CommandItemTemplate>
<asp:Button runat="server" ID="UpdateAll" Text="Update All" CommandName="UpdateAll" /></CommandItemTemplate>
</MasterTableView>
</telerik:RadGrid>
<asp:SqlDataSource ID="SqlDataSource1" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
ProviderName="System.Data.SqlClient" SelectCommand="SELECT TOP 10 CustomerID, ContactName FROM Customers"
runat="server"></asp:SqlDataSource>
protected void RadGrid1_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
{
if (e.CommandName == "UpdateAll")
{
foreach (GridEditableItem editedItem in RadGrid1.EditItems)
{
Hashtable newValues = new Hashtable();
//The GridTableView will fill the values from all editable columns in the hash
e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem);
SqlDataSource1.UpdateCommand = String.Format("Update Customers SET ContactName='{0}' WHERE CustomerID='{1}'"
, newValues["ContactName"], editedItem.GetDataKeyValue("CustomerID").ToString());
SqlDataSource1.Update();
editedItem.Edit = false;
}
}
RadGrid1.Rebind();
}
protected void RadGrid1_ItemDataBound(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
if (e.Item is GridDataItem && e.Item.IsInEditMode)
{
GridDataItem dataItem = e.Item as GridDataItem;
//Hides the Update button for each edit form
dataItem["EditCommandColumn"].Controls[0].Visible = false;
}
}
Protected Sub RadGrid1_ItemCommand(ByVal source As Object, ByVal e As Telerik.Web.UI.GridCommandEventArgs)
If (e.CommandName = "UpdateAll") Then
For Each editedItem As GridEditableItem In RadGrid1.EditItems
Dim newValues As Hashtable = New Hashtable
'The GridTableView will fill the values from all editable columns in the hash
e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem)
SqlDataSource1.UpdateCommand = String.Format("Update Customers SET ContactName='{0}' WHERE CustomerID='{1}'", newValues("ContactName"), editedItem.GetDataKeyValue("CustomerID").ToString())
SqlDataSource1.Update()
editedItem.Edit = False
Next
End If
RadGrid1.Rebind()
End Sub
Protected Sub RadGrid1_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs)
If (TypeOf e.Item Is GridDataItem AndAlso e.Item.IsInEditMode) Then
Dim dataItem As GridDataItem = CType(e.Item, GridDataItem)
'Hides the Update button for each edit form
dataItem("EditCommandColumn").Controls(0).Visible = False
End If
End Sub
Client-side editing with batch updateOne possible implementation is demonstrated on this demo of RadGrid for ASP.NET AJAX (review the code implementation for details). The general idea is to:
Wire the ondblclick event of the grid cells
Togglethe visibility of the column editors and store the end user changes
Push the altered content on the server and update the data source
Furthermore, a user-friendly confirm dialog will be displayed to prompt whether the updates should be propagated or discarded when you perform sorting, paging, etc. operation. The example uses RadAjaxManager instance to ajaxify the grid and perform RadAjaxManagerClientObject.ajaxRequest(args) calls. These calls are invoked in the ProcessChanges and CancelChanges client methods and the data in the source is refreshed inside the OnAjaxRequest handler on the server. The sample also features RadInputManager and RadFormDecorator which are used to filter the numeric entries and style the textboxes, checkboxes and dropdowns.
Another approach is presented in the paragraph below.
The following sample takes advantage of the editSelected() client side method, to put the control in edit mode for all items that were previously selected. Once the control is in edit mode, the user can enter data in the edit fields, and then after clicking a button in the command template, all the data will be updated from the code-behind section.
<script type="text/javascript">
function ToggleEditSelected() {
var grid = $find("RadGrid1");
var masterTable = grid.get_masterTableView();
masterTable.editSelectedItems();
}
</script>
<telerik:RadGrid RenderMode="Lightweight" AllowMultiRowEdit="true"
AllowMultiRowSelection="true"
ID="RadGrid1" OnNeedDataSource="RadGrid1_NeedDataSource" runat="server"
OnItemCommand="RadGrid1_ItemCommand" >
<MasterTableView DataKeyNames="CustomerID" CommandItemDisplay="Top">
<CommandItemTemplate>
<a href="javascript:void(0);" onclick="ToggleEditSelected();">
Edit selected</a>
<asp:LinkButton ID="LinkButton1" CommandName="UpdateChanges" runat="server">Update all</asp:LinkButton>
</CommandItemTemplate>
</MasterTableView>
<ClientSettings>
<Selecting AllowRowSelect="True"></Selecting>
</ClientSettings>
</telerik:RadGrid>
private void InitializeComponent()
{
this.RadGrid1.NeedDataSource += new Telerik.Web.UI.GridNeedDataSourceEventHandler(this.RadGrid1_NeedDataSource);
this.RadGrid1.ItemCommand += new Telerik.Web.UI.GridCommandEventHandler(this.RadGrid1_ItemCommand);
this.Load += new System.EventHandler(this.Page_Load);
}
public DataTable CustomersTable
{
get
{
DataTable res = (DataTable)this.Session["CustomersTable"];
if (res == null)
{
res = DataSourceHelperCS.GetDataTable("SELECT TOP 5 [CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City] FROM [Customers]");
this.Session["CustomersTable"] = res;
}
return res;
}
}
private void RadGrid1_NeedDataSource(object source, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
RadGrid1.DataSource = this.CustomersTable;
}
protected void RadGrid1_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
{
if (e.CommandName == "UpdateChanges")
{
if (RadGrid1.EditIndexes.Count == 0)
{
return;
}
foreach (GridDataItem item in RadGrid1.EditItems)
{
this.UpdateItem(item.EditFormItem);
}
e.Item.OwnerTableView.Rebind();
return;
}
}
private void UpdateItem(GridEditableItem editedItem)
{
DataTable customersTable = this.CustomersTable;
//Locate the changed row in the DataSource
DataRow[] changedRows = customersTable.Select("CustomerID = '" + editedItem.GetDataKeyValue("CustomerID").ToString() + "'");
if (changedRows.Length != 1)
{
return;
}
//Update new values
Hashtable newValues = new Hashtable();
//The GridTableView will fill the values from all editable columns in the hash
editedItem.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)
{
changedRow.CancelEdit();
}
}
Public ReadOnly Property CustomersTable As DataTable
Get
Dim res As DataTable = CType(Me.Session("CustomersTable"), DataTable)
If res Is Nothing Then
res = DataSourceHelperVB.GetDataTable("SELECT TOP 5 [CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City", FROM(Customers), ")", this.Session[CustomersTableUnknown=res)
End If
Return res
End Get
End Property
Private Sub InitializeComponent()
AddHandler RadGrid1.NeedDataSource, AddressOf Me.RadGrid1_NeedDataSource
AddHandler RadGrid1.ItemCommand, AddressOf Me.RadGrid1_ItemCommand
AddHandler Load, AddressOf Me.Page_Load
End Sub
Private Sub RadGrid1_NeedDataSource(ByVal source As Object, ByVal e As Telerik.Web.UI.GridNeedDataSourceEventArgs)
RadGrid1.DataSource = Me.CustomersTable
End Sub
Protected Sub RadGrid1_ItemCommand(ByVal source As Object, ByVal e As Telerik.Web.UI.GridCommandEventArgs)
If (e.CommandName = "UpdateChanges") Then
If (RadGrid1.EditIndexes.Count = 0) Then
Return
End If
For Each item As GridDataItem In RadGrid1.EditItems
Me.UpdateItem(item.EditFormItem)
Next
e.Item.OwnerTableView.Rebind()
Return
End If
End Sub
Private Sub UpdateItem(ByVal editedItem As GridEditableItem)
Dim customersTable As DataTable = Me.CustomersTable
'Locate the changed row in the DataSource
Dim changedRows() As DataRow = customersTable.Select(("CustomerID = '" _
+ (editedItem.GetDataKeyValue("CustomerID").ToString + "'")))
If (changedRows.Length <> 1) Then
Return
End If
'Update new values
Dim newValues As Hashtable = New Hashtable
'The GridTableView will fill the values from all editable columns in the hash
editedItem.OwnerTableView.ExtractValuesFromItem(newValues, editedItem)
Dim changedRow As DataRow = changedRows(0)
changedRow.BeginEdit()
Try
For Each entry As DictionaryEntry In newValues
changedRow(CType(entry.Key, String)) = entry.Value
Next
changedRow.EndEdit()
Catch Ex As Exception
changedRow.CancelEdit()
End Try
End Sub