Add item to listbox from another form - vb.net

I'm trying to add items to listbox from another form but the listbox doesn't seem to update.
I have 3 form : frm1, frm2, frm3
this my code in frm1 to open frm2:
Using frm As New frm2
frm.ShowDialog()
End Using
frm2 has a listbox named list_xxx
code in frm3:
Private Sub add_item()
frm2.list_xxx.add("aaaa")
End Sub
i want to add item to frm2 from frm3. but no success the listbox still empty.
how to fix it?

You are almost certainly referring to the default instance of frm2 in that second code snippet but you aren't displaying the default instance in the first code snippet. If you display one form and then add items to a ListBox on another form, there should be no surprise that you can't see those items. Either use the default instance everywhere or not at all. The more correct option is not at all, but that would require other changes too. The easier option is everywhere, which means changing the first code snippet to this:
frm2.ShowDialog()
No Using statement because you're not creating an object.

Related

Me.controls.Item on a VB.net Form is returning System.nullReferenceException 'object reference not set...'

I've created a vb net form that uses an array list to load data into various controls. (ultimately this is to interface with the Autodesk Inventor API, but I'm not failing the API part)
My first form(1) works correctly. I needed to break my form into multiple forms due to too much information. In Visual Studio 2022 I copied my Form1, pasted it and renamed it to Form2 then changed the references to Form1 located in Form2.designer.vb. To switch between Forms, I created a 'MainMenu' form to call either Form1 or Form2
By all manner of double checking, my method of calling my Form1 or Form2 are a copy paste (other than form names)
On my new form2, I cannot access any controls using the Me.Controls.Item method. I use a button to run the population of my textbox controls, so they exist.
works:
Me.textbox1.text = "some string"
Me.text = "form name string"
doesn't work:
Me.Controls.Item("textbox1").text = "any string"
In debug, mousing over the error line I get:
Me = {Projectname.Form1...} Me.Controls = {System.Windows.Forms.Form.ControlCollection} Me.Controls.Item("textbox1") = Nothing
In the Autos window, I can see my textbox1 in Me.Controls > Owner > textbox1 (and my 'some string' value)
I can also see my control in the Locals Me > textbox1
I guess I did something wrong when Copy/Pasting my Form1 to Form2
I created a new Form3 and copy pasted the controls and the Code from my Form2 and I have the same issue.
I have crated a new Form4 and created a new control (textbox) without a copy paste and things seem to work on that form, so far.
I'm sure somebody could fix this in seconds, but I'm tapped out. My Form2 (i could have sworn it worked before) has a lot of time into formatting multiple layers of tablelayoutpanels and would really like to not re-create my form2 from scratch.
If Me.Controls.Item("textbox1") is Nothing then there is no control whose Name property is "textbox1" and whose direct Parent is the form. As you can see, there are two conditions that could cause that to be the case. The control you want does not have its Name property set to "textbox1" and/or its direct Parent is some other control, e.g. a Panel.
Personally, I would scrap that form and create a new one the conventional way. Obviously you have done something wrong so who knows how far-reaching the issue(s) is?

Passing Values from Multiple UserControls

Note: Similar Question can be found here.
How can I pass values from multiple User Controls? The question in the link above provides an answer however I find the answer very tedious in my situation and there is a delay in passing of the values. (I have to cycle to and from UserControl1 and UserControl2 multiple times while in UserControl1 committing a change of a textbox or label to see any passing of values in UserControl2.)
Either way, since I have multiple UserControls in which each has many textboxes, labels, and comboboxes, I would very much not like having to create separate Sub Routines and EventHandlers for each and every control with a value that I would like to pass.
Is there a better way? I was thinking something like...
'In UserControl10
Dim UserControl1 As New UserControl1
Dim UserControl2 As New UserControl2
Dim UserControl3 As New UserControl3
UC10Label1.Text = UserControl1.Label1.Text
UC10TextBox1.Value = UserControl2.TextBox1.Value
UC10ComboBox1.Text = UserControl3.ComboBox1.SelectedItem
The code above obviously does not work the way I would imagine, how can I achieve something similar with the least amount of code?
Edited: I have multiple custom UserControls in which I use as 'views'. In each UserControl there are labels, textboxes, & comboboxes. I have a Panel1 in which on a triggered event, will display a UserControl(1-9) in the panel; each UserControl is displayed one at a time and is contingent on an event. I want to be able to pass values from each UserControl(1-9) to UserControl10's labels, textboxs, or comboboxs etc..
I'm guessing that the last three lines aren't in a Sub. They're probably not working because they're executing before the form has been shown.
If you want to update them automatically in your program, you should put them in a sub, but suspend the form layout while they're updating and then resume layout when the code has finished. Like this
Private Sub UpdateUserControls()
Me.SuspendLayout()
UC10Label1.Text = UserControl1.Label1.Text
UC10TextBox1.Value = UserControl2.TextBox1.Value
UC10ComboBox1.Text = UserControl3.ComboBox1.SelectedItem
Me.ResumeLayout()
End Sub
Depending on when you want to update these controls, you can do it each time the form is shown by placing the above Sub in the Form's .Shown event.
Or you could do it automatically every so often by placing it in a Timer's .tick event.
Or you could choose to update them at certain points in your program by placing the sub somewhere in your code.

How can I destroy the previous instance of object and create new one whenever a function is called?

Whenever a user selects a cell in a sheet I want a windows form to appear and any previous windows form that was connected to the previously active cell to be dissapear. How can I do this?
I'm thinking a solution like the following would work, but I don't know if it is good practice and I also don't know how to execute the command that I have commented out
Sub CreateNewFormForActiveCellAndDeleteThePreviousOne()
'Remove all previous instances of class Frm
Dim Frm as New Frm
End Sub
Instead of creating a new form instance I'd suggest updating the data on the form instead. Thus, you will save resources required for creating a new form instance. For example, you may define a public field in the Form's class and update it according to the selected cell in Excel.

Referencing cell values on DataGridView from another form

This is bugging me. I have a "main" form named frmMain with a DataGridView object named objDataGrid.
When a user double clicks on a row or clicks another button, I hide the main form, open a new form and want to reference the values in the row selected by the user but I keep getting an error when I try to access some, but not all, of the datagridview's properties.
For example here is the code that opens the form:
On Error Resume Next
Me.Hide()
frmGenerate.Show()
In the frmGenerate's load event I do the following:
Dim frmMain As frmMain = Nothing
frmMain = New frmMain
Any time I try to grab a value from the grid I get various errors.
frmMain.objDataGrid.Item(1, 2).Value
frmMain.objDataGrid.Rows(2).Cells(4).Value
frmMain.objDataGrid.SelectedRows(0).Index
frmMain.objDataGrid.Item(1, frmMain.objDataGrid.SelectedRows(0).Index).Value
These return index out of range errors even though I know for sure the indexes are correct.
Any ideas?
Thanks.
Why are you creating a new instance of frmMain? You need to refer to the existing one where they've selected a row.
You could pass just the row of the datagrid or PK field values instead of referencing the other form.

How to handle updating a DataGridView when the bound DataSource goes to empty?

I have a DataGridView to which I've set a list of objects to the DataSource. (I'm in VS 2005 using VB.) I created the DataGridView by creating a Data Source of type AssetIdentifier and dragging that Data Source onto my form.
I want to update the DataGridView when the selection in either a combo box or another DataGridView changes. (Below I'm considering a click in another DataGridView.) The following works:
Public Class dlgShowAssets
' class member variable
Private assetIdList As List(Of AssetIdentifier)
' pertinent subs and functions
Private Sub RefreshAssetIdentifierDataGridView()
AssetIdentifierDataGridView.DataSource = assetIdList
End Sub
Private Sub AssetDataGridView_CellClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles AssetDataGridView.CellClick
assetIdList = RepopulateTheList(id)
Me.RefreshAssetIdentifierDataGridView()
End Sub
End Class
In this case, I always knew that assetIdList would have at least one element. I'd update the list, and reset the data source of the DataGridView to that list, and all was well.
When I applied this to another situation, for which I couldn't guarantee that the list would have at least one element, things would work fine as long as I had at least one element in the list, but if the list became empty, the DataGridView threw System.IndexOutOfRangeException a number of times. The rows in the DataGridView would not go away if I went from a non-zero number of elements to zero.
I tried a workaround, which was to remove all of the elements, add one "dummy" element, and then re-bind the list to the control, and it still didn't work.
Also, following all of those exceptions, I'd get other similar exceptions when I hovered over the cells in the DataGridView.
I've been trying to track down this behavior for a few hours. Any insights? Thanks!
Will be happy to add more info if needed.
UPDATE: Some of the members of AssetIdentifier were "Nothing" but I fixed that in the constructor, and the exceptions still occur.
Refactored code and it works ...