I have the following situation:
In form1's constructor, I create an instance of a class. This class's constructor performs some actions and is then to populate form1's listbox with said data.
When I run the code, I get an exception that a loop occured and that I should use me, not form1 but the listbox is not part of the class, so I can only connect to form1.listbox1.
If I add a button and put the code there, all works fine. How can I populate the listbox during program startup?
Here's an example of my code:
Form1:
Public Class Form1
Public MyClass1 As New MyClass
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
End Class
MyClass:
Public Class MyClass
Public MyList as new Listbox
Public Sub New()
'Constructor.
Me.MyList.AddItem ("Test")
Me.UpdateDebugView()
End Sub
Public Sub UpdateDebugView()
Form1.lTodoList = Me.MyList
End Sub
End Class
Exception thrown (translated to english):
The form referenced to itself while attempting to make a defaultitem, that lead to an endless loop. Reference inside the constructor of the form to the form using Me.
System.InvalidOperationException
CodePudding user response:
When you hold a reference to something, you can access its members, but it shouldn't access yours (in most cases). But you can communicate backwards with events.
Declare MyClass1 as WithEvents in the Form, and you can add a designer event handler to the code (alternatively, you can add the handler dynamically but I have done the prior below). Raise the event instead of trying to set something on the Form.
Public Class Form1
Public WithEvents MyClass1 As New MyClass
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Private Sub MyClass1_ToDo() Handles MyClass1.ToDo
Me.lToDoList = MyClass.MyList
End Sub
End Class
Public Class MyClass
Public MyList as new Listbox
Public Sub New()
'Constructor.
Me.MyList.AddItem ("Test")
Me.UpdateDebugView()
End Sub
Public Sub UpdateDebugView()
RaiseEvent ToDo
End Sub
Public Event ToDo()
End Class
I would normally pass back the state to the event handler, but I didn't feel good about passing a ListBox. Maybe you can expose a data structure instead of a UI control to keep the UI on the UI, and out of the class. This should work for you though
CodePudding user response:
The problem is the location of creating the MyClass object.
It is created at the beginning of class creation before anything else runs. You can fix it by moving the creation of secondary class levels to the form_load sub as follows:
Public Class Form1
Public MyClass1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.MyClass1 = new MyClass
End Sub
End Class
This ensures that the form loads fully before creating other classes and as such, they can now refer to items on Form1.