Field Validation in Repeater Control - asp.net

I have a question related to asp.net and vb.net. I have a repeater control that I bind some data to and allow users to update/change fields within certain text boxes. I added a validation control to trigger when the user doesn't enter a valid date or the text "TBD". On submit, I want to go through and highlight each field where its corresponding validator is not valid. This is my current code, but I am lost as to how to find the text box control.
Sub ValidateDateField(ByVal sender As Object, _
ByVal args As ServerValidateEventArgs)
'validate against three conditions - date, "TBD", and "N/A"
Dim dtValue = args.Value
If dtValue.ToUpper = "TBD" Or dtValue.ToUpper = "N/A" Then
args.IsValid = True
ElseIf IsDate(dtValue) Then
args.IsValid = True
Else
args.IsValid = False
Dim cont As WebControl = DirectCast(Page.FindControl(args.ToString), WebControl)
cont.BackColor = Drawing.Color.White
util.Client_Alert("Please Update Highlighted Fields")
End If
End Sub
I am completely lost as to how to get cont = textbox1row1 of my repeater control. Please advise. All examples I have seen so far directly state the control as in text1.BackColor =

So I figured out the answer. Sorry for the question. Don't know why I didn't think about it sooner. I found the naming container of the my custom val and then found the control based on its name in the repeater. in vb.net it was something like this:
Sub ValidateDateField(ByVal sender As Object, _
ByVal args As ServerValidateEventArgs)
'args holds value. validate against three conditions - date, "TBD", and "N/A"
Dim dtValue = args.Value
Dim cont As CustomValidator = sender
Dim myNC As Control = cont.NamingContainer
Dim strControl As String
strControl = cont.ControlToValidate
Dim txtbox As TextBox = _
DirectCast(myNC.FindControl(cont.ControlToValidate), TextBox)
If dtValue.ToUpper = "TBD" Or dtValue.ToUpper = "N/A" Or IsDate(dtValue) Then
args.IsValid = True
txtbox.BackColor = Drawing.Color.Empty
Else
args.IsValid = False
txtbox.BackColor = Drawing.Color.White
End If
End Sub

Related

How do I manage multiple FOR loops in Multiview Navigation Event Handler

Please bear with me a bit as I try to explain my problem.
I have multiple GridView controls, each with its own checkbox and textboxes.
User must either check the checkboxes or enter data into all textboxes.
If checkbox is not checked and textboxes within a particular gridview control is empty, when a user clicks the NEXT button of a multiview control, an error is raised.
The following code shows two FOR loops inside button click event of the NEXT navigation button.
The first Gridview1 FOR loop works great. If checkbox is not checked and the textboxes are empty, an alert message is displayed and user cannot navigate to next page.
If however, either the checkbox is checked or textboxes are filled with data, user can then successfully navigate to the next page.
The issue is with the second FOR loop for grvspouse gridview control.
If checkbox is not checked and textboxes are empty, the alert box is displayed with message that user must checkbox or enter data into textboxes. This is fine. However, the problem is that user is still taken to the next page.
Is there a way to handle multiple FOR loops inside BTN_NEXT navigation event handler?
Protected Sub btnNext_Click(ByVal sender As Object, ByVal e As EventArgs)
'If the message failed at some point, let the user know
For Each row As GridViewRow In Gridview1.Rows
Dim namesource As TextBox = TryCast(row.FindControl("txtsourcename"), TextBox)
Dim nmesource As String = namesource.Text
Dim addresssource As TextBox = TryCast(row.FindControl("txtsourceaddress"), TextBox)
Dim addrsource As String = addresssource.Text
Dim incomesource As TextBox = TryCast(row.FindControl("txtsourceincome"), TextBox)
Dim incmsource As String = incomesource.Text
Dim ckb As CheckBox = TryCast(row.FindControl("grid1Details"), CheckBox)
Dim checkb As Boolean = ckb.Checked
If checkb = False AndAlso nmesource = "" AndAlso addrsource = "" AndAlso incmsource = "" Then
ClientScript.RegisterStartupScript([GetType](), "Confirm", "jAlert('Please enter values on all textboxes or check the checkbox next to each textbox!');", True)
Else
myMultiView.ActiveViewIndex += 1
lblResult.Visible = True
End If
Next
For Each row As GridViewRow In grvspouse.Rows
Dim namespouse As TextBox = TryCast(row.FindControl("txtspousename"), TextBox)
Dim nmespouse As String = namespouse.Text
Dim addressspouse As TextBox = TryCast(row.FindControl("txtspouseaddress"), TextBox)
Dim addrspouse As String = addressspouse.Text
Dim incomespouse As TextBox = TryCast(row.FindControl("txtspouseincome"), TextBox)
Dim incmspouse As String = incomespouse.Text
Dim ckb2 As CheckBox = TryCast(row.FindControl("spouseDetails"), CheckBox)
Dim checkc As Boolean = ckb2.Checked
If checkc = False AndAlso nmespouse = "" AndAlso addrspouse = "" AndAlso incmspouse = "" Then
ClientScript.RegisterStartupScript([GetType](), "Confirm", "jAlert('Please enter values on all textboxes or check the checkbox next to each textbox!');", True)
Else
myMultiView.ActiveViewIndex += 1
lblResult.Visible = True
End If
Next
End Sub
[Edited]
You are facing this problem because you coded it that way....The easiest fix would be to create a STRING VARIABLE object and by each click,the program would check the VARIABLEfor a desired value and if the value matches then it'ld move to the next form.A complete example would look like this :
'Create a VARIABLE named HITCOUNT and keep the value empty at first.
Public class MyProject
Dim HITCOUNT as string = ""
If HITCOUNT = "" Then
For Each row As GridViewRow In Gridview1.Rows
Dim namesource As TextBox = TryCast(row.FindControl("txtsourcename"), TextBox)
Dim nmesource As String = namesource.Text
Dim addresssource As TextBox = TryCast(row.FindControl("txtsourceaddress"), TextBox)
Dim addrsource As String = addresssource.Text
Dim incomesource As TextBox = TryCast(row.FindControl("txtsourceincome"), TextBox)
Dim incmsource As String = incomesource.Text
Dim ckb As CheckBox = TryCast(row.FindControl("grid1Details"), CheckBox)
Dim checkb As Boolean = ckb.Checked
If checkb = False AndAlso nmesource = "" AndAlso addrsource = "" AndAlso incmsource = "" Then
ClientScript.RegisterStartupScript([GetType](), "Confirm", "jAlert('Please enter values on all textboxes or check the checkbox next to each textbox!');", True)
Else
myMultiView.ActiveViewIndex += 1
lblResult.Visible = True
End If
Next
HITCOUNT = "1" 'adding an integer value of 1(you can add anything)
End if
If HITCOUNT = "1" then
For Each row As GridViewRow In grvspouse.Rows
Dim namespouse As TextBox = TryCast(row.FindControl("txtspousename"), TextBox)
Dim nmespouse As String = namespouse.Text
Dim addressspouse As TextBox = TryCast(row.FindControl("txtspouseaddress"), TextBox)
Dim addrspouse As String = addressspouse.Text
Dim incomespouse As TextBox = TryCast(row.FindControl("txtspouseincome"), TextBox)
Dim incmspouse As String = incomespouse.Text
Dim ckb2 As CheckBox = TryCast(row.FindControl("spouseDetails"), CheckBox)
Dim checkc As Boolean = ckb2.Checked
If checkc = False AndAlso nmespouse = "" AndAlso addrspouse = "" AndAlso incmspouse = "" Then
ClientScript.RegisterStartupScript([GetType](), "Confirm", "jAlert('Please enter values on all textboxes or check the checkbox next to each textbox!');", True)
Else
myMultiView.ActiveViewIndex += 1
lblResult.Visible = True
End If
Next
HITCOUNT="2"
End if
'and move on and on
This is just one way and maybe the quickest one.There are many other ways to do so.If you don't wanna use this one, just comment and i'll post another solution

dropdownlist does not retain values after postback if it is inside formview and is populated at runtime

I need help figuring out why some controls that are inside a formview and are filled at runtime lose their contents after postback.
I have a dropdownlist (ddl_1) that I populate based on entries from another dropdownlist (ddl_2) in the same formview. All seem to work fine util a postback event occurs after which, the newly populated dropdownlist (ddl_1) is empty.
The EnableViewState for both these ddls is set to true. ddl_2 is databound but ddl_1 is not. In Page_Load in IsPostBack clause, ddl_2 is databound and then I call the function that populates ddl_1.
If I move ddl_1 outside of the formview, it retains its entries after postback just fine.
Another similar issue is with a TextBox inside the formview. When in insert mode, the contents of the TextBox disappear after postback. This does not happen in insert mode though.
What is specific to formview that causes this?
Thanks much.
Here is the Page_load code.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
If NavHelper.User.UserName = "" Then
Dim UserIP As String
Dim UserLogin As String
Dim UserEmail As String
UserIP = HttpContext.Current.Request.UserHostAddress
UserLogin = HttpContext.Current.Session("Username")
UserEmail = HttpContext.Current.Session("Email")
GetUserInfo()
CurrentRFQ = Nothing
If NavHelper.RFQ.ID = -1 Then
formview_RFQ.ChangeMode(FormViewMode.Insert)
tabpanelCustomerParts.Visible = False
tabpanelDocuments.Visible = False
tabpanelReviews.Visible = False
tabpanelRFQReviewHistory.Visible = False
listview_CustomerParts.Dispose()
Else
formview_RFQ.ChangeMode(FormViewMode.Edit)
listview_ReviewContracts_Initial.EditIndex = 0
SessionHelper.CurrentObject = TAA.Library.RFQ.GetObject(NavHelper.RFQ.ID)
mRFQ = DirectCast(SessionHelper.CurrentObject, TAA.Library.RFQ)
Dim UserdeptTotal As Long
UserdeptTotal = HttpContext.Current.Session("DepartmentTotal")
If formview_RFQ.FindControl("ddlCompanyBuyerNVList") IsNot Nothing Then
Dim ddl As DropDownList = DirectCast(formview_RFQ.FindControl("ddlCompanyBuyerNVList"), DropDownList)
FillCompanyNameDropDownList(ddl)
End If
tabpanelCustomerParts.Visible = True
tabpanelDocuments.Visible = True
tabpanelReviews.Visible = True
tabpanelRFQReviewHistory.Visible = True
If NavHelper.RFQ.Copy = True Then
SetModifyCopy()
End If
End If
Else 'IsPostBack
datasource_BuyerNVList.Dispose()
datasource_BuyerNVList.DataBind()
Dim ddl As DropDownList
If (formview_RFQ.CurrentMode = FormViewMode.Insert) Then
ddl = DirectCast(formview_RFQ.FindControl("ddlCompanyBuyerNVListInsert"), DropDownList)
ElseIf formview_RFQ.FindControl("ddlCompanyBuyerNVList") IsNot Nothing Then
ddl = DirectCast(formview_RFQ.FindControl("ddlCompanyBuyerNVList"), DropDownList)
End If
FillCompanyNameDropDownList(ddl)
End If
End If
End Sub
While binding the dropdown use the IsPostback option.
if (!IsPostback)
{
BindDropdown1();
BindDropdown2();
}
This will retain your state. If you are not using ispostback every time the dropdown will be binded when ever you refresh the page. So use ispostback for binding dropdown for the first time.

Asp.net session variables get mixed up

I have a user control that uses an UpdatePanel. The controls is essentially a table with a Button. When the user clicks the Button, a modal popup opens that allows them to select some value. Data for the table (which uses a Repeater as its DataSource) is stored in a session variable between partial postbacks (when the UpdatePanel fires) as a list of objects. Everything works fine if I have just one control but if I use this control in the same page more than once, the list of objects in the session variables get combined and are not separated for each control. I thought this might be because the session variable names are not unique, so anywhere I call or use the variable, I do it like this:
Dim sessionName as string = Me.UniqueID & "_" & "userNotificationDS"
Session(sessionName) = myListOfObjects
But this has not changed the outcome. Anyone know what I might be doing wrong here? If you believe the full code would be helpful, let me know.
Control Server Code:
Protected Sub delete_click(ByVal sender As Object, ByVal e As EventArgs)
Dim btn As LinkButton = CType(sender, LinkButton)
Dim ds As New List(Of myObject)
sessionName = Me.UniqueID & "_" & "myDataSet"
ds = Session(sessionName.ToString)
Dim id As String = btn.CommandArgument
ds.RemoveAll(Function(userNotification) userNotification.User.NetworkID.Equals(id))
Session(sessionName.ToString) = ds
bindData(ds)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
sessionName = Me.UniqueID & "_" & "myDataSet"
If (Session(sessionName.ToString) IsNot Nothing) Then
bindData(Session(sessionName.ToString))
End If
End Sub
Private Function buildPagedSet(ByVal userNotification As List(Of myObject)) As PagedDataSource
Dim ps As PagedDataSource = New PagedDataSource()
ps.DataSource = userNotification
ps.AllowPaging = True
ps.PageSize = numRows
Return ps
End Function
Public Sub bindData(ByVal commentList As List(Of myObject))
sessionName = Me.UniqueID & "_" & "myDataSet"
Dim currentPage As Integer = 0
Dim ps As PagedDataSource
Dim numLable As Label
Dim denomLable As Label
Dim curPage As Integer = 1
Dim totalPage As Integer = 0
If (Not myObject Is Nothing) Then
Try
ps = buildPagedSet(commentList)
totalPage = ps.PageCount
Session(sessionName.ToString) = commentList
rowTotal = ps.Count
'for paging
If Not (ViewState(Me.UniqueID & "_Page") Is Nothing) Then
currentPage = Convert.ToInt32(ViewState(Me.UniqueID & "_Page"))
Else
ViewState(Me.UniqueID & "_Page") = 1
currentPage = 1
End If
If (currentPage > 0 And currentPage <= ps.PageCount) Then
ps.CurrentPageIndex = currentPage - 1
Me.dataRepeateUsers.DataSource = ps
Me.dataRepeateUsers.DataBind()
ElseIf (currentPage >= ps.PageCount) Then
ViewState(Me.UniqueID & "_Page") = Convert.ToInt32(ViewState(Me.UniqueID & "_Page")) - 1
ElseIf (currentPage <= 0) Then
ViewState(Me.UniqueID & "_Page") = Convert.ToInt32(ViewState(Me.UniqueID & "_Page")) + 1
Else
End If
Catch ex As Exception
Throw
End Try
Else
Dim emptySet As New List(Of myObject)
Me.dataRepeateUsers.DataSource = emptySet
Me.dataRepeateUsers.DataBind()
End If
End Sub
The control is instantiated like this:
Me.notifier1.bindData(notificationList)
In this example, when the user deletes something from notifier1 ( the delete_click event) the object is removed from the list and it gets added back to the session. If anything causes notifier2's update panel to fire, it will display the same exact data as notifier1
My hunch is your are storing your myListOfObjects in the session but reusing that object somwhere and modifying it and storing it in the Session again with a different key. It is probably still the same object being stored for both Session keys.
You can do a simple test by storing an object in the Session with two differnt keys. Then pull it out using the first key and modify that object and don't reassign it back to the Session (not needed anyways). Now pull the other object out from the second key and look at it. It will match the modifications because the object is the same object just stored under two diffeent keys in the Session.
If Kelsey's hunch is correct, you could store each of the instances of myListOfObjects in a Dictionary(Of String, myListOfObjectsType) and use the .UniqueID as the key (the Of String part).

get value of label when button clicked in nested repeater asp.net vb

I have nested repeaters, each item in the nested repeater has a label and a button on it, i want to beable to access the label.text when the button is clicked, I think i'm nearly there as I can return the index of the repeater and nested repeater that is clicked, i'm just having some trouble finding the label itself.
You might be able to help me without me posting the repeater code. Here is my code behind for when the button is clicked.
Protected Sub btnEditUser_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim btnEditUser As Button = DirectCast(sender, Button)
Dim reClient As RepeaterItem = DirectCast(btnEditUser.NamingContainer.Parent.Parent, RepeaterItem)
Dim reUser As RepeaterItem = DirectCast(btnEditUser.NamingContainer, RepeaterItem)
Dim selectedClient As Integer = reClient.ItemIndex
Dim selectedUser As Integer = reUser.ItemIndex
Dim UserId As Label = DirectCast(reClients.Items(selectedClient).FindControl("lUserName"), Label)
Response.Write(selectedClient & " " & selectedUser & " " & UserId.Text)
End Sub
I'm currently getting this error 'Object reference not set to an instance of an object.' when trying to write the value of UserId.Text so i think i've got it slightly wrong in this line:
Dim UserId As Label = DirectCast(reClients.Items(selectedClient).FindControl("lUserName"), Label)
This is just a guess, but sometimes you get errors like this when not all rows contain the control you're looking for. Often the code loops through the rows in order, hits a header row first that doesn't contain the relevant control, and fails.
Here is a good MSDN article - Locating a Control Inside a Hierarchy of Naming containers.
Private Function FindControlRecursive(
ByVal rootControl As Control, ByVal controlID As String) As Control
If rootControl.ID = controlID Then
Return rootControl
End If
For Each controlToSearch As Control In rootControl.Controls
Dim controlToReturn As Control =
FindControlRecursive(controlToSearch, controlID)
If controlToReturn IsNot Nothing Then
Return controlToReturn
End If
Next
Return Nothing
End Function
Try it,
Dim UserId As Label =DirectCast(FindControlRecursive(repClient,"lUserName"),Label)

While creating a gridview programmatically, how do I evaluate the value of a column?

I am creating a gridview programmatically and I want to use the solution to this question: Programmatically access GridView columns and manipulate. In other words, I want to hide the hyperlinkfield and instead display a templatefield if the value of the "submitted" column in the row is 1. I'm listing employment applications and letting the user click "Load Application" if they have not yet submitted an application, or displaying "submitted" in plain text if they have already submitted it. I know how to do this if I create my gridview in the aspx file, but I don't know how to do this when I'm creating my gridview at runtime. Here's my code:
Public Sub getSavedApps(ByVal userID As Integer)
Dim ds As New DataSet
ds = clsData.sqlGetAllApps(userID)
If ds.Tables(0).Rows.Count > 0 Then
popAppSelect.Show()
'let user select which app they want to work on
Dim grdAppSelect As New GridView
'need to find out if this row has a value of 1 or 0 for submitted
Dim submitted As Boolean
'position column
Dim fieldPosition As New BoundField
fieldPosition.DataField = "positionDesired"
fieldPosition.HeaderText = "Position Desired"
If fieldPosition.DataField.ToString = "" Then
fieldPosition.DataFormatString = "<em>No position specified</em>"
End If
Dim colPosition As DataControlField = fieldPosition
'date column
Dim fieldDate As New BoundField
fieldDate.DataField = "dateStarted"
fieldDate.HeaderText = "Date Started"
Dim colDate As DataControlField = fieldDate
Dim strAppID(0) As String
strAppID(0) = "appID"
Dim colLoad As DataControlField
'submitted column
If submitted Then
Dim fieldLoad As New TemplateField
fieldLoad.ItemTemplate = New GridViewTemplate(DataControlRowType.DataRow, "submitted")
colLoad = fieldLoad
Else
Dim fieldLoad As New HyperLinkField
fieldLoad.Text = "<b>Load Application »</b>"
fieldLoad.DataTextFormatString = "{0}"
fieldLoad.DataNavigateUrlFields = strAppID
fieldLoad.DataNavigateUrlFormatString = "?load={0}"
colLoad = fieldLoad
End If
'add the columns to the gridview
With grdAppSelect
.ID = "grdAppSelect"
.CssClass = "grdAppSelect"
.CellPadding = 5
.BorderWidth = "0"
.HeaderStyle.HorizontalAlign = HorizontalAlign.Left
With .Columns
.Add(colPosition)
.Add(colDate)
.Add(colLoad)
End With
.AutoGenerateColumns = False
.DataSource = ds.Tables(0)
.DataBind()
End With
Dim lnkNew As New HyperLink
lnkNew.Text = "<b>Start New Application »</b>"
lnkNew.NavigateUrl = "?load="
Dim strClear As New LiteralControl
strClear.Text = "<br class='clearer' />"
'add the controls to the panel
pnlAppSelect.Controls.Add(grdAppSelect)
pnlAppSelect.Controls.Add(strClear)
'pnlAppSelect.Controls.Add(lnkNew)
Else
'should be apps there but couldn't find them
lblGeneralError.Text = "Could not find any previously started applications."
End If
End Sub
I found the solution. I needed to add an event handler when I created the gridview so that I could access the RowDataBound event and do the evaluation there. Here's the event handler code I used:
AddHandler grdAppSelect.RowDataBound, AddressOf grdAppSelect_RowDataBound
Then I just did my evaluation during RowDataBound like so:
Sub grdAppSelect_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim load As Control = e.Row.Controls(2)
Dim submitted As Control = e.Row.Controls(3)
Dim submittedText As String = e.Row.Cells(3).Text
If submittedText = "True" Then
load.Visible = False
End If
submitted.Visible = False
End If
End Sub

Resources