Combine Row Cell for Repeater Record - asp.net

I'm trying to combine the row cells when the campaign code and vehicle no are repeated as shown in below image. The result listed below is with gridview 20 page size
Problem
When the grid view page size is set with 2 for example, the row cell no longer combined. The result show each separated record.
If campaign code is sorted ascending/descending, the last record row cells will always not combine even though the campaign code and vehicle no are matched. Below image shown campaign code sorted in ascending. So when the campaign code is sorted descending, all the CMP002 are combined, while the last record of CMP001 will not be combined as shown in below image anymore.
Code Behind
Private Sub GV_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GV.RowDataBound
For rowIndex As Integer = GV.Rows.Count - 2 To 0 Step -1
Dim gvRow As GridViewRow = GV.Rows(rowIndex)
Dim gvPreviousRow As GridViewRow = GV.Rows(rowIndex + 1)
Dim sCurrCampaignCode As String = GV.DataKeys(rowIndex).Values("CAMPAIGN_CODE")
Dim sCurrVehicleNo As String = GV.DataKeys(rowIndex).Values("VEHICLE_NO")
Dim sPreviousCampaignCode As String = GV.DataKeys(rowIndex + 1).Values("CAMPAIG_CODE")
Dim sPreviousVehicleNo As String = GV.DataKeys(rowIndex + 1).Values("VEHICLE_NO")
If sCurrCampaignCode = sPreviousCampaignCode AndAlso sCurrVehicleNo = sPreviousVehicleNo Then
If sCurrCampaignCode = sPreviousCampaignCode Then
If gvPreviousRow.Cells(1).RowSpan < 2 Then
gvRow.Cells(1).RowSpan = 2
gvRow.Cells(2).RowSpan = 2
gvRow.Cells(3).RowSpan = 2
Else
gvRow.Cells(1).RowSpan = gvPreviousRow.Cells(1).RowSpan + 1
gvRow.Cells(2).RowSpan = gvPreviousRow.Cells(2).RowSpan + 1
gvRow.Cells(3).RowSpan = gvPreviousRow.Cells(3).RowSpan + 1
End If
gvPreviousRow.Cells(1).Visible = False
gvPreviousRow.Cells(2).Visible = False
gvPreviousRow.Cells(3).Visible = False
End If
End If
Next
End Sub

I just found a solution. Code have to be moved from RowDataBound to OnDataBound instead

Related

get values of dynamic checkboxes

I am dynamically creating checkboxes in VB.Net and an .aspx page, based on values in my db. I'm placing them in a two column table for ease of alignment. this part works fine.
Private Async Function InitForEditAsync() As Task
Dim docList = Await GetLoanApplicationConfigurationDocs()
Dim row = New HtmlTableRow()
Dim cell = New HtmlTableCell()
Dim i = 0
For Each doc In docList
Dim chkBox = New HtmlInputCheckBox()
Dim lbl = New Label()
Dim remainder = i Mod 2
chkBox.ID = "chkDocId" + doc.Id.ToString
lbl.Text = doc.DisplayName
cell.Controls.Add(chkBox)
cell.Controls.Add(lbl)
row.Cells.Add(cell)
cell = New HtmlTableCell()
If remainder <> 0 OrElse i = docList.Count() - 1 Then
tblEdit.Rows.Add(row)
row = New HtmlTableRow()
End If
i += 1
Next
End Function
Now I need to retrieve the values without knowing the id's but am not having any luck. I tried this:
For Each chkBox As HtmlInputCheckBox In pnlEdit.Controls.OfType(Of HtmlInputCheckBox)
but the checkboxes are not returned in the list of controls. The table is, but there are no rows in the table object when I explored it in the control collection and when I tried this:
For Each row As HtmlTableRow In tblEdit.Rows.OfType(Of HtmlTableRow)
If it will help, here is a Snip of the UI and the HTML that is created:
Any suggestions are appreciated. Thanks in advance.
Based on some ideas I got from another site, I'm going to rewrite this using the asp:CheckBoxList. apparently it binds like a datagrid and you can enumerate through it. Seems like what i need.
UPDATE: Everything I posted to start was resolved with five lines of code! "cblDocList is my asp CheckboxList and docList is my ienumerable of objects.
cblDocList.RepeatColumns = 2
cblDocList.DataSource = docList
cblDocList.DataTextField = "DisplayName"
cblDocList.DataValueField = "Id"
cblDocList.DataBind()
It’s something you can do through a loop for each row and each cell or using Linq to have only cells that have controls of type HtmlInputCheckBox inside.
I have simplified your code to be able run that here also shows you an example to achieve your task. Obviously you must change following your exigences .
Hope I well understood :)
Dim tblEdit As New HtmlTable
For k As Integer = 0 To 10
Dim cell = New HtmlTableCell()
Dim row = New HtmlTableRow()
Dim chkBox = New HtmlInputCheckBox()
Dim lbl = New Label()
Dim remainder = k Mod 2
chkBox.ID = "chkDocId_" + k.ToString
chkBox.Checked = remainder = 0
lbl.Text = "Text indicator of CheckBox nr:" + k.ToString
cell.Controls.Add(chkBox)
cell.Controls.Add(lbl)
row.Cells.Add(cell)
cell = New HtmlTableCell()
tblEdit.Rows.Add(row)
Next
Dim checkBoxes As IEnumerable(Of HtmlInputCheckBox) =
(From mRow In tblEdit.Rows).Select(Function(mr)
Dim cb = (From cc In CType(mr, HtmlTableRow).Cells
Where CType(cc, HtmlTableCell).Controls.OfType(Of HtmlInputCheckBox).Count > 0
Select CType(cc, HtmlTableCell).Controls.OfType(Of HtmlInputCheckBox)()(0)).FirstOrDefault
Return CType(cb, HtmlInputCheckBox)
End Function).ToList
For Each checkBox In checkBoxes
Debug.WriteLine("CheckBox ID: {0} Checked: {1} ", checkBox.ID, checkBox.Checked)
Next

Asp.Net GridView Retrieving cell values of each row through for loop and hiding empty columns

I know variations of this question have been asked a lot and I have been looking for answers for a long time and have tried many different blocks of code. Here is what I have right now which I am looping through from 0 to gridview1.rows.count-1. This code is in the RowDataBound Event.
Dim test As String
For i As Integer = 0 To GridView1.Rows.Count - 1
test = GridView1.Rows(i).Cells.Item(e.Row.RowIndex).Text.ToString
If test = " " Then
e.Row.Cells(i).Visible = False
End If
Next
Every time I get the error: Specified argument was out of the range of valid values.
Parameter name: index on this line
test = GridView1.Rows(i).Cells.Item(e.Row.RowIndex).Text.ToString
However, I think the error is just because I am going outside of the row range but can't figure out how to fix it. How can I successfully check each cell of all the rows and columns and hide the columns that return nothing.
I can now hide all of the actual cells within each column that is blank with this
Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
Dim GridView1 As GridView = FormView1.FindControl("GridView1")
For Each row As GridViewRow In GridView1.Rows
For i As Integer = 0 To row.Cells.Count - 1
Dim strtest As String = row.Cells(i).Text.ToString
If strtest = " " Then
row.Cells(i).Visible = False
End If
Next
Next
But it still won't let me hide the columns because with autogeneratecolumns it doesn't recognize that any columns are there so the code,
GridView1.Columns(i).visible = false
Throws the out of range error because there is no range of columns
For Each row As GridViewRow in GridView1.rows // rows
dim someval as String
for x= 0 to GridView1.Columns.Count // cols
if someval= = row.Cells[x].Text;
GridView1.Columns(x).Visible = false;
end if
next x
Next
manually typed pls check for typos'
Try something like this.
But I would probably point out that you seem to be reading through the entire grid every time you bind a row, which seems unnecessary. Rather you can have a separate method which you can call after the gridview is databound to hide your columns.
Put the below code in a function and call this function after the databinding for the grid.
Private Sub CheckForEmptyValues()
Dim dgv As DataGridView = GridView1
For r As Integer = 0 To dgv.RowCount - 1
For c As Integer = 0 To dgv.ColumnCount - 1
Dim cellValue as string = dgv.Rows(r).Cells(c).Value
If cellValue = " " Then
dgv.Rows(r).Cells(c).Visible = False
End If
Next
Next
End Sub
Ok Guys I finally found the correct way to do this, at least a way that works for me. So you have to use the row.cells.count -1 to actually get the count of your columns when you have autogeneratecolumns set to true and in order to iterate through your columns to set them to visible = false, you must use
GridView1.HeaderRow.Cells(i).visible = False
Here is my Final code and hopefully this will help a lot of people out that have the same problem, Thank you all for your help and answers
Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
Dim GridView1 As GridView = FormView1.FindControl("GridView1")
For Each row As GridViewRow In GridView1.Rows
For i As Integer = 0 To row.Cells.Count - 1
Dim strtest As String = row.Cells(i).Text.ToString
If strtest = " " Then
GridView1.HeaderRow.Cells(i).Visible = False
row.Cells(i).Visible = False
End If
Next
Next
End Sub

Command button with 'paste date' function to its next left cell

I'd like to create a Commandbutton with functionality to paste a date in to the cell to its left - I need to copy this button below in future.
I am trying:
Private Sub CommandButton2_Click()
Dim Str As String
Str = Date
Range(TopLeftCell).Value = Str
End Sub
I would recommend using Form Control instead of ActiveX control and the reason is very simple. When you copy the button across, the link to the macro remains intact., which is also one of your requirements.
And this is the code that you can use for the CommandButton (Form Control)
Sub Button1_Click()
Dim cellAddr As String
Dim aCol As Long
'~~> Get the address of the cell
cellAddr = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address
'~~> Also get the column number
aCol = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Column
'~~> This is required if the button is in column 1
If aCol <> 1 Then _
ActiveSheet.Range(cellAddr).Offset(, -1).Value = Date
End Sub
To point at a specific range do something like this:
Private Sub CommandButton1_Click()
Dim Str As String
Str = Date
Range("C5").Value = Str
End Sub
Alternatively use a named range i.e. give the range C5 the name "TopLeftCell"
...then you can use the following:
Private Sub CommandButton1_Click()
Dim Str As String
Str = Date
Range("TopLeftCell").Value = Str
End Sub
Something like this:
Private Sub CommandButton2_Click()
Dim r As Long, c As Long, i As Long
Dim str As String
r = Rows.Count
c = Columns.Count
str = Date
For i = 1 To r
If Cells(i, 1).Top > CommandButton2.Top Then
Exit For
End If
Next
r = i - 1 ' you have to calibrate, what fits better r = i or r = i - 1 or r = i - 2 ....
For i = 1 To c
If Cells(1, i).Left > CommandButton2.Left Then
Exit For
End If
Next
c = i - 2 ' you have to calibrate, what fits better c = i or c = i - 1 or c = i - 2 ....
Cells(r, c) = str
End Sub
This should work, but it really depends on where you place the button. Look at the lines r = i - 1 and c = i - 2.

How to fill all textboxes after click on gridview by making classLibrary?

I want to make a class library containing classes for common tasks.
I made such a class that worked very well on some forms but it have some errors that I can't trace down.
This is my code and it does the following:
It accepts 3 parameters: form name, datagridview name and the textbox name prefixes.
It counts the datagrid columns
It takes the current row index
It makes the array with a length corresponding to the number of columns
It's looking in the form for all text boxes that have a name with prefix parameter + column name and set the value in it
Code:
Sub setRecordFieldToControl(ByVal root As Form, ByVal dgv As DataGridView, ByVal cntrlPreNam1 As String, ByVal cntrlPreNam2 As String)
Dim j, k, z As Integer
Dim s As String
z = dgv.ColumnCount
k = dgv.CurrentRow.Index
j = 0
Dim headTxt(z) As String
For indx = 0 To z - 1
headTxt(indx) = dgv.Columns(indx).HeaderText
Next
For Each i As Control In root.Controls
If TypeOf i Is MaskedTextBox Or TypeOf i Is ComboBox Then
For clm = 0 To z
If i.Name = cntrlPreNam1 & headTxt(clm) Or i.Name = cntrlPreNam1 & headTxt(clm) Then
s = (dgv.Rows(k).Cells(j).Value)
i.Text = s
' i.Text = dgv.Item(j, k).Value
j = j + 1
If j >= z Then
Exit For
End If
End If
Next
End If
Next
End Sub
My problem is: on some forms I got this error:
Index is out of range for line i.Text = s
The error does not show up when I put something else in my text box, the error only appears when I put the s in it.
The error is probably in the line
For clm = 0 To z
It should read
For clm = 0 To z - 1
The column indexes range from 0 .. number_of_columns - 1.
UPDATE
There are several problems with your code:
The logic seems wrong to me. You are looking for the column (clm) with the right name but then take the value of another column (j). Why?
The variable names are not speaking and are even misleading (e.g. i for a Control).
You have nested loops with an O(n^2) behavior. See Big O Notation.
I suggest rewriting it. Use a dictionary for the possible control names, that stores the corresponding column indexes by name. Dictionaries have a nearly constant access speed. In other words: Lookups are very fast.
Sub SetRecordFieldToControl(ByVal root As Form, ByVal dgv As DataGridView, _
ByVal cntrlPrefix1 As String, ByVal cntrlPrefix2 As String)
Dim currentRowIndex As Integer = dgv.CurrentRow.Index
Dim columnDict = New Dictionary(Of String, Integer)
For i As Integer = 0 To dgv.ColumnCount - 1
Dim headerText As String = dgv.Columns(i).HeaderText
columnDict.Add(cntrlPrefix1 & headerText, i)
columnDict.Add(cntrlPrefix2 & headerText, i)
Next
For Each cntrl As Control In root.Controls
If TypeOf cntrl Is MaskedTextBox Or TypeOf cntrl Is ComboBox Then
Dim columnIndex As Integer
If columnDict.TryGetValue(cntrl.Name, columnIndex) Then
Dim value As Object
value = dgv.Rows(currentRowIndex).Cells(columnIndex).Value
If Not value Is Nothing Then
cntrl.Text = value.ToString()
End If
End If
End If
Next
End Sub

Loop through controls and change LINQ columns

I have the following code:
Dim i As Integer
For i = 1 To 20
Dim captionTextBox As TextBox = DirectCast(Me.FindControl("news_Image" + i.ToString() + "CaptionTextBox"), TextBox)
Dim deleteCheckBox As CheckBox = DirectCast(Me.FindControl("Image" + i.ToString() + "DeleteCheckBox"), CheckBox)
If Not deleteCheckBox.Checked = False Then
If Not captionTextBox.Text = "" Then
'Insert the value of the textbox into the column like news_Image1Caption, news_image2Caption nased on the value of i
End If
End If
Next
Where the comment is in the code above, I need to insert the value of the textbox (text) into Linq columns. For example: articleToUpdate.news_Image1Caption, news_Image2Caption, but I need to change the number after news_ to the value of i in the for loop. How can I do this?
Thanks
Luke
Did you try to set the ID column to Auto-Generated Value = true ?
INSERT INTO [dbo].[s_Tbl]([ID], [news_Image1Caption], [news_image2Caption]) VALUES (...)

Resources