Telerik radgrid row color issue - asp.net

In my code I have this sub to handle changing row colors depending on the contents of a column called "backorder" which is bit in sqlserver.
When I test if it is True or 1 it executes the main "IF" code twice which is correct for my datatable. 2 rows display as backorder = True. However the grid remains the normal color. If I uncomment the else code block, ALL cells in that column are orange regardless of content and the execution still passed thru the main "IF" twice. I am quite confused by this behavior. If it was CSS interfering, why would it let the orange color work? I have tried a dozen variations of code which all posters say should work...
Please help! I have spent most of the day trying to unravel this!
Protected Sub RadGrid1_ItemDataBound(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
If TypeOf e.Item Is GridDataItem Then
Dim item As GridDataItem = DirectCast(e.Item, GridDataItem)
If item("backorder").Text = "True" Or item("backorder").Text = "1" Then
item("backorder").BackColor = System.Drawing.Color.Red
Else
'item("backorder").BackColor = System.Drawing.Color.Orange
End If
End If
End Sub

Your problem is that item("backorder") returns an object of type TableCell, not a row. Therefore, when setting item("backorder").BackColor = System.Drawing.Color.Red you are setting the cell in the column backorder's BackColor, not the entire rows backcolor. If the Column backorder is not visible, you wont see any change.
Try the following code:
Protected Sub RadGrid1_ItemDataBound(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
If TypeOf e.Item Is GridDataItem Then
Dim item As GridDataItem = DirectCast(e.Item, GridDataItem)
If item("backorder").Text = "True" Or item("backorder").Text = "1" Then
item.BackColor = Drawing.Color.Red
Else
item.BackColor = System.Drawing.Color.Orange
End If
End If
End Sub
What this does is check the column 'backorder', and then sets the entire rows BackColor by setting the BackColor for the GridDataItem.
Check out Shinu's answer in the following post. Telerik Forum Post

It may be related to the Boolean evaluation you're doing. You've accounted for "True" and 1, but there are others: "true", and -1 come immediately to mind. You might try this instead:
Protected Sub RadGrid1_ItemDataBound(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
If TypeOf e.Item Is GridDataItem Then
Dim item As GridDataItem = DirectCast(e.Item, GridDataItem)
If Convert.ToBoolean(item("backorder").Text) = True Then
item("backorder").BackColor = System.Drawing.Color.Red
Else
item("backorder").BackColor = System.Drawing.Color.Orange
End If
End If
End Sub
That way, you're letting the built-in Convert object handle the heavy-lifting on the "truthiness" of the statement contained in the string.

Related

VB.net For Each Loop Not Accounting for First Datarow

I am currently looping through a data gridview in Visual Studio, The Loop works well and the code does pretty much what I want,
My only problem is that it seems to skip, or not account for the first row in my gridview, I have looked online to resolve this but cannot find anything,
I was wondering if i could get some assistance with this...
Here is my code for the loop:
'Checks the flags for montor/expiry date to set red or green cells
'------------------------------------------------------------------
For Each Row As GridViewRow In GridView3.Rows
'-----------------------------------------------------------------------------------------
Dim MonitorVal As String = GridView3.DataKeys(e.Row.RowIndex).Values("Monitor").ToString
If MonitorVal.Contains("Yes") Then
Dim IsExtention As String = GridView3.DataKeys(e.Row.RowIndex).Values("FileName").ToString
If IsExtention = "" Or IsExtention = Nothing Or IsExtention = "Null" Then
'set red
'--------
e.Row.BackColor = Drawing.Color.LightPink
Else
'else green
'-----------
e.Row.BackColor = Drawing.Color.LightGreen
End If
Else
'else green
'-----------
e.Row.BackColor = Drawing.Color.LightGreen
End If
Next
I guess that "first row in gridview" actually means the header-row of the grid. That is not returned from GridView.Rows, only rows with DataControlRowType.DataRow are returned. You can get it only in events like RowDataBound or RowCreated. I would suggest to use RowDataBound in this case:
Protected Sub GridView3_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView3.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.Header
' ... '
Case DataControlRowType.DataRow
' ... '
Case DataControlRowType.Footer
' ... '
End Select
End Sub
Documentation:
Only rows with their RowType property set to
DataControlRowType.DataRow are stored in the Rows collection. The
GridViewRow objects that represent the header, footer, and pager rows
are not included in the collection.

Modifying a copy of a Collection from with a For Each still gives error

I am trying to scan through some True/False RadioButtonLists that I have. They're within an QuestionsList. I am trying to add a message to each item saying "Correct" or "Incorrect", but when I do so I get "Collection was modified; enumeration operation may not execute."
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
If (IsPostBack) Then
Dim SubmittedQuestionsList As New HtmlGenericControl("ol")
SubmittedQuestionsList = QuestionsList
For Each QuestionItem In SubmittedQuestionsList.Controls
If TypeOf QuestionItem Is HtmlGenericControl Then
For Each question In QuestionItem.Controls
If TypeOf question Is RadioButtonList Then
Dim QuestionExplanation As New Panel
If (question.SelectedValue = "true") Then
QuestionExplanation.CssClass = "succcess-response"
QuestionExplanation.Controls.Add(New LiteralControl("Correct!"))
Else
QuestionExplanation.CssClass = "error-response"
QuestionExplanation.Controls.Add(New LiteralControl("Incorrect:"))
End If
'If I uncomment the line below, error goes away
QuestionsList.Controls.Add(QuestionExplanation)
Debug.WriteLine(question.SelectedValue)
End If
Next
End If
Next
End If
End Sub
What is the best way to loop through it (or a copy of it), and add a message as I go?
Per Dave's comment, noting that SubmittedQuestionsList was simply a reference to QuestionsList, I found I could simply use an Array.
Replace:
Dim SubmittedQuestionsList As New HtmlGenericControl("ol")
SubmittedQuestionsList = QuestionsList
with:
Dim SubmittedQuestionsList(QuestionsList.Controls.Count) As HtmlGenericControl
QuestionsList.Controls.CopyTo(SubmittedQuestionsList, 0)

Gridview - Greying out checkboxes once one is checked

I'm new to all of this code, so please be patient.
On my gridview, I am trying to make it so, once I check on of the checkboxes, the others get greyed out, making it impossible to select another. How would I code this?
Thanks in advance.
PS: I'm using vb, rather than C#.
Edit: Here is the code I want to run.
Protected Sub btnOK_Click(ByVal sender As Object, ByVal e As
System.Web.UI.ImageClickEventArgs) Handles btnOK.Click
Dim TxtbxID As TextBox
Dim RB As System.Web.UI.WebControls.RadioButton
For Each row As GridViewRow In GridView1.Rows
RB = row.FindControl("select")
If RB.Checked Then
Me.txtHiddenProblem.Text = row.Cells(3).Text & " on " & row.Cells(5).Text
TxtbxID = FormView1.FindControl("ProblemTextbox")
TxtbxID.Text = txtHiddenProblem.Text
End Sub
Take a look at this article: http://www.ezzylearning.com/tutorial.aspx?tid=5187857
It has some lines of code which help you determine the particular gridview row the checkbox element was associated with...
public void chkStatus_OnCheckedChanged(object sender, EventArgs e)
{
CheckBox chkStatus = (CheckBox)sender;
GridViewRow row = (GridViewRow)chkStatus.NamingContainer;
//other code
}
Now all we need to do is when the checkbox element is checked, iterate through the grid, find the checkbox, and disable them if its not the same as the one which caused the event...

Using Hidden Fields in an ItemCreated handler

I'm making a large data entry web form using a DataList.
I have three sets of questions that I store some info about in ASP HiddenFields. I want to color the back of these data list items based on the values of those HiddenFields, but in the ItemCreated event my DataListItemEventArgs are all Nothing or Empty.
I had this working using ItemDataBound, but my rows would lose color upon postback.
This is what I was using in ItemDataBound:
Protected Sub CategoryColors(ByVal sender As Object, ByVal e As DataListItemEventArgs) Handles TheTable.ItemDataBound
Dim v = CType(e.Item.FindControl("CtType"), HiddenField).Value
Try
If v = 1 Then
e.Item.BackColor = Drawing.Color.LightBlue
ElseIf v = 2 Then
e.Item.BackColor = Drawing.Color.Khaki
ElseIf v = 3 Then
e.Item.BackColor = Drawing.Color.LightGreen
Else
e.Item.BackColor = Drawing.Color.Red
End If
Catch ex As Exception
End Try
End Sub
Copying the body of that sub to the ItemCreated handler doesn't do anything. Can I do this same thing a different way? Thanks much for your help.

How can i add a row to a data-bound gridview without causing viewstate errors?

I'm trying to add a row grouping row to my data-bound gridview. It works fine on the first response, but at the postback i got the "Failed to load viewstate" error.
There is the code for the GridView's RowDataBound event:
Private Sub AddGroupingRow(ByRef eRow As GridViewRow, ByVal Css As String, ByVal ColSpan As Integer, ByVal Txt As String)
Dim cell As New TableCell()
cell.ColumnSpan = ColSpan
cell.CssClass = "Spacing FieldCell"
cell.Text = Txt
Dim row As New GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal)
row.CssClass = Css
row.Cells.Add(cell)
Dim tbl As Table
tbl = eRow.Parent
tbl.Rows.AddAt(eRow.RowIndex + 1, row)
End Sub
Private Prev_Client_ID As Integer = -1
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim dr As Data.DataRowView = TryCast(e.Row.DataItem, Data.DataRowView)
If dr IsNot Nothing AndAlso dr.Row.RowState <> Data.DataRowState.Added Then
Dim Client_ID As Integer = dr.Item("Client_ID")
If Client_ID <> Prev_Client_ID Then AddGroupingRow(e.Row, "Group", 8, dr.Item("Client_Name"))
Prev_Client_ID = Client_ID
End If
End If
End Sub
I know that it's easier to create the grouping rows at the datasource, but deriving from this code, i want to create some base to other grids at the site.
Try this link. it should help you. I too had the same problem. The only way to resolve is a proper understanding of viewstate.
After some thinking, the answer could not be simpler: disable the viewstate of the gridview.
I was re-binding the datasource at every paging or sorting, so the need for the viewstate was minimum, except for the PageSize and PageIndex, that i became forced to keep track manually.
This is a considerable trade-off: things like PageSize and PageIndex must be managed manually afterwards, since their state are keeped by the ViewState.
So, even doing exactly what i was meant to do, i've decided to adopt an simple alternative solution:
If Cliente_ID <> Cliente_ID_Anterior Then
For i As Integer = 0 To e.Row.Cells.Count - 1
e.Row.Cells(i).Style("border-top") = "solid 1px #777777"
Next
e.Row.Cells(0).Style("border-bottom") = "none"
Else
e.Row.Cells(0).Text = " "
e.Row.Cells(0).Style("border-top") = "none"
e.Row.Cells(0).Style("border-bottom") = "none"
End If
It still groups the column, but in another way, and is more sort friendly. I could use rowspans and turn cells invisible, but it would be harder to keep. Besides, I'll need to paint the line when the user moves the mouse over it, and a rowspan would hinder a lot.

Resources