Items.Add For listbox

SacrificialArts

New member
Joined
Jun 30, 2006
Messages
2
Programming Experience
1-3
Sorry if this has already been covered, I could not find information as specific as this.

I am making an IM program and have made a form for entering new screennames. I have run into the following problem.

I have the following code for form1:
VB.NET:
[SIZE=2][COLOR=#0000ff]Private [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] MenuItem4_Click([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] MenuItem4.Click
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] AddBuddy [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Form2
AddBuddy.Show()
[/SIZE][SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Add([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] Item [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Object[/COLOR][/SIZE][SIZE=2])
ListBox1.Items.Add(Item)
[/SIZE][SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE]
And this for Form2:
VB.NET:
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] Sn [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Screenname
[/SIZE][SIZE=2][COLOR=#0000ff]Private [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Button2_Click([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] Button2.Click
[/SIZE][SIZE=2][COLOR=#0000ff]End
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Private [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Button1_Click([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] Button1.Click
Sn = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Screenname
Sn.Screenname = TextBox1.Text
Hide()
[/SIZE][SIZE=2][COLOR=#0000ff]Call[/COLOR][/SIZE][SIZE=2] Add(Sn.Screenname)
[/SIZE][SIZE=2][COLOR=#0000ff]End [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]

I got the idea for the code here, but it gives me an error that says that "Add" is not declared.What's more, when I ignore the error and run it, it works. Can anyone tell me how to "fix" the error? Any help is appreciated.
 
Dump "Call" and change it to the instance of your form1.

myform1.Add(Sn.Screenname)

-tg
 
Actualy, now that I look it over, it's not clear as to WHICH add is the problem.

-tg
 
TechGnome is right, you must preform that method on an instance of form1.

You can't find that reference from form2, form1 have to give it to form2. There is one property that is useful for this, the Owner property which is of type form. What you do is to assign the 'Me' instance of form1 to form2.Owner property when you create a new form2. form2 is then able to get a reference to form1 whenever it needs it from its own Owner property.

Also when you get the form1 instance from form2 you need to know about casting general objects into more specific ones, that is class objects that at some level are inherited from a base class may be stored (they call it 'boxing') in a variable of a more general type. For example all kinds of controls like Label/Button etc may be boxed into a variable of type Control because they are all derived from that base class. It's the same thing with forms, your form1 class inherits the System.Windows.Forms.Form class, this is the same type as the Owner property. How this works as briefly explained allow you to store your form1 instance into the Owner property, and when you want to retrieve it you get the correct instance, but it will be of the system form type. What you do then is to use one of the casting features like CType or DirectCast, in many cases you also have to check the type of some general type object with the TypeOf/GetType functionality before casting it into the specific type. The reason you must cast to a specific type is to access the type specific properties, those are the properties that only the inherited class got and not the base class, your Add method of form1 is one example of a type specific property, the base class system form does not have an Add method.

Here are the code examples, I have highlighed the key code changes with green:
VB.NET:
[U]'form1 - MenuItem4_Click:[/U]
 
Dim AddBuddy As New Form2
[COLOR=darkgreen]AddBuddy.Owner = Me[/COLOR]
AddBuddy.Show()
 
[U]'form2 - Button1_Click:[/U]
 
Sn = [SIZE=2][COLOR=black]New[/COLOR][/SIZE][SIZE=2] Screenname
Sn.Screenname = TextBox1.Text
[/SIZE][COLOR=darkgreen]Dim form1instance As Form1 = DirectCast(Me.Owner, Form1)[/COLOR]
[COLOR=darkgreen]form1instance.Add(Sn.Screenname)
[/COLOR]Me.Close()

I changed also you Hide to Close after finished transferring the data, because you don't seem to Show it again later consequently building up hidden form2 instances in memory, in the form1 method you have posted you always create a new instance of form2.
 
I'd like to make a semi-related point here -

I find reading your code quite hard because the variable names you have chosen arent that good - the code doesnt self-document and there are no documenting comments.

As an example, I'm guessing that Button2 is your Quit button, because the only thing it does is call End
Its a very minor additional step to rename the Button2 to btnQuitProgram after you add it to the form.

The same goes for Form1 and Form2 - if they had "proper" names it would be easier to guess at their purpose.

In a similar way, Form2.Add() as a sub name is very bland - add what? As an example, if you look at microsoft's DataTable object, you can see an AddRow sub. The name leads us to believe that calling it will add a row to the table. When you customize it in the designer, a wizard will go a step further for you.. If you make a DataTable of type IM_CONTACTSDataTable (lets say it maps to a database table called IM_CONTACTS), then the designer will create another method for you called AddIM_CONTACTSRow().

The difference between the two is one of type - specifically, AddIM_CONTACTSRow is a sub that takes as a parameter, an object of type IM_CONTACTSRow (which the designer has also made for you)

The others are discussing an OO concept called coupling - i.e. how much one object dpends on another object's existence to work. In your example youre trying to couple form1 and form2 very closely.

I'd like to hear a little more about the problem - (things i might have guessed if your variable naming was more descriptive) - because I think there's a base line issue here where youre trying to couple form1 and form2 together too much, and not encapsulating each form's data in the right way.

As an example, if Form2's job is to come on screen and ask the user to type some info about what thye want their screen name to be, address, display name, font and that sort of jazz, then form2 really has to operate independently. Then you would arrange your code like this:

in frmPreferences (form1 ?) you would have:
VB.NET:
Public Sub btnAddNewScreenName_Click(...) Handles btnAddNewScreenNam.Click
 
  Dim x as New frmSNInfoGatherer()
  x.ShowModal()
  'the form is shown and code execution halts until x closes
 
  'now i should ask x what the user entered
  Dim bo as New BuddyObject
  bo.ScreenName = x.GetScreenName()
  bo.DisplayFont = x.GetChosenFont()
 
  'listbox 1?
  lstKnownScreennames.Items.Add(bo)
End Sub


the crucial thing here is that frmSNInfoGatherer never gets to know about frmPreferences - it simply doesnt need to in order to do its job of prompting the user for some text. OO programming is all about making an object that represents something, it has internal data (secrets) and externally revealed data - reveal enough to make an object usable, and always seke to avoid the situation where one object fiddles with another object's data. Question yourself as to why that fiddling logic isnt in the fiddle target..
Program in a "when I want your opinion i'll ask for it" not a "when I want your opinion i'll give it to you" kind of way..

This is the concept of low coupling (objects dont depend on each other) and high cohesion (objects know everything about hemselves that they need to know in order to operate, all the relevant data and processes are stored inside the object)

As a further example, if we go to an old programming language like pascal, we might find a library called StringUtils
StringUtils might contain a function called Concat(s1, s2) where the s1/s2 are the two strings to be concatenated and the return value is the concatenated string
Nowadays in OO terms we have the Concat method as part of a string, so we can say:

Dim s as String = "hello"
Dim t as String = s.Concat("world")
We havent had a library such as StringUtils fiddling with other objects data..

There are still cases when this occurs and the purists might say "yes but take a string like 'hello world' - it's 11 characters. if you add a load of code to that for all the methods then you end up taking a lot of memory if you have 1000 strings"
Well.. not quite - the data is repeated, yes.. but modern OO programming languages only keep one copy of the compiled code for all string objects, because the code doesnt change.

Some fiddle-with-other methods still exist and I dont quite agree wiht the need. For example i must say:
String.Format("the number is {0}", myNumber)

I dont see why i cant just say:
"the number is {0}".Format(number)

but MS have decided I cant, for one reason or another I may never know..

Anyway.. use other objects, ask them to do stuff, dont fiddle with data that isnt yours. :) Hope that makes sense. If it doesnt, feel free to ask for clarification
 
Excellent points made on Naming and Coupling, cjard. :)

My points were that the 'DataCollector' dialog could if needed (as were the posted request) ask the caller to do stuff, but in order to do that the caller would have to identify itself first, only then would DC be holding an object and be in access of its properties and methods.
 
cjard said:
I dont see why i cant just say:
"the number is {0}".Format(number)

To correct myself here; you can. Just like you say myDate.ToString("date format string") you can also say myInteger.ToString("integer format string")
 
Back
Top