I created an ASP Table Control and added a row to it programatically. I then repeated the process to add another row. The first row that I added disappeared and only the newest row is being displayed. Is there a property that needs to be set to allow the state of the table to be saved?
EDIT:
All I do is click a button on the page and it adds a row to the table. Repeated clicks of the button only add one from to the table. If it helps, here is the function that adds the rows.
Protected Sub addItemButton(sender As Object, e As EventArgs)
'get the id of the item they selected
Dim id As String = CType(sender, Button).Text
'clear out the data being displayed
gridViewItemSearchItems.DataSource = Nothing
gridViewItemSearchItems.DataBind()
'add this item to the line table
Dim itemToAdd As Item = gp.Items.GetItemByKey(id)
Dim tableRow As New System.Web.UI.WebControls.TableRow()
Dim cellId As New System.Web.UI.WebControls.TableCell
cellId.Text = itemToAdd.Key.Id
Dim cellDesc As New System.Web.UI.WebControls.TableCell
cellDesc.Text = itemToAdd.Description
Dim cellMSRP As New System.Web.UI.WebControls.TableCell
cellMSRP.Text = gp.Items.GetItemMSRP(itemToAdd.Key)
Dim cellCost As New System.Web.UI.WebControls.TableCell
cellCost.Text = itemToAdd.CurrentCost.Value
Dim cellUnitPrice As New System.Web.UI.WebControls.TableCell
cellUnitPrice.Text = itemToAdd.StandardCost.Value
Dim cellDiscount As New System.Web.UI.WebControls.TableCell
cellDiscount.Text = "12%"
Dim cellQuantity As New System.Web.UI.WebControls.TableCell
cellQuantity.Text = "1"
tableRow.Cells.Add(cellId)
tableRow.Cells.Add(cellDesc)
tableRow.Cells.Add(cellMSRP)
tableRow.Cells.Add(cellCost)
tableRow.Cells.Add(cellUnitPrice)
tableRow.Cells.Add(cellDiscount)
tableRow.Cells.Add(cellQuantity)
tblItems.Rows.Add(tableRow)
End Sub
Since you're adding the rows to your table dynamically, they have to be re-created on each successive post-back.
Look at this answer for an explanation as to why dynamically added controls can disappear: ASP.NET dynamically created controls and Postback
EDIT: It is possible to dynamically add controls during a post-back, my answer here shows a way to do that using ViewState. Although, this does become very cumbersome. You might want to re-think the design of the page.
Related
Every time I change a dropdown on a webpage, the page "resets". A row I've inserted programmatically disappears and a new one is written. I want to let the user add multiple rows.
I'm attempting to
Use a dropdown to fill mulitple GridViews displaying product infromation
User will add a quantity in a text box
Click 'Add to cart', which will...
Create a new row on an existing Table on that page with the selected product details
This works fine for the first row only, however, if I change the dropdown or click the 'Add to cart' button, the newly inserted row will be overwritten by the row from subsequent updates.
This is my table...
<asp:Table ID="tblOrderPreview" runat="server" BorderStyle="Solid" Width="800px" >
<asp:TableHeaderRow BorderStyle= "Solid"><asp:TableHeaderCell>Product</asp:TableHeaderCell><asp:TableHeaderCell>Qty</asp:TableHeaderCell><asp:TableHeaderCell>Price</asp:TableHeaderCell><asp:TableHeaderCell>Total</asp:TableHeaderCell><asp:TableCell><b>Remove Item</b></asp:TableCell></asp:TableHeaderRow>
<asp:TableRow BorderStyle= "Solid"><asp:TableCell></asp:TableCell><asp:TableCell></asp:TableCell><asp:TableCell></asp:TableCell><asp:TableCell></asp:TableCell><asp:TableCell></asp:TableCell></asp:TableRow>
</asp:Table>
And this is the code the button calls:
Protected Sub btnAddToCart_Click(sender As Object, e As System.EventArgs) Handles btnAddToCart.Click
lblValidator.Visible = False
If txtQuantity.Text <> "" Then
lblValidator.Visible = False
Dim name As String
name = GridView3.Rows(0).Cells(0).Text.ToString
Dim qantity As Integer
qantity = Convert.ToDouble(txtQuantity.Text)
Dim price As String
price = Convert.ToDouble(GridView5.Rows(0).Cells(0).Text.ToString)
Dim total As String
total = "$" + (price * qantity).ToString
'insert new row to tblOrderPreview (count rows, then insert another row named COUNT+1
Dim tRow As New TableRow()
tblOrderPreview.Rows.Add(tRow)
Dim tCellProduct As New TableCell()
tCellProduct.Text = name
tRow.Cells.Add(tCellProduct)
Dim tCellQty As New TableCell()
tCellQty.Text = qantity.ToString
tRow.Cells.Add(tCellQty)
Dim tCellPrice As New TableCell()
tCellPrice.Text = price
tRow.Cells.Add(tCellPrice)
Dim tCellTotal As New TableCell()
tCellTotal.Text = total
tRow.Cells.Add(tCellTotal)
Dim tCellRemove As New TableCell()
tCellRemove.Text = "del!"
tRow.Cells.Add(tCellRemove)
Else
lblValidator.Visible = True
End If
End Sub
Just to clarify my comment above and show some code:
Dim tblRowColl As TableRowCollection = tblOrderPreview.Rows
'Run the code that gets the new row
For Each tblRow As TableRow In tblRowColl
tblOrderPreview.Rows.Add(tblRow)
Next
Hopefully this helps.
Thanks,
Firstcape
I'm using a custom template class to generate lines with my repeater control, i'd like to be able to specify the controls in this repeater dynamically from the code behind my aspx page.
In the code behind I've added controls to a list like this:
Dim lstControls As New List(Of Control)
lstControls.Add(New TextBox)
lstControls.Add(New Label)
lstControls.Add(New CheckBox)
lstControls.Add(New DropDownList)
lstControls.Add(New CheckBox)
Then i use this line to add the controls to my template
rptrSummary.ItemTemplate = New myTemplate(ListItemType.Item, , lstControls)
From the instantiateIn sub i'm doing something like this:
Dim ph As New PlaceHolder
For i = 0 To lstControls.Count - 1
ph.Controls.Add(lstControls(i))
Next
This doesn't work properly and following .databind() of my repeater control the controls i specify only appear on the final row. I think this is because i've only declared the controls as NEW once, so i only have one rows worth.
tldr?/ conclusion:
How can i generate new controls of the same type as controls from my list? Something like:
Dim newControl as new Control = type(lstControl(0))
(this obviously doesn't work)
I've found the answer, here are some examples in case anyone else is stuck (i may also change the title so it's more similar to likely search criteria):
dim egTextbox as new textbox
dim egLabel as new label
dim newObject1 as Object = Activator.CreateInstance(egTextbox.GetType)
dim newObject2 as Object = Activator.CreateInstance(egLabel.GetType)
newObject1 is now a textbox
newObject2 is now a label
I'm trying to allow my users to enter in large lists of data using an ASP.Net GridView control. The affect I'm trying to create is to make the GridView control act like a spreadsheet. The user can freely enter data and tab from column to column and row to row. The user can use a button at the bottom of the page to add rows as needed. There is also a button at the bottom of the form to save as needed.
To do this, I created a DataTable with a bunch of empty rows and bound it to a GridView. The GridView's columns are template columns that contain textboxes. So, when the page opens, it actually looks like a spread sheet. When the user hits the add rows button, I just add another ten rows to the DataTable the GridView is bound to and it works like a charm.
The issue I'm running into is reading the data that the user entered. When the user hits the paging link or the update button, I would like to update the DataTable with the data the user typed in. Here is what I have.
Private Sub UpdateDataTable()
Dim objCatRow As clsCategoriesRow = Session("gvCategoriesRow")
Dim drQuery() As DataRow = Nothing
Dim drRow As DataRow = Nothing
Dim objRow As GridViewRow = Nothing
Dim intRecNo As Integer = 0
Dim txt As TextBox = Nothing
Dim lbl As Label = Nothing
'Loop through all of the rows in the grid view control
For Each objRow In Me.gvCategories.Rows
'Get the label that contains the identity column
lbl = objRow.Cells(GridColumns.Category).FindControl("lblItemRecNo")
intRecNo = lbl.Text
'Update the datarow bound to this grid view row
'First, query the datarow from the data table
drQuery = objCatRow.Table.Select("recno = " & intRecNo)
'Make sure our query returned a row
If Not IsNothing(drQuery) AndAlso drQuery.Count > 0 Then
'Get the value from the textbox in the grid view
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory")
'Upadte the data row with the value the user entered
'THE VALUE IN txt.Text IS EMPTY. HOW CAN I GET THE VALUE THE USER TYPED IN?
drQuery(0)("Category") = txt.Text
'Get the value from the textbox in the grid view
txt = objRow.Cells(GridColumns.SortORder).FindControl("txtItemSortOrder")
'Upadte the data row with the value the user entered
drQuery(0)("sortorder") = txt.Text
End If
Next
End Sub
The issue is that this is not returning what the user typed in. The line
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory")
returns a reference to the textbox in the templated column. But, it contains the previous value, the value from the view state, not the value the user typed in.
How can I get the value the user typed into the grid?
I want to mention that I know how to add EDIT and UPDATE buttons to each row. I would like to avoid doing that way if I can. My users have huge lists of data to enter in and that approach would make the application unusable.
Thanks in advance,
Mike
The form data posted by the user is found in the Page.Request.Form.Item collection. The Page.Request.Form.AllKeys lists the "keys" associated with all of the form item values.
If Page.Request.Form.HasKeys Then
For Each key as String In Page.Request.Form.AllKeys
' step through the keys and use Page.Request.Form.Item(key) to get the data entered
Next
end If
After testing, I was able to get the data from the Request.Form data or the GridView control during page.load on postback, as long as you don't bind the control on postback, but only during the initial request ("GET").
Keep in mind, controls have to be re-created for each request to the page. The Request data posted is used by ASP.NET to repopulate form data controls only after the controls are re-created on the page and the ViewState for the controls is processed, etc.
Request.Form collection
ASP.NET Page Life Cycle
You should replace this:
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory")
with this
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory").Value
I have a web form but I have to do this by code since I dont know the number of hyperlinks I need from the beginning.
How can I add some hyperlinks with Image in a label, the number of hyperlink depends on the number of rows of a query, and each row give me the link information to navigate.
Thanks in advance.
As you loop through your data you can manually add a link to the row something like this:
For i As Integer = 0 To 10
Dim row As New HtmlTableRow
row.Cells.Add(New HtmlTableCell)
Dim Link As New HyperLink
Link.Text = "WhateverText"
Link.NavigateUrl = "page.aspx"
Link.ImageUrl = "~/Theme/Images/SomeImage.gif"
Link.ToolTip = "ToolTipText"
row.Cells(0).Controls.Add(Link)
Next
That of course adds the link as the first cell in an html table. Not sure how you plan to display your data.
In response to the comment below. You can instead insert the new cell something like this
For i As Integer = 0 To 10
Dim row As New HtmlTableRow
Dim cell As New HtmlTableCell
row.Cells.Insert(1, cell)
Dim Link As New HyperLink
Link.Text = "WhateverText"
Link.NavigateUrl = "page.aspx"
Link.ImageUrl = "~/Theme/Images/SomeImage.gif"
Link.ToolTip = "ToolTipText"
row.Cells(0).Controls.Add(Link)
Next
You could also simply add the control to the existing cell that the label is in instead of making a new cell. You can do that by the index value of your existing cell (starting at 0 for each cell that is in the row)
This question is similar to what you want to do:
Auto increment asp control ID
Two options either use a repeater or dynamically add the controls to a panel or some other container control.
I inherited a site which I am in the middle of updating which has a DropDownList and a RangeValidator assigned to it. The data is bound to the dropdown on Page_Load. The values are retrieved from the database so the value property of each item is set to the unique ID of the item in the DB.
The RangeValidator looks something like:
<asp:rangevalidator id="ddRangeValidator" runat="server" ControlToValidate="ddMenu" ErrorMessage="Please select value in range" MinimumValue="1" MaximumValue="100000" Type="Integer">*</asp:rangevalidator>
I have a method which automatically populates this value in jQuery e.g.
$("#ddMenu").val("An Option");
This works, however, when I try to post the page the range validation fails. Then even if I manually select that value, or select another valid value it still won't validate. The only way to make it validate is to select non-valid value and then re-selecting a valid one.
Any ideas?
Update
Here is the data binding code:
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load, Me.Load
If Not Page.IsPostBack Then
Dim ds As New DataSet()
Dim myDbObject As New myDbObject()
ds = myDbObject.ToDataSet() // retrieves all objects from the database
// store the results in a temporary view to filter
Dim dv As DataView
dv = New DataView(ds.Tables(0), "IsLive = True", "ID", DataViewRowState.CurrentRows)
Dim i As Integer = 0
ddMenu.Items.Add("Select a value")
ddMenu.Items.Item(0).Value = 0
// add all objects from filtered list into drop down menu
For i = 0 To dv.Count - 1
With ddMenu.Items
// add a new item
.Add(dv.Item(i).Item("Name"))
// set the Value property as unique ID of object
.Item(i + 1).Value = dv.Item(i).Item("ID")
End With
Next
End If
End If
Turns out it was an issue with my page loading twice...so now the issue is going to be tracking down why it is loading twice!
I guess the Range validator verifies the actual "value" of the dropdown list. May it be possible that by using jQuery to populate your dropdown the actual entry doesn't get a proper option "value"? Could you maybe post the rendered HTML code of your dropdown list?