PreviousPage and control created at run-time - asp.net

At run-time I add a textbox with
Dim MRNCell As New TableCell
MRNCell.ID = "MRNCell"
Dim txtMRN As New TextBox
txtMRN.ID = "NewMRN"
MRNCell.Controls.Add(txtMRN)
MRNRow.Cells.Add(MRNCell)
I then attempt to access the Text property in a public readonly Property using PreviousPage. Below are three renditions of the Property, none of which works.
Public ReadOnly Property NewMRN() As String
Get
Dim NewMRNNum As TextBox = CType(Me.FindControl("NewMRN"), TextBox)
'NewMRNNum = Nothing
Return NewMRNNum.Text
End Get
End Property
Public ReadOnly Property NewMRN() As String
Get
Dim sNewMRN As String = String.Empty
For Each MyRow As TableRow In MyTable.Rows
For Each MyCell As TableCell In MyRow.Cells
If MyCell.ID = "MRNCell" Then
For Each MyControl As Control In MyCell.Controls
Dim MRNBox As New TextBox
MRNBox = TryCast(MyControl, TextBox)
If Not (MRNBox Is Nothing) Then
sNewMRN = MRNBox.Text
End If
Next
End If
Next
Next
'There is only one TextBox in the table and sNewMRN = ""
Return sNewMRN
End Get
End Property
Public ReadOnly Property NewMRN() As String
Get
'For this one the TextBox is declared Public in the class
'The Text property = ""
Return txtMRN.Text
End Get
End Property
I have two public readonly properties. The first one returns the Text property from a TextBox created in the designer and the other attempts to return the Text property created at run-time. One works and the other either throws an exception or returns an empty string, depending on which of the three methods I use.
If Not PreviousPage Is Nothing Then
'Works
Dim sMessageID As String = PreviousPage.MessageID
'Does not work
Dim sNewMRN As String = PreviousPage.NewMRN
Literal1.Text = "<p>" & sMessageID & "</p><p>" & sNewMRN & "</p>"
End If
So, how can I access the Text property of a Textbox created at run-time, have that value returned in a public readonly property, so I can access it with PreviousPage?
Greg

Once again, writing the question made me think about it enough that I came up with a solution. I add the textbox at design-time and set the visible property to false. Then at run-time I make it visible and add it to the table row cell.
Greg

Related

Can i use a single session variable to store all the field values

I have 9 pages with 10 fields in each page. Can i use a single session variable to store all the field(textbox,drop downlist,radiobuttons) values of 9 pages? If so could you give me small example inorder to proceed. Im kind of stuck.
Could you? Yes. Should you? Most likely not - though I can't say for sure without understanding what problem you are intending to solve.
Update with one sample solution
OK, I'm going to assume you want to store the values from the controls and not the controls themselves. If so, the easiest solution is stuff them in using some meaningful token to separate them. Like:
Session("MyControlValueList") = "name='txt1',value='hello'|name='txt2', value'world'"
To retrieve you would split them into a string array:
myArray = Session("MyControlValueList").Split("|")
And then iterate through to find the control/value you want.
So strictly speaking that's an answer. I still question whether it is the best answer for your particular scenario. Unfortunately I can't judge that until you provide more information.
Create a custom class with all the fields you want to save, then populate an instance of that and save that instance as a session variable.
I have something similar, but not identical - I'm saving various shipping address fields for an order, and I'm allowing the admins to update the order, either the shipping information or the order line items. Since that information is kept on separate tables, I store the shipping information in a session variable, and then compare it to what's on the form when they hit the "Update" button. If nothing has changed, I skip the update routine on the SQL Server database.
The easiest way for me to do this was to create a "OrderInfo" class. I saved the shipping information to this class, then saved that class to a session variable. Here's the code showing the class -
Public Class OrderInfo
Private v_shipname As String
Private v_add1 As String
Private v_add2 As String
Private v_city As String
Private v_state As String
Private v_zipcd As String
Private v_dateneeded As Date
Private v_billingmeth As Integer
Public Property ShipName() As String
Get
Return v_shipname
End Get
Set(value As String)
v_shipname = value
End Set
End Property
Public Property Add1() As String
Get
Return v_add1
End Get
Set(value As String)
v_add1 = value
End Set
End Property
Public Property Add2() As String
Get
Return v_add2
End Get
Set(value As String)
v_add2 = value
End Set
End Property
Public Property City() As String
Get
Return v_city
End Get
Set(value As String)
v_city = value
End Set
End Property
Public Property State() As String
Get
Return v_state
End Get
Set(value As String)
v_state = value
End Set
End Property
Public Property ZipCd() As String
Get
Return v_zipcd
End Get
Set(value As String)
v_zipcd = value
End Set
End Property
Public Property DateNeeded() As Date
Get
Return v_dateneeded
End Get
Set(value As Date)
v_dateneeded = value
End Set
End Property
Public Property BillingMeth() As Integer
Get
Return v_billingmeth
End Get
Set(value As Integer)
v_billingmeth = value
End Set
End Property
End Class
Here's the code for when I tested the concept to see if I could store a custom class in a session variable. This routine gets the order record, populates the fields in an instance of the custom class, and on the web form, as well. I save that instance to a session variable, then I initialize another new instance of that custom class, load the session variable to it. I then display the field values from the "retrieved" custom class, and what showed on the label matched what it should be -
Protected Sub LoadOrderInfo(ByVal ordID As Integer)
Dim connSQL As New SqlConnection
connSQL.ConnectionString = ConfigurationManager.ConnectionStrings("sqlConnectionString").ToString
Dim strProcName As String = "uspGetOrderInfoGeneral"
Dim cmd As New SqlCommand(strProcName, connSQL)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("OrderID", ordID)
If connSQL.State <> ConnectionState.Open Then
cmd.Connection.Open()
End If
Dim drOrderInfo As SqlDataReader
drOrderInfo = cmd.ExecuteReader
If drOrderInfo.Read Then
Dim orgOrder As New OrderInfo
orgOrder.ShipName = drOrderInfo("shipName")
orgOrder.Add1 = drOrderInfo("ShipAdd1")
orgOrder.Add2 = drOrderInfo("ShipAdd2")
orgOrder.City = drOrderInfo("ShipCity")
orgOrder.State = drOrderInfo("ShipState")
orgOrder.ZipCd = drOrderInfo("ShipZip")
orgOrder.DateNeeded = drOrderInfo("DateNeeded")
orgOrder.BillingMeth = drOrderInfo("BillingMethodID")
If Session.Item("orgOrder") Is Nothing Then
Session.Add("orgOrder", orgOrder)
Else
Session.Item("orgOrder") = orgOrder
End If
' I could just as easily populate the form from the class instance here
txtShipName.Text = drOrderInfo("shipName")
txtAdd1.Text = drOrderInfo("ShipAdd1")
txtAdd2.Text = drOrderInfo("ShipAdd2")
txtCity.Text = drOrderInfo("ShipCity")
txtState.Text = drOrderInfo("ShipState")
txtZipCd.Text = drOrderInfo("ShipZip")
selDate.Value = drOrderInfo("DateNeeded")
ddlBillMeth.SelectedValue = drOrderInfo("BillingMethodID")
End If
cmd.Connection.Close()
Dim retOrder As New OrderInfo
retOrder = Session.Item("orgOrder")
lblWelcomeMssg.Text = retOrder.ShipName & ", " & retOrder.Add1 & ", " & retOrder.City & ", " & retOrder.DateNeeded.ToShortDateString & ", " & retOrder.BillingMeth.ToString
End Sub
This might not be practical or desirable, given the number of fields you are trying to hold onto that way, but I'm not here to judge, so this is one possibility. I've worked with other projects where you create a table, and save that table as a session variable, so whatever structure you put into an object is retained if you save that object as a session variable.

ASP.NET DropDownList Selected Value With Enumeration

I'm using the settings in an enumeration to populate a dropdownlist in ASP.NET 4.0. The problem I'm having is that when I attempt to set a selected value other than first item, it throws an error telling me it cannot have more than one option selected.
Here's a sample of the code:
Public Shared Function ConvertEnumToArray(ByVal enumType As System.Type, _
Optional ByVal DefaultValue As String = "nodefault", _
Optional ByVal PromptValue As String = "", _
Optional ByVal PromptText As String = "") As ListItem()
Dim itemSelected As Boolean = False
Dim i As Int32 = 0
If Not enumType.IsEnum Then
Throw New Exception(String.Format("Type {0} is not an enumeration.", enumType.Name))
End If
'Dim itemValues() As Array = [Enum].GetValues(enumType)
Dim fields As FieldInfo() = enumType.GetFields()
Dim itemNames() As String = [Enum].GetNames(enumType)
Dim arr(itemNames.Length + 1) As ListItem
For Each field As FieldInfo In fields
If Not field.Name.Equals("value__") Then
Dim item As New ListItem(field.Name, field.GetRawConstantValue().ToString())
If item.Value = DefaultValue And DefaultValue <> "nodefault" Then
item.Selected = True
itemSelected = True
End If
arr(i) = item
i = i + 1
End If
Next
If PromptText <> "" Then
Dim item As New ListItem(PromptText, PromptValue)
If Not itemSelected Then
item.Selected = True
End If
arr(i) = item
End If
Return arr
End Function
Dim arrExtraChargesOptions() As ListItem
arrExtraChargesOptions = Enumerations.ConvertEnumToArray(GetType(Enumerations.MoneyRoomCourierExtraChargesOptions))
For Each li As ListItem In arrExtraChargesOptions
'since arrays double in capacity to store data, there may be nulls
If Not li Is Nothing Then
Me.drpMondayExtraCharges.Items.Add(li)
End If
Next
Me.drpMondayExtraCharges.ClearSelection()
Me.drpMondayExtraCharges.SelectedIndex = -1
Me.drpMondayExtraCharges.Items.FindByValue(Courier.MondayExtraCharge.ToString()).Selected = True
Despite clearing the selected value in multiple ways, the first item remains selected resulting in the error as mentioned above.
Other items that might help explaining how I ended up with the code above:
I'm setting the return type of the function to an array since that's the parameter type the AddRange function on the DropdownList.Items expects, but when I used that method, an exception resulted due to the NULLs in the array.
Before adding the ClearSelection() and SelectedIndex = -1 lines, my setting the selected value (either through the FindByValue as above or just directly setting the SelectedValue) resulted in my desired selected value being ignored.
Any thoughts? Thanks.
EDIT: I misspoke above (bad memory): Setting the SelectedValue directly results is what results in it being ignored. It has nothing to do with ClearSelection Or SelectedIndex =1 as I stated in the second bullet up above.
I found this issue (and I didn't provide enough code for you to find it yourselves).
Basically, I had a dropdownlist for each day of the week and the list items returned by ConvertEnumToArray above were added to each of the dropdowns. As a result, the selected item was changed on all the dropdown since the same list items were on each dropdown. Adding them to the dropdown as New Listitems solved the problem.

System.ArgumentException: String value can not be converted to a date

I have a web form that uses an Ajax date calendar. This works fine. The problem that i have is that when i submit my form i get the following message.
'String value can not be converted to a date' .AgendaDate = New SmartDate(txtAgendaDate.Text)
Here is my web form that holds the calendar and the associated text box...
<td>
<asp:TextBox ID="txtAgendaDate" runat="server" ForeColor="Black" ></asp:TextBox>
</td>
<td>
<asp:ImageButton runat="Server" ID="ImageButton1" ImageUrl="~/images/calendarpic.png"
AlternateText="Click here to display calendar" />
<cc1:calendarextender ID="CalendarExtender1" runat="server"
TargetControlID="txtAgendaDate" PopupButtonID="ImageButton1" >
</cc1:calendarextender>
</td>
I have a class with the associated properties on it for the web form. The rest of the fields work and submit data to the database except the textfield for the ajax calendar.
Here is my stripped down version for the code for the class and the txtAgendaDate code...
#Region " Agenda Variables "
'Declare Variables and data types and set default values
Private mAgendaID As Integer = 0
Private mOrganiser As String = ""
Private mMeeting As String = ""
Private mAgendaDate As SmartDate = New SmartDate()
#End Region
#Region " Constructors "
Public Sub New()
End Sub
Public Sub New(ByVal reader As SafeDataReader)
' Public Sub New(ByVal reader As SQLDataReader)
'Combine variables & property types
With reader
mAgendaID = .GetInt32("AgendaID")
mOrganiser = .GetString("Organiser")
mMeeting = .GetString("Meeting")
mAgendaDate = .GetSmartDate("AgendaDate")
End With
End Sub
#End Region
#Region "Properties"
'Define form field properies so that they can be used when adding the data to the database on the add button is pressed.
Public Property AgendaID() As Integer
Get
Return mAgendaID
End Get
Set(ByVal Value As Integer)
mAgendaID = Value
End Set
End Property
Public Property Organiser() As String
Get
Return mOrganiser
End Get
Set(ByVal value As String)
mOrganiser = value
End Set
End Property
Public Property Meeting() As String
Get
Return mMeeting
End Get
Set(ByVal value As String)
mMeeting = value
End Set
End Property
Public Property AgendaDate() As SmartDate
Get
Return mAgendaDate
End Get
Set(ByVal Value As SmartDate)
mAgendaDate = Value
End Set
End Property
#End Region
End Class
Here is my command that looks connects to the DB and at the stored procedure and also has the parameters.
Public Class Agenda_TempDAL
Public Shared Function AddAgenda_Temp(ByVal Agenda_Temp As Agenda_Temp) As Integer
'Declare i as integer as 0
Dim iAgendaID As Integer = 0
'Database conn, this is linked to the web config file .AppSettings
Using dbconnection As New SqlConnection(ConfigurationManager.AppSettings("dbconnection"))
dbconnection.Open()
'Command to state the stored procedure and the name of the stored procedure
Using dbcommand As SqlCommand = dbconnection.CreateCommand
With dbcommand
.CommandType = CommandType.StoredProcedure
.CommandText = "Stored_Proc_Name"
'Create parameter for AgendaID and output
Dim oParam As New SqlParameter
oParam.ParameterName = "#AgendaID"
oParam.Direction = ParameterDirection.Output
oParam.SqlDbType = SqlDbType.Int
'Create parameters for the remaining fields
.Parameters.Add(oParam)
.Parameters.AddWithValue("#Organiser", Agenda_Temp.Organiser)
.Parameters.AddWithValue("#Meeting", Agenda_Temp.Meeting)
.Parameters.AddWithValue("#AgendaDate", Agenda_Temp.AgendaDate.DBValue)
'Simply execute the query
dbcommand.ExecuteNonQuery()
End With
End Using
End Using
'Need to return the agendaID as an integer.
Return iAgendaID
End Function
End Class
And here is the code behind the button ion the web page. This is the page that causes the error based on the property / field. The problem lies on this line...
.AgendaDate = New SmartDate(txtAgendaDate.Text)
The whole code for the button is here...
Protected Sub btnAddAgendaTemplate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddAgendaTemplate.Click
'This works alongside the Class named Agenda_Temp which has the properties and DB connection assigned to it for each web form field.
Dim oAgenda_Temp As New Agenda_Temp
'Within the object Agenda_Temp Class use the properties defined.
'They are required to be defined in the Agenda_Temp/ app code so we can use them within here.
With oAgenda_Temp
.Organiser = txtOrganiser.Text
.Meeting = txtMeeting.Text
.AgendaDate = New SmartDate(txtAgendaDate.Text)
'Within the object Agenda_Temp class use the defined DAL which includes all the DC connect and stored procedures.
oAgenda_Temp.AgendaID = Agenda_TempDAL.AddAgenda_Temp(oAgenda_Temp)
End With
End Sub
End Class
I understand that its telling me that the string value cannot be converted to a date but i don't know hoe to resolve this as i am new to .net 2010?
Any help much appreciated.
Convert the string to a date before newing it:
From MSDN:
string date = "01/08/2008";
DateTime dt = Convert.ToDateTime(date);
Your's would become
DateTime dt = Convert.ToDateTime(txtAgendaDate.Text)
Then pass the date to your SmartDate constructor:
oAgenda_Temp.AgendaDate = new SmartDate(dt)
The final result:
With oAgenda_Temp
.Organiser = txtOrganiser.Text
.Meeting = txtMeeting.Text
.AgendaDate = New SmartDate(Convert.ToDateTime(txtAgendaDate.Text))
'Within the object Agenda_Temp class use the defined DAL which includes all the DC connect and stored procedures.
oAgenda_Temp.AgendaID = Agenda_TempDAL.AddAgenda_Temp(oAgenda_Temp)
End With
As others have pointed out, you need to convert the input value to a DateTime. I don't know what the SmartDate() function is doing, but the error message clearly indicates that the value cannot be converted to a date.
Secondly, I would add some validation to make sure that the input is valid before you submit the page. Use the RequiredFieldValidator and CompareValidator or RegularExpressionValidator:
<asp:TextBox ID="txtDate" runat="server" ... />
<asp:RequiredFieldValidator ID="reqDate" runat="server" ErrorMessage="Required" Display="Dynamic" ControlToValidate="txtDate"></asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="regDate" runat="server" ControlToValidate="txtDate" ErrorMessage="Please enter a valid date in the format (mm/dd/yyyy)" ValidationExpression="^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d$"></asp:RegularExpressionValidator>

Programatically created ASP.NET TextBox retains Text value after PostBack even if Control is cleared

I have a drop down menu, and based on which item is selected, I call a web service and then dynamically create some text boxes.
The first time I drop down the menu and select an item, it works perfectly, and the text boxes are created and populated dynamically. However, the next time I drop down the menu (after the first postback), and select something different... after the second postback, the original values remain in the textboxes.
I am clearing all of the text boxes out of the placeholder, then re-creating them, and then setting a NEW value, how can they retain the OLD values... especially if I controls.clear them from the page?
Note: The second time they are being created, the textbox IDs DO end up being the same. Could that have something to do with it? This duplicate ID functionality will need to be supported.
My code, called from Page_Load, is as follows: (edited to add more code)
Private Sub RefreshEntity()
Dim XmlRecords As New XmlDocument
Dim XmlRecordsNode As XmlNode
Dim EntityType As String = EntityTypes.SelectedValue
Dim Entity As String = RecordValue.Value
Dim FieldName As String
Dim FieldValue As String
FieldPlaceHolder.Controls.Clear()
If RecordList.SelectedValue <> "Select..." Then
Try
XmlRecordsNode = LoginInfo.SharePointConnectWebService.GetMetaData(LoginInfo.WSUser, LoginInfo.WSPass, _
EntityType, Entity)
XmlRecords.LoadXml(XmlRecordsNode.OuterXml)
Catch ex As Exception
ConfirmLabel.Text = "<b>Error:</b><br>" & ex.Message.ToString
Return
End Try
Else
SetProperties.Visible = False
Return
End If
For Each OneNode As XmlNode In XmlRecords.SelectNodes("Fields").Item(0).ChildNodes
FieldName = OneNode.Name
FieldValue = OneNode.InnerText
Dim newLabel As Label = New Label()
newLabel.Text = FieldName & ": "
Dim newTextBox As TextBox = New TextBox()
newTextBox.ID = "Field-" & FieldName
newTextBox.Text = FieldValue
Dim newLine As Label = New Label()
newLine.Text = "<br><br>"
FieldPlaceHolder.Controls.Add(newLabel)
FieldPlaceHolder.Controls.Add(newTextBox)
FieldPlaceHolder.Controls.Add(newLine)
Next
SetProperties.Visible = True
End Sub
And the RecordValue.Value is a hidden field that gets populated in every Page_Load:
RecordValue.Value = RecordList.SelectedValue
Where RecordList is my DropDown menu.
This is likely due to ViewState or the Posted values clobbering your values.
Once a control is dynamically added to the controls collection it needs to catch up with all the page life cycle events that have already fired. In the case of a post back this means that the ViewState and/or the posted form value will clobber the .text property on the TextBox based on the order you're adding the dynamic controls to the controls collection and setting the .text property.
To fix this you can disable ViewState by setting the .EnableViewState property to false on the dynamically generate controls also add the controls to the controls collection before you set any properties on them.
For Each OneNode As XmlNode In XmlRecords.SelectNodes("Fields").Item(0).ChildNodes
FieldName = OneNode.Name
FieldValue = OneNode.InnerText
Dim newLabel As Label = New Label()
Dim newTextBox As TextBox = New TextBox()
Dim newLine As Label = New Label()
newTextBox.ID = "Field-" & FieldName
newLabel.EnableViewState = False
newTextBox.EnableViewState = False
newLine.EnableViewState = False
FieldPlaceHolder.Controls.Add(newLabel)
FieldPlaceHolder.Controls.Add(newTextBox)
FieldPlaceHolder.Controls.Add(newLine)
newLabel.Text = FieldName & ": "
newTextBox.Text = FieldValue
newLine.Text = "<br><br>"
Next
You're not storing the value in a Session variable and then putting it back into the text box later in your code?

Programatic referencing of literals and object properties

I have advice that this might work for programmatically filling a set of literals from a set of object properties:-
For i As Integer = 1 To noOfTexts
Dim ctl As Literal = DirectCast(FindControl("help" & i), Literal)
If ctl IsNot Nothing Then
ctl.Text = pageData.help(i).trim()
ctl.Visible = True
End If
Next
However, the line: ctl.Text = pageData.help(i).trim() fails because it's not understood that pageData.help(i) should translate to pageData.help1, pageData.help2, etc.
Is there some syntax that would achieve this in VS2010 Asp.net VB?
You can reference properties dynamically using reflection...
Dim PageDataType As Type = GetType(pageData)
Dim PropertyName As String = "help" & i
Dim Property As PropertyInfo = PageDataType.GetProperty(PropertyName)
Dim PropertyValue As String
If Property IsNot Nothing
PropertyValue = Property.GetValue(pageData, Nothing)
End If
Note: Reflection in .NET is slower than direct access, but not enough to make its use impractical

Resources