Use FCKEditor to update record in ASP.NET

I wrote two posts on the integration and customization of FCKEditor in ASP.NET web application, today I will show how to use FCKEditor to update record.

This demo consists of a GridView with an Edit button for each row which upon clicked will load a DetailsView, and the DetailsView has a field called Note where the FCKEditor is used to update it.

1. GridView layout:

<asp:GridView ID="gvCustomerList" runat="server" AutoGenerateColumns="False"
    CssClass="grid" Width="100%" CellPadding="6" DataKeyNames="CustomerID">
    <Columns>
        <asp:TemplateField HeaderText="Action">
            <ItemTemplate>
                <asp:Button ID="btnEdit" runat="server" CommandName="cmdEdit"
                        Text="Edit" CommandArgument='<%# Eval("CustomerID") %>' />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CustomerID" HeaderText="ID" />
        <asp:BoundField HeaderText="First Name" DataField="CustomerFirstName" />
        <asp:BoundField HeaderText="Last Name" DataField="CustomerLastName" />
        <asp:BoundField HeaderText="Phone" DataField="CustomerPhone" />
        <asp:BoundField HeaderText="Email" DataField="CustomerEmail" />
        <asp:BoundField HeaderText="Note" DataField="Note" HtmlEncode="False" />
    </Columns>
    <RowStyle CssClass="grid-item" />
    <AlternatingRowStyle CssClass="grid-alternating-item" />
    <HeaderStyle CssClass="grid-header" />
</asp:GridView>

2. DetailsView layout:

<asp:Panel ID="pnlEditCustomer" runat="server" CssClass="popup-div-background">
    <asp:Panel ID="pnlCustomerDetails" runat="server" CssClass="popup-div-front">
    <asp:DetailsView ID="dvEditCustomer" runat="server" DefaultMode="Edit"
        AutoGenerateRows="False" Width="100%" DataKeyNames="CustomerID">
        <Fields>
            <asp:BoundField DataField="CustomerID" HeaderText="Customer ID" ReadOnly="True" />
            <asp:BoundField DataField="CustomerFirstName" HeaderText="First Name" ReadOnly="True" />
            <asp:BoundField DataField="CustomerLastName" HeaderText="Last Name" ReadOnly="True" />
            <asp:BoundField DataField="CustomerPhone" HeaderText="Phone" ReadOnly="True" />
            <asp:BoundField DataField="CustomerEmail" HeaderText="Email" ReadOnly="True" />
            <asp:TemplateField HeaderText="Note">
                <ItemTemplate>
                    <FCKeditorV2:FCKeditor ID="fckEditorNote" runat="server"
                    Value='<%#Bind("Note") %>' ToolbarSet="Basic">
                    </FCKeditorV2:FCKeditor>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:CommandField ShowEditButton="True" />
        </Fields>
    </asp:DetailsView>
    </asp:Panel>
</asp:Panel>

Both the GridView and DetailsView are defined in an UpdatePanel. The reason that the DetailsView is within two Panel controls is that I use AJAX ModalPopupExtender to load the DetailsView when user clicks the Edit button in the GridView. Here is the ModalPopupExtender:

4. ModalPopupExtender for loading the DetailsView

<cc1:ModalPopupExtender ID="mpeEditEmployee" runat="server"
    TargetControlID="lblPopupTargetID"
    PopupControlID="pnlEditCustomer">
</cc1:ModalPopupExtender>

TargetControlID=”lblPopupTargetID” is a trick for using AJAX ModalPopupExtender with GridView and “lblPopupTargetID” is a Label control in the UpdatePanel hidden by CSS style. The reason of this trick is that the Edit button that triggers the ModalPopup is defined in a TemplateField of the GridView and cannot be assigned directly to TargetControlID property, and you cannot assign this property on the fly either. However, if we assign TargetControlID to a hidden Label, how can we trigger the ModalPopup? The answer is we will trigger it from code behind by using ModalPopupExtender.Show() function.

5. Code Behind Functions

5.1 Bind GridView

Let’s add a function called LoadCustomerList() to bind the GridView control. This function will be called in Page_Load event handler:

Private Sub LoadCustomerList()
    Dim dt As New DataTable

    If (Session("CustomerDT") Is Nothing) Then
        Dim dc As New DataColumn("CustomerID", _
                System.Type.GetType("System.Int32"))
        dt.Columns.Add(dc)

        dc = New DataColumn("CustomerFirstName", _
            System.Type.GetType("System.String"))
        dt.Columns.Add(dc)

        dc = New DataColumn("CustomerLastName", _
            System.Type.GetType("System.String"))
        dt.Columns.Add(dc)

        dc = New DataColumn("CustomerPhone", _
        System.Type.GetType("System.String"))
        dt.Columns.Add(dc)

        dc = New DataColumn("CustomerEmail", _
            System.Type.GetType("System.String"))
        dt.Columns.Add(dc)

        dc = New DataColumn("Note", _
            System.Type.GetType("System.String"))
        dt.Columns.Add(dc)

        Dim dr As DataRow
        For i As Integer = 1 To 10
            dr = dt.NewRow
            dr("CustomerID") = i
            dr("CustomerFirstName") = "FirstName_" & i.ToString()
            dr("CustomerLastName") = "LastName_" & i.ToString()
            dr("CustomerPhone") = "123-456-7890"
            dr("CustomerEmail") = dr("CustomerFirstName").ToString() & _
                    "." & dr("CustomerLastName").ToString() & _
                    "@TechProsZone.net"
            dr("Note") = "Some random notes here."
            dt.Rows.Add(dr)
        Next
        Session("CustomerDT") = dt
    Else
        dt = CType(Session("CustomerDT"), DataTable)
    End If
    Me.gvCustomerList.DataSource = dt
    Me.gvCustomerList.DataBind()
End Sub
Protected Sub Page_Load(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then
        Me.LoadCustomerList()
    End If

End Sub

In this example, I am not using any database to store and load data. In reality, the LoadCustomerList() function should be pulling data from your database.

5.2 Edit Button Clicked

When the Edit button is clicked, GridView’s RowCommand event is fired. We can use the GridView’s RowCommand event handler to populate the DetailsView and then display the ModalPopup:

Private Sub gvCustomerList_RowCommand(ByVal sender As Object, _
        ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) _
            Handles gvCustomerList.RowCommand

    If (e.CommandName = "cmdEdit") Then
        Dim id As Integer = 0
        Integer.TryParse(e.CommandArgument.ToString(), id)
        Dim dt As DataTable = CType(Session("CustomerDT"), DataTable)
        Dim dv As DataView = New DataView(dt)
        dv.RowFilter = "CustomerID=" & id.ToString()
        Me.dvEditCustomer.DataSource = dv
        Me.dvEditCustomer.DataBind()
        Me.dvEditCustomer.DefaultMode = DetailsViewMode.Edit
        Dim fckEditor As FredCK.FCKeditorV2.FCKeditor = _
                Me.dvEditCustomer.FindControl("fckEditorNote")
        fckEditor.BasePath = Request.ApplicationPath & "/Common/fckeditor/"

        ViewState("CustomerID") = id.ToString()

        Me.mpeEditEmployee.Show()

    End If

End Sub

5.3 DetailsView Update Button Clicked

When DetailsView’s Update button is clicked, then ItemUpdating event is fired. We can use ItemUpdating event handler to update the record and then hide the ModalPopup when the update is done. The trick here is first to find the DetailsView by casting the “sender” object to a DetailsView object, then to use FindControl to find the FCKEditor control within the DetailsView. Once the FCKEditor control is found, then you can access to the content by calling FCKEditor.Value:

Private Sub dvEditCustomer_ItemUpdating(ByVal sender As Object, _
        ByVal e As System.Web.UI.WebControls.DetailsViewUpdateEventArgs) _
            Handles dvEditCustomer.ItemUpdating

    Dim id As Integer = 0
    Integer.TryParse(ViewState("CustomerID").ToString(), id)
    Dim dt As DataTable = CType(Session("CustomerDT"), DataTable)
    Dim drs As DataRow() = dt.Select("CustomerID=" & id.ToString())
    Dim dr As DataRow = drs(0)
    Dim dv As DetailsView = CType(sender, DetailsView)

    Dim fckEditor As FredCK.FCKeditorV2.FCKeditor = dv.FindControl("fckEditorNote")

    dr("Note") = fckEditor.Value
    dt.AcceptChanges()

    Session("CustomerDT") = dt

    Me.LoadCustomerList()
    Me.mpeEditEmployee.Hide()

End Sub

5.4 DetailsView Cancel Button Clicked

Finally we need to hide the ModalPopup when the DetailsView’s Cancel button is clicked. We can use ModeChanging event handler to hide the ModalPopup.

Private Sub dvEditCustomer_ModeChanging(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.DetailsViewModeEventArgs) _
        Handles dvEditCustomer.ModeChanging

    If (e.CancelingEdit) Then
        Me.mpeEditEmployee.Hide()
    End If

End Sub

5.5 Final Note

You will need to set validateRequest=”false” in the Page directive for the page that uses FCKEditor, otherwise, ASP.NET will throw an exception when you try to submit your form: “A potentially dangerous Request.Form value was detected from the client…”.

If you want to see how it works, just follow this link to the demo.

UPDATE:

1. You don’t need to set validateRequest=”false”. It seems that the latest version of FCKEditor will take care of it for you.

2. Rob mentioned in the comment that the demo only works in IE. In FireFox, when you click the “Link” icon in FCKEditor, the popup dialog is behind the ModalPopup. It turns out that when ModalPopup is generated, its z-index is always reset to 100001 to ensure it is on top of other elements. To fix the problem, open FCKEditor’s fckconfig.js file and find a line says:

FCKConfig.FloatingPanelsZIndex = 10000 ;

Change it to a number larger than 100001, for example:

FCKConfig.FloatingPanelsZIndex = 100002 ;

This should fix the problem with FireFox.

Thanks Rob for reporting the problem.

7
Leave a Reply

avatar
7 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
ShemJeffreyrob Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
rob
Guest
rob

Hi , i am having the problem with sample above that in firefox the fck dialog windows ( like the image editor or hyperlink insert dialog ) will appear behind the modal popup. However in IE8 it works. Do you happen to have any ideas how to solve this ?

Shem
Guest
Shem

@Jeffrey,

Unfortunately that didn’t work for me 🙁

Shem
Guest
Shem

@Jeffrey
that did the trick!!!
Thanks for your help Jeff 😉