This is a migrated thread and some comments may be shown as answers.

Change the BackColor of an edited cell for an AutoGenerated Grid

11 Answers 337 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Karl
Top achievements
Rank 1
Karl asked on 02 Nov 2013, 09:33 PM
Greetings!

Can anyone suggest a method with which I can change a cell's BackColor when its value is edited? Using textchanged, keydown or some other event will do. The problem I have is that the grid is autogenerated and most of the column names are unknown. 

I set my cells to be editable in PreRender like so:
For Each item As GridItem In RadGridViewExcelGridTest.MasterTableView.Items
    If TypeOf item Is GridEditableItem Then
        Dim editableItem As GridEditableItem = CType(item, GridDataItem)
        editableItem.Edit = True
    End If
Next
 
RadGridViewExcelGridTest.Rebind()

And my edit mode is InPlace. I noticed the Batch edit mode has its own ClientSetting called "ClientEvents-OnBatchEditCellValueChanged", but for reasons my edit mode has to be InPlace.

The way it works now is that the grid loads as completely editable. A user can update multiple cells on multiple rows - so I'd like to provide a visual cue to let the user know which items have been edited (and have not yet been saved). I noticed on this demo a little triangle shows when you click out of a cell that was edited - and that would be fine. I just didn't see the mechanism that produces that result. My situation would also be slightly different, as my cells are always in edit mode (i.e., textbox vs label) - but the principle
would be the same. 

I tried doing this on my ItemCreated (excluding the known column names, that are either not visible or not editable):
If TypeOf e.Item Is GridEditableItem Then
    Dim item As GridDataItem = TryCast(e.Item, GridDataItem)
    For Each column As GridColumn In item.OwnerTableView.RenderColumns
        If (column.UniqueName <> "Project" And column.UniqueName <> "DepartmentNumber" And column.UniqueName <> "ProjectNumber" And column.UniqueName <> "Alias") Then
            Dim EditBox As New TextBox()
            EditBox.Text = item(column).Text
            AddHandler EditBox.TextChanged, AddressOf EditBox_TextChanged
            EditBox.AutoPostBack = True
            item(column).Controls.Clear()
            item(column).Controls.Add(EditBox)
        End If
    Next
End If

But I then get an error message that the "Editor cannot be initialized for column: " followed by the first column that should be editable (and this error appears to get thrown on the Rebind() in my PreRender, for what it's worth).

11 Answers, 1 is accepted

Sort by
0
Princy
Top achievements
Rank 2
answered on 04 Nov 2013, 10:55 AM
Hi Karl,

Please try the following sample code snippet, I have tried to set the back-color for the rows that has its text changed.

ASPX:
<telerik:RadGrid ID="RadGrid1" runat="server" AutoGenerateColumns="true" DataSourceID="SqlDataSource1" 
  GridLines="None" AllowPaging="true" OnPreRender="RadGrid1_PreRender" AllowMultiRowEdit="true"
 OnItemCreated="RadGrid1_ItemCreated">
    <MasterTableView DataKeyNames="OrderID" EditMode="InPlace">
    </MasterTableView>
</telerik:RadGrid>

VB:
Protected Sub RadGrid1_PreRender(sender As Object, e As EventArgs)
    'To Keep rows in Edit Mode
    If Not IsPostBack Then
        For Each item As GridItem In RadGrid1.MasterTableView.Items
            If TypeOf item Is GridEditableItem Then
                Dim editableItem As GridEditableItem = TryCast(item, GridDataItem)
                editableItem.Edit = True
            End If
        Next
        RadGrid1.Rebind()
    End If
End Sub
Protected Sub RadGrid1_ItemCreated(sender As Object, e As GridItemEventArgs)
    If TypeOf e.Item Is GridEditableItem AndAlso e.Item.IsInEditMode Then
        Dim item As GridEditableItem = DirectCast(e.Item, GridEditableItem)
        For Each column As GridColumn In item.OwnerTableView.RenderColumns
            If column.ColumnType = "GridBoundColumn" Then
                'Checks for BoundColumn
                Dim txt As TextBox = DirectCast(item(column.UniqueName).Controls(0), TextBox)
                txt.AutoPostBack = True
                txt.TextChanged += New EventHandler(AddressOf txt_TextChanged)
            End If
            If column.ColumnType = "GridNumericColumn" Then
                'Checks for NumericColumn
                Dim txtnumeric As RadNumericTextBox = DirectCast(item(column.UniqueName).Controls(0), RadNumericTextBox)
                txtnumeric.AutoPostBack = True
                txtnumeric.TextChanged += New EventHandler(AddressOf txtnumeric_TextChanged)
            End If
        Next
    End If
End Sub
 
Private Sub txtnumeric_TextChanged(sender As Object, e As EventArgs)
    Dim txt As RadNumericTextBox = DirectCast(sender, RadNumericTextBox)
    txt.BackColor = Color.Gold
End Sub
 
Private Sub txt_TextChanged(sender As Object, e As EventArgs)
    Dim txt As TextBox = DirectCast(sender, TextBox)
    txt.BackColor = Color.Gold
End Sub

Thanks,
Princy
0
Karl
Top achievements
Rank 1
answered on 04 Nov 2013, 02:44 PM
Princy,

I did not get the expected results. Just a point of clarification - this line:
txt.TextChanged += New EventHandler(AddressOf txt_TextChanged)

This looks like a failed C# conversion to VB.net. Can you clarify this is how its supposed to be written:
AddHandler txt.TextChanged, AddressOf txt_TextChanged

With my version, the back color does not change. Also, the auto postback clears the changes of the cell (like when I tab out).

Thanks,

Karl
0
Princy
Top achievements
Rank 2
answered on 05 Nov 2013, 04:15 AM
Hi Karl,

The TextChanged event of TextBox can be raised as follows:

VB:
AddHandler txt.TextChanged, AddressOf txt_TextChanged
 
'Definition
Protected Sub txt_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
   . . .
End Sub

The code is working fine at my end. I have used 2013.2.611.40. Can you provide your full code snippet with the version you are using to identify the issue.

Thanks,
Princy
0
Karl
Top achievements
Rank 1
answered on 05 Nov 2013, 01:30 PM
Princy,

Thanks for your reply.

I'm using 2013.3.1015.40.

Here's my ItemCreated:
Protected Sub RadGridViewExcelGridTest_ItemCreated(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGridViewExcelGridTest.ItemCreated
 
    If TypeOf e.Item Is GridEditableItem AndAlso e.Item.IsInEditMode Then
        Dim item As GridEditableItem = DirectCast(e.Item, GridEditableItem)
        For Each column As GridColumn In item.OwnerTableView.RenderColumns
            If column.ColumnType = "GridNumericColumn" Then
                'Checks for NumericColumn
                Dim txtnumeric As RadNumericTextBox = DirectCast(item(column.UniqueName).Controls(0), RadNumericTextBox)
                txtnumeric.AutoPostBack = True
                AddHandler txtnumeric.TextChanged, AddressOf txtnumeric_TextChanged
            End If
        Next
    End If
 
End Sub

And here's the function:
Private Sub txtnumeric_TextChanged(sender As Object, e As EventArgs)
 
    'Response.Redirect("http://www.google.com")
    Dim txt As RadNumericTextBox = DirectCast(sender, RadNumericTextBox)
    txt.BackColor = Drawing.Color.Gold
 
End Sub

I used the Response.Redirect to confirm the function was being called (it is), and to verify the type of column (numeric), which is why I only have the one case in the ItemCreated event.

Thanks,

Karl
0
Princy
Top achievements
Rank 2
answered on 06 Nov 2013, 09:09 AM
Hi Karl,

I guess you are binding the RadGrid in the PageLoad event. Please bind the RadGrid in the NeedDataSource event as follows.

ASPX:
<telerik:RadGrid ID="RadGrid1" runat="server" AutoGenerateColumns="true" GridLines="None"
    AllowPaging="true" OnPreRender="RadGrid1_PreRender" AutoGenerateEditColumn="false"
    AllowMultiRowEdit="true" OnItemCreated="RadGrid1_ItemCreated">
    <MasterTableView DataKeyNames="OrderID" EditMode="InPlace">
    </MasterTableView>
</telerik:RadGrid>

VB:
Protected Sub RadGrid1_NeedDataSource(sender As Object, e As Telerik.Web.UI.GridNeedDataSourceEventArgs) Handles RadGrid1.NeedDataSource
       Dim ConnString As [String] = ConfigurationManager.ConnectionStrings("Northwind_newConnectionString3").ConnectionString
       Dim conn As New SqlConnection(ConnString)
       Dim adapter As New SqlDataAdapter()
       adapter.SelectCommand = New SqlCommand("SELECT OrderID,ShipCity,CustomerID FROM Orders", conn)
       Dim myDataTable As New DataTable()
       conn.Open()
       Try
           adapter.Fill(myDataTable)
       Finally
           conn.Close()
       End Try
       RadGrid1.DataSource = myDataTable
   End Sub
 
 
Protected Sub RadGrid1_PreRender(sender As Object, e As System.EventArgs) Handles RadGrid1.PreRender
       If Not IsPostBack Then
           For Each item As GridItem In RadGrid1.MasterTableView.Items
               If TypeOf item Is GridEditableItem Then
                   Dim editableItem As GridEditableItem = TryCast(item, GridDataItem)
                   editableItem.Edit = True
               End If
           Next
           RadGrid1.Rebind()
       End If
   End Sub
 
Protected Sub RadGrid1_ItemCreated(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemCreated
       If TypeOf e.Item Is GridEditableItem AndAlso e.Item.IsInEditMode Then
           Dim item As GridEditableItem = DirectCast(e.Item, GridEditableItem)
           For Each column As GridColumn In item.OwnerTableView.RenderColumns
               If column.ColumnType = "GridNumericColumn" Then
                   'Checks for NumericColumn
                   Dim txtnumeric As RadNumericTextBox = DirectCast(item(column.UniqueName).Controls(0), RadNumericTextBox)
                   txtnumeric.AutoPostBack = True
                   AddHandler txtnumeric.TextChanged, AddressOf txtnumeric_TextChanged
               End If
           Next
       End If
   End Sub
  
  
   Private Sub txtnumeric_TextChanged(sender As Object, e As EventArgs)
       Dim txt As RadNumericTextBox = DirectCast(sender, RadNumericTextBox)
       txt.BackColor = Drawing.Color.Gold
   End Sub
  
  

Thanks,
Princy
0
Karl
Top achievements
Rank 1
answered on 06 Nov 2013, 05:04 PM
Princy,

I think that will do the trick, but since I'm using stored procedures I'll need to rework a number of things, and I'm not very well versed on the NeedDataSource event. I have read the advanced data-binding article in the RadGrid documentation, and perused the forums, but wasn't able to find anything concrete for using stored procedures with NeedDataSource.

Here's my NeedDataSource event (with hard-coded parameters for testing):
Using con As New SqlConnection(cnSQLLive)
 
    con.Open()
    Try
        Dim cmd As New SqlCommand()
        cmd.CommandType = CommandType.StoredProcedure
        cmd.CommandText = "spJobForecastingGetEmployeesByDepartmentAndProject"
        cmd.Parameters.Add("DepartmentNumber", TypeCode.String, "13211")
        cmd.Parameters.Add("ProjectNumber", TypeCode.String, "1313249800")
        cmd.Connection = con
 
        Dim adapter As New SqlDataAdapter(cmd)
        Dim myDataTable As New DataTable()
        adapter.Fill(myDataTable)
 
        RadGridViewExcelGridTest.DataSource = myDataTable
    Finally
        con.Close()
    End Try
 
End Using

I removed the SelectCommand from my SqlDataSource, and added OnNeedDataSource to my RadGrid declaration. It looks right (to me anyway), but it doesn't load the grid. The grid doesn't load when the page loads, and it doesn't load when I programmatically call Rebind() in the selectedindexchanged event of a dropdownlist on my page.

And once that's settled, I'll need to figure out how to pass parameters to my stored procedure in the NeedDataSource event. This is how I was doing it using my SqlDataSource, from a dropdownlist's selectedindexchanged event:
SqlDataSourceExcelGridTest.SelectParameters.Clear()
 
SqlDataSourceExcelGridTest.SelectCommand = "spJobForecastingGetEmployeesByDepartmentAndProject"
SqlDataSourceExcelGridTest.SelectParameters.Add("DepartmentNumber", TypeCode.String, strUserDeptNumber)
SqlDataSourceExcelGridTest.SelectParameters.Add("ProjectNumber", DropdownListExistingProjects.SelectedValue)
 
SqlDataSourceExcelGridTest.DataBind()
RadGridViewExcelGridTest.Rebind()

I suspect the method will be similar, but I'd prefer to ask now than be stuck again.

Thanks!

Karl
0
Princy
Top achievements
Rank 2
answered on 08 Nov 2013, 06:00 AM
Hi Karl,

In your code make sure that you are able to add the parameters to the DataTable, if the parameters are not obtained properly the radgrid won't be bound properly. Put breakpoints in your code and check for the values in DataTable. I have tried a sample code snippet to bind the RadGrid to the value selected from DropDownList. Please try and let me know if any concern.

ASPX:
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true"
 OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
DataTextField="OrderID" DataValueField="EmployeeID" DataSourceID="SqlDataSource1">
</asp:DropDownList>
<telerik:RadGrid ID="RadGrid1" runat="server" AutoGenerateColumns="false" GridLines="None"
    AllowPaging="true" OnNeedDataSource="RadGrid1_NeedDataSource">
    <MasterTableView DataKeyNames="OrderID">
        <Columns>
            <telerik:GridNumericColumn UniqueName="OrderID" DataField="OrderID" HeaderText="OrderID" />
            <telerik:GridNumericColumn DataField="EmployeeID" HeaderText="EmployeeID" UniqueName="EmployeeID" />
        </Columns>
    </MasterTableView>
</telerik:RadGrid>

VB:
Private IsSelected As Boolean = False
Private orderid As String, employeeid As String
 
Public Shared connection As String = WebConfigurationManager.ConnectionStrings("Northwind_newConnectionString3").ConnectionString
Private conn As New SqlConnection(connection)
Public cmd As New SqlCommand()
 
Protected Sub RadGrid1_NeedDataSource(sender As Object, e As GridNeedDataSourceEventArgs)
    cmd.Connection = conn
    cmd.CommandType = CommandType.StoredProcedure
    cmd.CommandText = "StoredProcedure4"
 
    If IsSelected Then
        cmd.Parameters.AddWithValue("@OrderID", orderid)
        cmd.Parameters.AddWithValue("@EmployeeID", employeeid)
    Else
        cmd.Parameters.AddWithValue("@OrderID", 10302)
        cmd.Parameters.AddWithValue("@EmployeeID", 55)
    End If
 
    Dim dt As New DataSet()
    Dim adp As New SqlDataAdapter()
    adp.SelectCommand = cmd
    adp.Fill(dt)
    RadGrid1.DataSource = dt
    conn.Close()
End Sub
 
Protected Sub DropDownList1_SelectedIndexChanged(sender As Object, e As EventArgs)
    IsSelected = True
    orderid = DropDownList1.SelectedItem.Text
    employeeid = DropDownList1.SelectedValue
    RadGrid1.Rebind()
End Sub

Thanks,
Princy
0
Karl
Top achievements
Rank 1
answered on 08 Nov 2013, 03:01 PM
Princy,

Thanks - that does the trick!

However, it's created a few quirks that's I'm hoping you can help remedy.

1. The number of editable rows is constrained by the number of records that are initilly loaded. For example, if I have 4 records in my data set, then change to a data set with 8 records, only the first 4 are editable.

Link to screencast: http://screencast.com/t/PipUrn6I8N

2. If I edit a record, save those changes, and attempt to edit another record, my data set disappears.

Link to screencast: http://www.screencast.com/t/FfecC9ds

3. Because of the postback (I presume), any changes to the last cell edited aren't retained unless the cell gets its own post back (tab out).

Link to screencast: http://screencast.com/t/UJbN8nbLsARW

Thanks for continued support!

Karl
0
Daniel
Telerik team
answered on 13 Nov 2013, 10:11 AM
Hello Karl,

Straight onto your questions:

1) I believe the problem is related to the Not IsPostBack condition in the PreRender event. When you change the datasource, you don't put the new rows in edit mode
Protected Sub RadGrid1_PreRender(sender As Object, e As System.EventArgs) Handles RadGrid1.PreRender
       If Not IsPostBack Then
 ....

2) Can you share the code behind the Save Changes button with me? Also can you please put a breakpoint there to see if the database is updated correctly?

3) I'm not sure what's happening here. I do my best to find out if you post the relevant code.

Finally, I'd like to recommend that you keep the developer console of your browser open all the time so that you can see if there are JS errors.

Regards,
Daniel
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
0
Karl
Top achievements
Rank 1
answered on 13 Nov 2013, 02:04 PM
Daniel,

Regarding item #1: I'm using Princy's suggestion by inclusing the Not IsPostBack condition. If, however, I comment out that condition, my cells lose the "color change on text change" feature, and my cells revert to the pre-edited text when tabbing out.

Link to screencast: http://screencast.com/t/CqwMY6RHX

Regarding item #2: Here's the code for my save changes. Note, if I include a Rebind statement after the update, the cells drop out of edit mode.
Protected Sub RadGridProjectScheduling_ItemCommand(sender As Object, e As Telerik.Web.UI.GridCommandEventArgs) Handles RadGridProjectScheduling.ItemCommand
    If (e.CommandName = "UpdateAll") Then
        Dim columns As Array
        columns = RadGridProjectScheduling.MasterTableView.RenderColumns
        For Each editedItem As GridEditableItem In RadGridProjectScheduling.EditItems
            Dim newValues As Hashtable = New Hashtable
            For Each column As GridColumn In columns
                If (column.UniqueName <> "ExpandColumn" And column.UniqueName <> "RowIndicator" And column.UniqueName <> "DepartmentNumber" And column.UniqueName <> "ProjectNumber" And column.UniqueName <> "Alias" And column.UniqueName <> "Project" And column.UniqueName <> "Name" And column.UniqueName <> "JF_ID") Then
                    e.Item.OwnerTableView.ExtractValuesFromItem(newValues, editedItem)
                    Dim columnValue As String = newValues(column.UniqueName)
                    SqlDataSourceExcelGridTest.UpdateParameters.Clear()
                    SqlDataSourceExcelGridTest.UpdateParameters.Add("DepartmentNumber", newValues("DepartmentNumber"))
                    SqlDataSourceExcelGridTest.UpdateParameters.Add("ProjectNumber", newValues("ProjectNumber"))
                    SqlDataSourceExcelGridTest.UpdateParameters.Add("Alias", newValues("Alias"))
                    SqlDataSourceExcelGridTest.UpdateParameters.Add("WorkWeek", column.UniqueName)
                    SqlDataSourceExcelGridTest.UpdateParameters.Add("WorkHours", columnValue)
                    SqlDataSourceExcelGridTest.Update()
                    editedItem.Edit = False
                End If
            Next
        Next
    ElseIf (e.CommandName = "Insert") Then
        ModalPopupExtenderAddEmployee.Show()
    End If
End Sub

And since I have access to the Database, I can confirm the appropriate record(s) is updated.

Regarding item #3: I'm not sure what you mean by the "relevant" code. I'm using the code as supplied by Princy. I'll paste it below for the sake of completeness.
Protected Sub RadGridProjectScheduling_ItemCreated(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGridProjectScheduling.ItemCreated
    If TypeOf e.Item Is GridEditableItem AndAlso e.Item.IsInEditMode Then
        Dim item As GridEditableItem = DirectCast(e.Item, GridEditableItem)
        For Each column As GridColumn In item.OwnerTableView.RenderColumns
            If column.ColumnType = "GridNumericColumn" Then
                'Checks for NumericColumn
                Dim txtnumeric As RadNumericTextBox = DirectCast(item(column.UniqueName).Controls(0), RadNumericTextBox)
                txtnumeric.AutoPostBack = True
                AddHandler txtnumeric.TextChanged, AddressOf txtnumeric_TextChanged
            End If
        Next
    End If
End Sub

Private Sub txtnumeric_TextChanged(sender As Object, e As EventArgs)
    Dim txt As RadNumericTextBox = DirectCast(sender, RadNumericTextBox)
    txt.BackColor = Drawing.Color.Honeydew
End Sub

Thanks,

Karl

0
Accepted
Daniel
Telerik team
answered on 18 Nov 2013, 01:15 PM
Hello Karl,

I will paste my reply from the support ticket here so that it is available for the community:

"I examined some of the code in your project. I think it would be better for you if you set the background color for the changed values on the client - except if you specifically need to make a roundtrip to the server.
So, if you decide to try this approach, here is how you can integrate it in your code:"
Protected Sub RadGridProjectScheduling_ItemCreated(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGridProjectScheduling.ItemCreated
  
    If TypeOf e.Item Is GridEditableItem AndAlso e.Item.IsInEditMode Then
        Dim item As GridEditableItem = DirectCast(e.Item, GridEditableItem)
        For Each column As GridColumn In item.OwnerTableView.RenderColumns
            If column.ColumnType = "GridNumericColumn" Then
                'Checks for NumericColumn
                Dim txtnumeric As RadNumericTextBox = DirectCast(item(column.UniqueName).Controls(0), RadNumericTextBox)
                txtnumeric.ClientEvents.OnValueChanging = "function(sender, args) { sender.get_styles().EnabledStyle[0] = 'background-color: orange'; sender.updateCssClass(); }"
                txtnumeric.EnabledStyle.BackColor = Drawing.Color.Honeydew 'we need to set something here, as the styles are serialized to the client only when they are in a non-default state
                txtnumeric.AutoPostBack = False
            End If
        Next
    End If
  
End Sub

"There is too much code which I would need to debug in order to give you a better advice, but after a quick look at it I think you can continue using your initial approach for databinding instead of advanced data-binding using NeedDataSource."

Regards,
Daniel
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
Tags
Grid
Asked by
Karl
Top achievements
Rank 1
Answers by
Princy
Top achievements
Rank 2
Karl
Top achievements
Rank 1
Daniel
Telerik team
Share this question
or