Insert/Update/Delete content items with RadGrid for ASP.NET AJAX

December 06, 2009 Digital Experience
In the following blog post I'm  going to show you how to create a custom control that uses one of the most powerful controls form Telerik.Web.UI suite - RadGrid for ASP.NET AJAX and its functionality to Insert/Update/Delete content items. The control will allow you to populate the RadGrid with items from different Generic Content providers and then manipulate the items from Sitefinity's front-end. First we need to create a template for our custom control. In this template I will put the following controls:

 

  • RadComboBox which I will use to switch the providers and rebind the RadGrid by setting the combobox' AutoPostBack property to true.
  • RadGrid for ASP.NET AJAX with several columns:
    • "Name" of the content item
    • "Content" of the items
    • "Edit"
    • "Delete"
  • RadAjaxManagerProxy and RadAjaxLoadingPanel

 

<%@ Control Language="C#"AutoEventWireup="true"CodeFile="GridContentEditorTemplate.ascx.cs"Inherits="CustomControls_GridContentEditorTemplate" %>
 
<script type="text/javascript"
 
    function RemoveItem(object, args) { 
        var combo = $find("<%= RadComboBox1.ClientID %>");         
        if (combo.findItemByText("Libraries") != null) { 
            combo.trackChanges(); 
            combo.get_items().remove(combo.findItemByText("Libraries")); 
            combo.commitChanges(); 
        } 
    } 
</script>
 
<telerik:RadAjaxManagerProxy ID="RadAjaxManager1"runat="server"
                <AjaxSettings>
                    <telerik:AjaxSetting AjaxControlID="RadGrid1"
                        <UpdatedControls>
                            <telerik:AjaxUpdatedControl ControlID="RadGrid1"LoadingPanelID="RadAjaxLoadingPanel1"/>
                        </UpdatedControls>
                    </telerik:AjaxSetting>
                </AjaxSettings>
</telerik:RadAjaxManagerProxy>
<telerik:RadAjaxLoadingPanel runat="server"ID="RadAjaxLoadingPanel1"BackgroundPosition="Center"
      <asp:Image runat="server"ID="Image1"ImageUrl="~/Images/ajax-loader.gif"/>
</telerik:RadAjaxLoadingPanel>
 
<telerik:RadComboBox ID="RadComboBox1"OnClientLoad="RemoveItem"runat="server"Skin="Black"/>
<telerik:RadGrid id="RadGrid1"runat="server"Skin="Black"  >
   <MasterTableView  EditMode="InPlace"CommandItemDisplay="TopAndBottom"AutoGenerateColumns="False"DataKeyNames="ID"AllowAutomaticInserts="true"
    <EditFormSettings InsertCaption="Add new item"CaptionFormatString="Edit Item: {0}"CaptionDataField="ID"PopUpSettings-Modal="true"/>
    <Columns>
     <telerik:GridBoundColumn HeaderText="ContentName"UniqueName="Name"></telerik:GridBoundColumn>
     <telerik:GridBoundColumn HeaderText="Content"DataField="Content"UniqueName="Content"></telerik:GridBoundColumn>
     <telerik:GridEditCommandColumn HeaderText="Edit"UniqueName="EditCommandColumn"></telerik:GridEditCommandColumn>
     <telerik:GridButtonColumn CommandName="Delete"Text="Delete"HeaderText="Delete"
      UniqueName"DeleteColumn"/>
    </Columns>
   </MasterTableView>
</telerik:RadGrid>

 

In this template I subscribed for the OnClientLoad event of RadComboBox control. This is because I need to remove one of the providers that are populated in the custom control on the server. I have to remove the Libraries provider, because it uses binary data. You can remove the provider from the list if you add a condition inside the "if" check in the GCProviders method, like:

 if (provider !=null && provider.Name != "Libraries")

The custom control:

Here I inherited from the SimpleControl class and overrode the LayoutTemplatePath. Here I set the path to my template which has RadGrid, RadComboBox, RadAjaxManagerProxy and RadAjaxLoadingPanel declarations. I created a new property for the provider name which gets the value from the RadComboBox SelectedItem.

publicoverridestring LayoutTemplatePath 
    { 
        get
        { 
            return"~/CustomControls/GridContentEditorTemplate.ascx"
        } 
    } 
 
    publicstring ProviderName 
    { 
        get
        { 
            return Combo.SelectedItem.Text; 
        } 
    } 
 

 

Inside InitializeControls I bound the RadCombobox and subscribed for RadGrid's events - PreRender, UpdateCommand, DeleteCommand, NeedDataSource, InsertCommand

protectedoverridevoid InitializeControls(System.Web.UI.Control controlContainer) 
    { 
            base.InitializeControls(controlContainer);              
            this.Combo.DataSource = GCProviders(); 
            this.Combo.AutoPostBack = true
            this.Combo.DataBind(); 
            Grid.PreRender += new EventHandler(Grid_PreRender); 
            Grid.UpdateCommand += new GridCommandEventHandler(Grid_UpdateCommand); 
            Grid.DeleteCommand += new GridCommandEventHandler(Grid_DeleteCommand); 
            Grid.NeedDataSource += new GridNeedDataSourceEventHandler(Grid_NeedDataSource); 
            Grid.InsertCommand += new GridCommandEventHandler(Grid_InsertCommand); 
            Grid.AllowMultiRowEdit = true
    } 

 

As some of the providers like GenericContent and Wiki have different metakeys for the  "Title", I had to dynamically change the GridBoundColumn value inside Grid's PreRender event handler and then rebind the grid.

void Grid_PreRender(object sender, EventArgs e) 
    { 
        foreach (GridColumn column in Grid.Columns) 
        { 
            if (column.UniqueName == "Name"
            { 
                if (this.ProviderName == WikiProviderName || this.ProviderName == GenericContentProviderName) 
                { 
                    (column as GridBoundColumn).DataField = "Name"
                    break
                } 
 
                (column as GridBoundColumn).DataField = "Title"
            } 
             
        } 
        Grid.Rebind(); 
    } 

To check the provider I created a helper method, whose value I passed inside the Insert, Update, Delete event handlers.

    { 
        if ((providerName != GenericContentProviderName) && (providerName != WikiProviderName)) 
        { 
            returntrue
        } 
        else
        { 
            returnfalse
        } 
    } 

You can find the complete code below:

 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using Telerik.Cms.Web.UI; 
using Telerik.Web.UI; 
using System.Collections; 
using Telerik.Cms.Engine; 
using Telerik.News; 
using System.Web.UI.WebControls; 
using Telerik.News.WebControls.Admin; 
 
/// <summary>
/// Summary description for GridContentEditor
/// </summary>
publicclass GridContentEditor : SimpleControl 
    public GridContentEditor() 
    { 
 
    } 
    #region Properties
 
    publicoverridestring LayoutTemplatePath 
    { 
        get
        { 
            return"~/CustomControls/GridContentEditorTemplate.ascx"
        } 
    } 
 
    publicstring ProviderName 
    { 
        get
        { 
            return Combo.SelectedItem.Text; 
        } 
    } 

    #endregion

    #region Methods
 
    protectedoverridevoid InitializeControls(System.Web.UI.Control controlContainer) 
    { 
            base.InitializeControls(controlContainer);              
            this.Combo.DataSource = GCProviders(); 
            this.Combo.AutoPostBack = true
            this.Combo.DataBind(); 
            Grid.PreRender += new EventHandler(Grid_PreRender); 
            Grid.UpdateCommand += new GridCommandEventHandler(Grid_UpdateCommand); 
            Grid.DeleteCommand += new GridCommandEventHandler(Grid_DeleteCommand); 
            Grid.NeedDataSource += new GridNeedDataSourceEventHandler(Grid_NeedDataSource); 
            Grid.InsertCommand += new GridCommandEventHandler(Grid_InsertCommand); 
           
            Grid.AllowMultiRowEdit = true
    } 
 
    void Grid_PreRender(object sender, EventArgs e) 
    { 
        foreach (GridColumn column in Grid.Columns) 
        { 
            if (column.UniqueName == "Name"
            { 
                if (this.ProviderName == WikiProviderName || this.ProviderName == GenericContentProviderName) 
                { 
                    (column as GridBoundColumn).DataField = "Name"
                    break
                } 
 
                (column as GridBoundColumn).DataField = "Title"
            } 
             
        } 
        Grid.Rebind(); 
    } 
 
    void Grid_InsertCommand(object source, GridCommandEventArgs e) 
    { 
        manager = new ContentManager(ProviderName); 
        GridEditableItem editedItem = e.Item as GridEditableItem; 
 
        Hashtable newValues = new Hashtable(); 
        e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem); 
        IContent insertContent = manager.CreateContent("text/html"); 
        if (CheckProvider(ProviderName)) 
        { 
            insertContent.SetMetaData("Title", newValues["Title"]); 
            insertContent.Content = newValues["Content"]; 
            manager.SaveContent(insertContent); 
        } 
        else
        { 
            this.MetaData = "Name"
            insertContent.SetMetaData(MetaData, newValues[MetaData]); 
            insertContent.Content = newValues["Content"]; 
            manager.SaveContent(insertContent); 
        } 
        
        Grid.Rebind(); 
    } 
 
    void Grid_UpdateCommand(object source, GridCommandEventArgs e) 
    { 
        manager = new ContentManager(ProviderName); 
        GridEditableItem editedItem = e.Item as GridEditableItem; 
        Guid cntId = (Guid)editedItem.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["ID"]; 
 
        Hashtable newValues = new Hashtable(); 
        e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem); 
        IContent UpdatedContent = manager.GetContent(cntId); 
        if (CheckProvider(ProviderName)) 
        { 
            UpdatedContent.SetMetaData("Title", newValues["Title"]); 
            UpdatedContent.Content = newValues["Content"]; 
            manager.SaveContent(UpdatedContent); 
        } 
        else
        { 
            this.MetaData = "Name"
            UpdatedContent.SetMetaData(MetaData, newValues[MetaData]); 
            UpdatedContent.Content = newValues["Content"]; 
            manager.SaveContent(UpdatedContent); 
        } 
    } 
 
 
    void Grid_DeleteCommand(object source, GridCommandEventArgs e) 
    { 
        manager = new ContentManager(ProviderName); 
        Guid deleteITemID = (Guid)e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["ID"]; 
        IContent newCnt = manager.GetContent(deleteITemID) as IContent; 
        manager.DeleteContent(newCnt.ID); 
    } 
 
    void Grid_NeedDataSource(object source, GridNeedDataSourceEventArgs e) 
    { 
        Grid.DataSource = GridDataSource(); 
    } 
 
    public IList GridDataSource() 
    { 
        manager = new ContentManager(ProviderName); 
        IList allItems = manager.GetContent(); 
        return allItems; 
    } 
 
    public IList GCProviders() 
    { 
 
        List<string> providers = new List<string>(ContentManager.Providers.Count); 
        foreach (ContentProviderBase provider in ContentManager.Providers.Values) 
        { 
            if (provider !=null
            { 
               providers.Add(provider.Name); 
            } 
 
        } 
        return providers.ToArray(); 
 
    } 
 
    privatebool CheckProvider(string providerName) 
    { 
        if ((providerName != GenericContentProviderName) && (providerName != WikiProviderName)) 
        { 
            returntrue
        } 
        else
        { 
            returnfalse
        } 
    } 

    #endregion

    #region Control references
 
    publicvirtual RadGrid Grid 
    { 
        get
        { 
            returnbase.Container.GetControl<RadGrid>("RadGrid1"true); 
        } 
    } 
 
 
    publicvirtual RadComboBox Combo 
    { 
        get
        { 
            returnbase.Container.GetControl<RadComboBox>("RadComboBox1"true); 
        } 
    } 

    #endregion


    #region Private constraints 
     
 
    private ContentManager manager; 
    privatestring GenericContentProviderName = "Generic_Content"
    privatestring WikiProviderName = "Wiki"
    privatestring MetaData; 

    #endregion
 
 
 

 

The Progress Team