How to initialize an object array that was created inside a Structure in VB.NET? - vb.net

No matter what I do, I end up with Object reference not set to an instance of an object at runtime. The problem is RptParamList().
The Structure is...
Partial Class WebReports_RptGeneric
Inherits Page
Protected ObjUtils As New Utilities
Protected ObjDtn As New DataTable
Structure SchedParms
Shared ReportName As String
Shared RptParamList() As ParameterValue
End Structure
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim objSecurit As New STISecurity
Dim intRc As Integer
Dim objAudit As New Audits
...
Public Sub XqtSaveSched(ByVal sender As System.Object, ByVal e As System.EventArgs)
'Get Report Name and Report Parameters
paramList.Clear()
dt.Reset()
dt = ObjUtils.GetDataTableForQuery("sp_GetPosFieldNames", paramList)
ReDim SchedParms.RptParamList(13)
SchedParms.RptParamList(0).Name = "rpFY" (BLOWS UP HERE!!)
SchedParms.RptParamList(0).Value = CStr(Session("FY"))
SchedParms.RptParamList(1).Name = "rpUserID"
SchedParms.RptParamList(1).Value = "1000000"
SchedParms.RptParamList(2).Name = "rpShowLinks"
SchedParms.RptParamList(2).Value = CStr(False)
I tried adding the ReDim statement as an initializer, but that didn't work. I also tried SchedParms.RptParamList(0) = new ParameterValue() , but that didn't work either.

You need to create an array with the New keyword, otherwise RptParamList will be Nothing
Shared RptParamList As ParameterValue() = New ParameterValue(13) {}
If the array can grow, use a List(Of ParameterValue), rather than redimmming an array. Lists do that automatically.
Shared RptParamList As New List(Of ParameterValue)()
Then add items with the Add method
SchedParms.RptParamList.Add(New ParameterValue())

Related

VB - Find child form from parent

I am in a project with multiple form.
I create a TicTacToe form here :
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
Dim page As Form = New TicTacToe
page.Show(Me)
End Sub
Here is a TicTacToe form:
Public Class TicTacToe
Public opponent as String
'Some code where user set opponent
Public Function Receive(S As String)
if string = opponent
'Some code
End Function
End Class
I would like to call my function Receive in my main form
If i do:
TicTactoe.Receive(S)
It call a instance of Receive where opponent does not exist.
I would like to find the oppened form of TicTacToe and call Receive
Thanks
Comments in line
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
page.Receive("Joe")
End Sub
'A form level variable to hold a reference to the instance of TicTacToe
'Although vb.net can use default instances, you have created an explicit
'instance of TicTacToe so you need to keep a reference if you want to
'refer to this instance.
Private page As TicTacToe
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
page = New TicTacToe()
page.Show(Me)
End Sub
Partial Public Class TicTacToe
Inherits Form
Public opponent As String
'Functions must be declared as a Type
'If you do not need a return value use a Sub
Public Function Receive(S As String) As String
Dim someString As String = ""
If S = opponent Then
'Do something
End If
'There must be a return Value
Return someString
End Function
End Class
Use this to show the form
Dim page As TicTacToe
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
page = New TicTacToe
page.Show(Me)
End Sub
Then you can use
page.Receive(S)
Edit
To use multiple forms
For Each f As TicTacToe in Application.OpenForms().OfType(Of TicTacToe)
f.Receive (S)
Next
In C#, you'd need a new instance, but as you are in VB, the compiler already does that for you.
What you are currently doing, is creating a new instance of the TicTacToe form and showing it:
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
Dim page As Form = New TicTacToe
page.Show(Me)
End Sub
But you don't save that instance anywhere. Then, in your next piece of code, you are using a different instance, which is the static one created by the compiler:
TicTacToe.Receive(S) // TicTacToe is the static instance
Therefore, you end up calling two different instances, which explains why there is no opponent set.
To get around this problem, do not create a new instance. In your Private Sub MenuTicTacToe, just use the instance created by the compiler, and you won't have this problem, just like this:
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
TicTacToe.Show(Me)
End Sub
Hope this helps.

How to save many object (with the same class) to txt file and binding those object with listbox VB.NET

I try to program a simple project to save data to txt file, read it and use binding data to show it. My project like this.
When I add ID Person to "Add ID" textbox (Textbox which near Button "Add ID"). It will add ID to Listbox and "ID Name" textbox. With this IDName, I insert FirstName and LastName for first person and Save Person's Name. Then, I Add new ID in "Add ID" textbox and fill First,last name and save it again
I refer this page http://vbnetsample.blogspot.de/2007/12/serialize-deserialize-class-to-file.html?m=1 to save and read data to txt file. It's run ok. But my problem is that when I save Person 2 with ID 2, Person 1 is overwrited. I think I can save Person to List Person. But it will make difficult when I want to update any Person's data. I don't know whether Is there any way to save and update each person. And by the way How can I show data by binding data in listbox.
Here is my code
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Public Class Form1
Public pPerson As New Person
'Serialize and Save Data to txt file
Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveButton.Click
pPerson.IDName = IDNameTextBox.Text
pPerson.FirstName = FirstNameTextBox.Text
pPerson.LastName = LastNameTextBox.Text
Dim fs As FileStream = New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter()
bf.Serialize(fs, pPerson)
fs.Close()
End Sub
'Deserialize and Read Data from txt file
Private Sub ReadButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ReadButton.Click
If FileIO.FileSystem.FileExists("C:\Users\Bruce\Desktop\test.txt") Then
Dim fsRead As New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.Open)
Dim bf As New BinaryFormatter()
Dim objTest As Object = bf.Deserialize(fsRead)
fsRead.Close()
IDNameTextBox.Text = objTest.IDName
FirstNameTextBox.Text = objTest.FirstName
LastNameTextBox.Text = objTest.LastName
End If
End Sub
Private Sub AddIDButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddIDButton.Click
ListBox1.Items.Insert(0, AddIDTextBox.Text)
IDNameTextBox.Text = AddIDTextBox.Text
End Sub
End Class
'Create Class Person
<System.Serializable()>
Public Class Person
Private m_sIDName As String
Private m_sFirstName As String
Private m_sLastName As String
Public Sub New()
End Sub
Public Property IDName() As String
Get
Return Me.m_sIDName
End Get
Set(ByVal value As String)
Me.m_sIDName = value
End Set
End Property
Public Property FirstName() As String
Get
Return Me.m_sFirstName
End Get
Set(ByVal value As String)
Me.m_sFirstName = value
End Set
End Property
Public Property LastName() As String
Get
Return Me.m_sLastName
End Get
Set(ByVal value As String)
Me.m_sLastName = value
End Set
End Property
End Class
To me it seems like the issue here is
Dim fs As FileStream = New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.OpenOrCreate)
you have to change it to this:
If not File.Exists("C:\Users\Bruce\Desktop\test.txt") Then
File.create("C:\Users\Bruce\Desktop\test.txt")
End If
Dim fs As FileStream = New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.Append)
The whole problem was that your file was simply open (or created if it was not there before) and being written from the first line.By using FileMode.Append your File will be opened and anything new will be tried to be written at the end of the file.
Let me know if this worked :)

Retrieve a object from a list of objects in visual basic and use it to fill text/combo boxes

I have a class as seen below:
Public Class parameters
Public Property test As String
Public Property test_type As String
Public Property user_test_name As String
Public Property meas As String
Public Property spec As String
...etc
End Class
I make a list of objects that I import from a csv somewhere. The user_test_name's from the list gets sent to a list box:
For Each parameters In param
' MsgBox(parameters.user_test_name)
ListBox1.Items.Add(parameters.user_test_name)
Next
now when the user selects something from the list i want the rest of the properties of that particular user_test_name object to populate in certain text/combo boxes in the application. Here is how I grab what is selected.
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Dim selected_name As String = ListBox1.SelectedItem()
' MsgBox(selected_name)
find_object_by_user_test_name(selected_name)
End Sub
Now i'm having difficulty finding the object with the selected_name from the list and using its properties to fill the text.combo boxes. I tried the following to no success:
Public Sub find_object_by_user_test_name(ByVal description)
MsgBox(description)
Dim matches = From parameters In param
Where parameters.user_test_name = description
Select parameters
' MsgBox(matches)
' MsgBox(matches.user_test_name)
TextBox1.Text = matches.test
TextBox2.Text = matches.test_name
etc,,, on and on
' populate_area(matches)
End Sub
Instead of adding the name (a string) to the ListBox, add your actual INSTANCE to it.
First, override ToString() in your class so that it displays properly in your ListBox:
Public Class parameters
Public Property test As String
Public Property test_type As String
Public Property user_test_name As String
Public Property meas As String
Public Property spec As String
Public Overrides Function ToString() As String
Return user_test_name
End Function
End Class
Next, add each instance to the ListBox:
For Each parameters In param
ListBox1.Items.Add(parameters)
Next
Now, the SelectedIndexChanged() event, you can cast the SelectedItem() item back to parameters and you already have everything at your disposal:
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
If ListBox1.SelectedIndex <> -1 Then
Dim P As parameters = DirectCast(ListBox1.SelectedItem, parameters)
' ... do something with "P" ...
Debug.Print(P.user_test_name & " --> " & P.test)
End If
End Sub
If the user_test_names are unique, it may be easier to use a dictionary and retrieve the objects that way.
Dim params As New Dictionary(Of String, parameters)
params.add(MyParameterObject.user_test_name, MyParameterObject)
Then
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Dim selected_name As String = ListBox1.SelectedItem()
Dim selected_param as parameters = params(selected_name)
End Sub
Something like this should do it:
Public Sub find_object_by_user_test_name(ByVal description As String)
' assuming param is your list of parameter objects
For Each p In param
If p.user_test_name = description Then
TextBox1.Text = p.test
TestBox2.Text = p.test_name
...
Exit For
End If
Next
End Sub
A few notes about your code. First, you can't allow two objects to have the same user_test_name. Second, you can't use parameters as a variable name if you already have a class called parameters in your current namespace (which you do).
There is a simpler solution than any of these--just do the following:
Dim i as Integer = ListBox1.SelectedIndex
Then you can use i as an index to your original list of objects.

How do i get the object from one sub to the other sub

What i am trying to do is to get the intGuestID1 from page_load to be used in bth_add area
Because i am trying to get the ID when it has been clicked from another form to frmAddFollowUp so i tried to request it from the page_load as when i request from the add button, it only gives me the number 0 instead of the id from the previous form.
Partial Class frmAddFollowUp
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim objCDBFeedback As New CDBFeedback
Dim objCDBDepartment As New CDBDepartment
Dim intGuestID1 As Integer
Dim arrList As New ArrayList
If Page.IsPostBack = False Then
intGuestID1 = Request.QueryString("id")
arrList = objCDBDepartment.getAllDepartmentDropDownList
lstDepartment.DataSource = arrList
lstDepartment.DataTextField = "DepartmentName"
lstDepartment.DataValueField = "Department"
lstDepartment.DataBind()
End If
End Sub
Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAdd.Click
Dim CheckBoolean As Boolean = True
Dim objCDBFeedback As New CDBFeedback
Dim objCFeedback As New CFeedback
If txtStaffName.Text = "" Then
lblValidateStaffName.Text = "*Please enter Staff Name."
CheckBoolean = False
Else
lblValidateStaffName.Text = ""
End If
If txtFollowUpSummary.Text = "" Then
lblValidateFollowUpSummary.Text = "*Please enter Follow up summary."
CheckBoolean = False
ElseIf txtFollowUpSummary.Text.Contains("'") Then
txtFollowUpSummary.Text = txtFollowUpSummary.Text.Replace("'", "''")
Else
lblValidateFollowUpSummary.Text = ""
End If
If txtAmount2.Text = "" Then
lblValidateAmount2.Text = "*Please enter the Amount or put in NIL if there is no amount."
CheckBoolean = False
Else
lblValidateAmount2.Text = ""
End If
If CheckBoolean = False Then
If txtStaffName.Text.Contains("''") Then
txtStaffName.Text = txtStaffName.Text.Replace("''", "'")
End If
If txtFollowUpSummary.Text.Contains("''") Then
txtFollowUpSummary.Text = txtFollowUpSummary.Text.Replace("''", "'")
End If
Else
Dim intNumOfRecordsAffected As Integer
objCFeedback.GuestId = intGuestID1
objCFeedback.Feedback = txtFollowUpSummary.Text
objCFeedback.Department = lstDepartment.SelectedItem.Value
objCFeedback.StaffName = txtStaffName.Text
objCFeedback.Amount = txtAmount2.Text
intNumOfRecordsAffected = objCDBFeedback.addNewFollowUp(objCFeedback)
Response.Redirect("frmIncident.aspx")
End If
End Sub
You may either specify ByRef parameter type or use Function that returns reference of an object. In your code-snippet, you may declare variable at class-level (fields) so you may use them in different event handlers/sub.
Make intGuestID1 a private member variable. That will allow you to access this variable in both functions.
Is this code compiling? I do not see intGuestID1 being declared in btnAdd_Click, this should be throwing an error.
To declare a private member variable add the following above the Page_Load function, for example:
Partial Class frmAddFollowUp
Inherits System.Web.UI.Page
Private _intGuestID1 as Integer ' The _ prefix is just a naming convention that is used for class member variables, if you don't like it, you can remove it.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Now, in your Page_Load method, remove the line Dim intGuestID1 As Integer, as you no longer need to declare this. Finally, anywhere you see intGuestID1, rename it to _intGuestID1
Also, some ways to possibly refactor this is to create a Read Only Property that encapsulates the fact that you're getting _intGuestID1 from the QueryString. See the following example:
Private ReadOnly Property GuestID1() as Int32
Get
Return Request.QueryString("id")
End Get
End Property
One of the benefits of doing this is to perform any checks on the value before using it, such as, is it an actual number that is stored in Request.QueryString("id"), or is the user allowed to have access to the entity represented by this id, or whatever else you can think of. When you do this, you'll need to change all references to _intGuestID1 to GuestID1.

Bind a Class Property that returns a list to a DataGridViewComboBoxColumn

I have a file name that is found at multiple paths. I want to present this data to the user in the format of a DGV. I have a DGV with one text box column for the name, and another combobox column for the paths. I am having trouble getting the combobox column to bind to the property of the class that returns the paths.
Any help would be much appreciated.
Public Class fileTest
Public Property FileName As String
Public Property Paths As String()
Public Sub New(ByRef _name As String, ByVal _paths As String())
Me.FileName = _name
Me.Paths = _paths
End Sub
End Class
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim fileList As New BindingList(Of fileTest)
fileList.Add(New fileTest("TEST", {"ABC", "123"}))
Me.DataGridView1.AutoGenerateColumns = False
Me.DataGridView1.DataSource = fileList
Me.DataGridView1.Columns("FileName").DataPropertyName = "FileName"
CType(Me.DataGridView1.Columns("Paths"), DataGridViewComboBoxColumn).DataPropertyName = "Path"
End Sub
DataGridViewComboBoxColumn is horrible. HORRIBLE.
We eventually gave up using it and now just float a standard Combobox over the grid.