listbox hell

D

Dave Sauny

Ok, its a friday, I'm at work and I cant get this to work:

I have 3 listboxes on one tab control page. when i select an item in
listbox1 i want whatever is selected on the other 2 listboxes
unselected. when listbox2 is selected, 1 and 3 should have no items
selected and the same with listbox 3.

Sounds simple... should be simple! I have tried
listbox[x].clearselected(), listbox[x].selectedindex=-1 and beating it
with a large stick. But so far nothing seems to work. It appears to
work for the first 3 mouse clicks and then starts selecting one on
each listbox! I have added the above commands to the mousedown,
mouseclick, selectedindexchanged and every other event i can think of
in order to erradicate this problem with no success, so i am ask you
if you know of any other way of being able to do this?

Thanks

Dave
 
G

Guest

In the GotFocus event of each listbox, you should be able to clear the other
two listboxes. If this doesn't work, then I would be interested in how it
can be done.
 
C

Cor Ligthert

Dave,

I have the idea that this sample does what you ask.

I made it for this, so when I need to add comments, tell it than I will do
that, however when you understand it, than that looks for me always a little
bit silly..

\\\
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
For Each ctr As Control In Me.Controls
If TypeOf ctr Is ListBox Then
DirectCast(ctr, ListBox).SelectionMode _
= SelectionMode.MultiExtended
AddHandler DirectCast(ctr, ListBox).SelectedIndexChanged, _
AddressOf ListBox_SelectedIndexChanged
End If
Next
End Sub
Private Sub ListBox_SelectedIndexChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs)
For Each ctr As Control In Me.Controls
If TypeOf ctr Is ListBox Then
RemoveHandler DirectCast(ctr, ListBox).SelectedIndexChanged,
_
AddressOf ListBox_SelectedIndexChanged
End If
Next
Select Case DirectCast(sender, ListBox).Name
Case "ListBox1"
For i As Integer = 0 To ListBox3.Items.Count - 1
ListBox3.SetSelected(i, False)
Next
For i As Integer = 0 To ListBox2.Items.Count - 1
ListBox2.SetSelected(i, False)
Next
Case "ListBox2"
For i As Integer = 0 To ListBox1.Items.Count - 1
ListBox1.SetSelected(i, False)
Next
For i As Integer = 0 To ListBox3.Items.Count - 1
ListBox3.SetSelected(i, False)
Next
Case "ListBox3"
For i As Integer = 0 To ListBox2.Items.Count - 1
ListBox2.SetSelected(i, False)
Next
For i As Integer = 0 To ListBox2.Items.Count - 1
ListBox2.SetSelected(i, False)
Next
End Select
For Each ctr As Control In Me.Controls
If TypeOf ctr Is ListBox Then
AddHandler DirectCast(ctr, ListBox).SelectedIndexChanged, _
AddressOf ListBox_SelectedIndexChanged
End If
Next
///

I hope this helps?

Cor
 
D

Dave Sauny

cheers cor, i didnt know there was a setSelected method, it has been a
life saver on amonday morning! cheers

Cor Ligthert said:
Dave,

I have the idea that this sample does what you ask.

I made it for this, so when I need to add comments, tell it than I will do
that, however when you understand it, than that looks for me always a little
bit silly..

\\\
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
For Each ctr As Control In Me.Controls
If TypeOf ctr Is ListBox Then
DirectCast(ctr, ListBox).SelectionMode _
= SelectionMode.MultiExtended
AddHandler DirectCast(ctr, ListBox).SelectedIndexChanged, _
AddressOf ListBox_SelectedIndexChanged
End If
Next
End Sub
Private Sub ListBox_SelectedIndexChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs)
For Each ctr As Control In Me.Controls
If TypeOf ctr Is ListBox Then
RemoveHandler DirectCast(ctr, ListBox).SelectedIndexChanged,
_
AddressOf ListBox_SelectedIndexChanged
End If
Next
Select Case DirectCast(sender, ListBox).Name
Case "ListBox1"
For i As Integer = 0 To ListBox3.Items.Count - 1
ListBox3.SetSelected(i, False)
Next
For i As Integer = 0 To ListBox2.Items.Count - 1
ListBox2.SetSelected(i, False)
Next
Case "ListBox2"
For i As Integer = 0 To ListBox1.Items.Count - 1
ListBox1.SetSelected(i, False)
Next
For i As Integer = 0 To ListBox3.Items.Count - 1
ListBox3.SetSelected(i, False)
Next
Case "ListBox3"
For i As Integer = 0 To ListBox2.Items.Count - 1
ListBox2.SetSelected(i, False)
Next
For i As Integer = 0 To ListBox2.Items.Count - 1
ListBox2.SetSelected(i, False)
Next
End Select
For Each ctr As Control In Me.Controls
If TypeOf ctr Is ListBox Then
AddHandler DirectCast(ctr, ListBox).SelectedIndexChanged, _
AddressOf ListBox_SelectedIndexChanged
End If
Next
///

I hope this helps?

Cor

Dave Sauny said:
Ok, its a friday, I'm at work and I cant get this to work:

I have 3 listboxes on one tab control page. when i select an item in
listbox1 i want whatever is selected on the other 2 listboxes
unselected. when listbox2 is selected, 1 and 3 should have no items
selected and the same with listbox 3.

Sounds simple... should be simple! I have tried
listbox[x].clearselected(), listbox[x].selectedindex=-1 and beating it
with a large stick. But so far nothing seems to work. It appears to
work for the first 3 mouse clicks and then starts selecting one on
each listbox! I have added the above commands to the mousedown,
mouseclick, selectedindexchanged and every other event i can think of
in order to erradicate this problem with no success, so i am ask you
if you know of any other way of being able to do this?

Thanks

Dave
 
C

Cor Ligthert

Dave,
cheers cor, i didnt know there was a setSelected method, it has been a
life saver on amonday morning! cheers

Look good at the sample, because setSelected does an indexchange event and
gives than without preventing firing an endless loop, therefore I remove the
handler inside the method and add it again at the end.

Cor
 
L

Larry Serflaten

Cor Ligthert said:
Look good at the sample, because setSelected does an indexchange event and
gives than without preventing firing an endless loop, therefore I remove the
handler inside the method and add it again at the end.

To continue the discussion, here is another way to do that same task. Instead
of adding and removing handlers, it simply uses a 'busy' flag stored in the first
listbox to indicate no processing should be done.... While Cor's routine would
catch all listboxes, I went on the assumption that you know which listboxes you
want included in the group:

Private Sub ExclusiveListboxes(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles ListBox1.SelectedIndexChanged, _
ListBox2.SelectedIndexChanged, _
ListBox3.SelectedIndexChanged

If ListBox1.Tag Is Nothing Then
ListBox1.Tag = "BUSY"
For Each box As ListBox In New ListBox() {ListBox1, ListBox2, ListBox3}
If Not sender Is box Then
For idx As Integer = box.SelectedIndices.Count - 1 To 0 Step -1
box.SetSelected(box.SelectedIndices(idx), False)
Next
End If
Next
ListBox1.Tag = Nothing
End If
End Sub



One optimization would be to save the Listbox array at the module level to
avoid creating a new array each time a new listbox is selected. If you have
other events that would need the array, then it would be advantageous to
keep such an array alive for the entire lifetime of the form....

LFS
 
C

Cor Ligthert

Larry,

I agree I could have used this one instead of that case select, what would
make it a easier to understand and more efficient.

\\\
If Not sender Is box Then
///

However I think that the deleting and adding of the handler will be more
efficient in this case, because otherwise it is all the time catching a
fired event. That was the reason that I did it this way and not as I always
tell with a booleanswitch. (Or you would need a do events in your program
anyway)

While your use of that selectedindices optimizing it as well.

I avoided that array of controls to be not again the one who was comming
with that. I use it almost forever and than comes Hefried forever with that
for each control loop.

:)

I think that this would be more optimal.

\\\
Private lstbAr As ListBox()
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
lstbAr = New ListBox() {ListBox1, ListBox2, ListBox3}
For Each lstb As ListBox In lstbAr
AddHandler lstb.SelectedIndexChanged, _
AddressOf ListBox_SelectedIndexChanged
lstb.SelectionMode _
= SelectionMode.MultiExtended
Next
End Sub
Private Sub ListBox_SelectedIndexChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs)
For Each lstb As ListBox In lstbAr
If TypeOf lstb Is ListBox Then
RemoveHandler lstb.SelectedIndexChanged, _
AddressOf ListBox_SelectedIndexChanged
End If
Next
For Each lstb As ListBox In lstbAr
If Not sender Is lstb Then
For i As Integer = lstb.SelectedIndices.Count _
- 1 To 0 Step -1
lstb.SetSelected((lstb.SelectedIndices(i)), False)
Next
End If
Next
For Each lstb As ListBox In lstbAr
If TypeOf lstb Is ListBox Then
AddHandler lstb.SelectedIndexChanged, _
AddressOf ListBox_SelectedIndexChanged
End If
Next
End Sub
//

Stupid I did not make it directly this way.

:)

Cor
 
L

Larry Serflaten

Cor Ligthert said:
However I think that the deleting and adding of the handler will be more
efficient in this case, because otherwise it is all the time catching a
fired event.

When the user clicks on one Listbox, that very same event is fired
three (or more) times (once for the initial change and once each for
selected items in the other listboxes) but it does nothing in any event
after the first click event, other than the flag test. Those are all early
bound, and known quantities. I am thinking those events will be
raised quickly, with minimal code.

Do you really know how much code is added when you make a call
to RemoveHandler, 3 times, and then AddHandler 3 more times?

To verify the efficiency, we'd need to count CPU cycles (or time the
events) to see which is the shorter. I would suggest it may be that
simply letting the events be raised could result in fewer instructions
than removing and adding 3 event handlers. I don't know for sure,
but if I had to do it, I would still go with the boolean flag approach
due to its simpler design, and possibility that it may actually be faster
than removing and adding the handlers.

Why do you think events are less efficient?

LFS
 
C

Cor Ligthert

"Larry Serflaten" <[email protected]>

Inline this time
When the user clicks on one Listbox, that very same event is fired
three (or more) times (once for the initial change and once each for
selected items in the other listboxes) but it does nothing in any event
after the first click event, other than the flag test. Those are all
early
bound, and known quantities. I am thinking those events will be
raised quickly, with minimal code.

Do I see something wrong in my sample, there it is only one time removing
and adding three handlers for an index change altough I can even optimize
that by setting a static and test that to the sender, it becomes than even
again faster and than it will only be done by a change of the listbox.
\\\
Static last As Object
If Not last Is sender Then
'Routine Cor
End If
last = sender
///

What do you mean with "early bound" that looks as it is in my samples not
"early bound"?
Do you really know how much code is added when you make a call
to RemoveHandler, 3 times, and then AddHandler 3 more times?

No do you? Can be in my opinon be twice as your declaration in the sub
handles listbox1.indexchanged, listbox2.indexchanged... etc. And with that
static maybe even much less. However this I don't know just a gues.
To verify the efficiency, we'd need to count CPU cycles (or time the
events) to see which is the shorter. I would suggest it may be that
simply letting the events be raised could result in fewer instructions
than removing and adding 3 event handlers. I don't know for sure,
but if I had to do it, I would still go with the boolean flag approach
due to its simpler design, and possibility that it may actually be faster
than removing and adding the handlers.

Why do you think events are less efficient?

Everything that is done not needed is less efficient as far as I can see is
your routine while deselecting throwing an event and than goes doing the
routine again and again and again for every selected item that has to be
deselected.

Did you debug your sample, than you will probably see what I mean

Cor
 
L

Larry Serflaten

Cor Ligthert said:
Inline this time
Do I see something wrong in my sample, there it is only one time removing
and adding three handlers for an index change

Isn't that what I said, you remove and add handlers 3 times. (one for each
listbox)

What do you mean with "early bound" that looks as it is in my samples not
"early bound"?

Early bound, very simply, means the compiler knows what interface to use.
Therefore raising events can be made similar to calling a sub, rather than more
expensive techniques when late bound.

No do you? Can be in my opinon be twice as your declaration in the sub
handles listbox1.indexchanged, listbox2.indexchanged... etc. And with that
static maybe even much less. However this I don't know just a gues.

That was my point. Letting it raise the events will be very similar to calling a sub.
In this case the extras subs (events) do almost nothing, which you can see from the
the supplied code, so it will not be very many CPU instructions.

Adding and removing handlers has to do some kind of binding work on the objects
and may be a significant amount of CPU instructions, for each bound object.

I was only suggesting there may be fewer instructions used to just let it raise the
events, than to bind and unbind event handlers for each listbox change:
Everything that is done not needed is less efficient as far as I can see

You may want to rethink that opinion. For one example, the Arraylist
objects do many things that may not be needed, but when used for
dynamic lists, they result in the developer writting less code.

Did you debug your sample, than you will probably see what I mean

I saw what it did, and I mentioned that:
When the user clicks on one Listbox, that very same event is fired
three (or more) times (once for the initial change and once each for
selected items in the other listboxes) but it does nothing in any event
after the first click event, other than the flag test.

Apparently a timed test will be the best way to resolve which is more
efficient, but I don't have the time, nor interest to work on that now.
At this time, I just don't see adding and removing handlers as a common
practise. It is not something I count on doing for every event that may
or may not be recursive. My opinion may change at a later date, but
for now, I'd go with the fewer lines of code....

LFS
 
C

Cor Ligthert

Larry,

You really did not debug step by step your sample, than you would not have
written this message.

In this way explaining me what is early bound is realy abusing me, moreover
giving the idea, hat my sample is using late binding.
At this time, I just don't see adding and removing handlers as a common
practise.

And this is really anoying. I told that I mostly use a boolean, however in
this case, because the raising from the selected index change event inside
the sub, remove the handlers to avoid that consequently raising of the event
and with that recursevily running of the sub, what creates as the OP told in
his subject a "Listbox hell"

Cor
 
L

Larry Serflaten

Cor Ligthert said:
In this way explaining me what is early bound is realy abusing me,

You are not the only person reading these posts. I answered what
early bound meant because you asked, and others may want to know.
If you already knew the answer, then you've 'abused' me by asking a
question for which you already knew the answer!
And this is really anoying. I told that I mostly use a boolean,

You added that AFTER I posted my example. If you remember, I started
my first post with:

"To continue the discussion, here is another way to do that same task."

And then showed the flag method. Your first post was the handler method,
with no mention of a boolean switch until after I posted my example.
because the raising from the selected index change event inside
the sub, remove the handlers to avoid that consequently raising of the event
and with that recursevily running of the sub, what creates as the OP told in
his subject a "Listbox hell"

The OP did not mention recursive problems, you did, saying your manipulations
of the event handlers avoids it:

"Look good at the sample, because setSelected does an indexchange event and
gives than without preventing firing an endless loop,"

When I posted my example, you gave your opinion on why you thought your
version was better:

"However I think that the deleting and adding of the handler will be more
efficient in this case, because otherwise it is all the time catching a
fired event."

Since this is a discussion group, I was willing to discuss the pros and cons
but if you are going to take offense at someone questioning your opinion,
or read into the words, more than is there:

"What do you mean with "early bound" that looks as it is in my samples not
"early bound"?"

It is not going to be very enlightening to anyone when such bickering goes on.

Quite simply: "Those are all early bound, and known quantities."

Actually meant: Those (events) are all early bound, and (the instructions
within them are) known quantities.

I said nothing about your code not being early bound, yet you seem to say I
said they were not. What I did say was that adding and removing handlers will
include an unknown amount of CPU instructions.

I would suggest you start looking at posts in the NG as being a discussion
amoung friends and not read into them derogatory meanings, or other abusive
conversation, until it is plainly evident.

This makes twice now, that you have said (approximately) that I have insulted
you when it never started out like that. I am always open for discussion, but if
you are going to take a simple discussion as a personal attack, then my best
move would be to stop discussing things with you....

LFS
 
C

Cor Ligthert

Larry,

All in line and with open mind
You are not the only person reading these posts. I answered what
early bound meant because you asked, and others may want to know.
If you already knew the answer, then you've 'abused' me by asking a
question for which you already knew the answer!

No however when you add to an answer from me and start teaching me that
early binding is better than late binding, than you can not say that it is
more for everybody.
You added that AFTER I posted my example. If you remember, I started
my first post with:

Yes of course there was no reason to tell that earlier I am not writing a
book here.
"To continue the discussion, here is another way to do that same task."

From witch I told that it was an improvement
And then showed the flag method. Your first post was the handler method,
with no mention of a boolean switch until after I posted my example.

From which I all the time are telling that that does in my opinion not fit
in this case and ask you if you step by step debug your program, however
untill now you have not given any answer on that.
The OP did not mention recursive problems, you did, saying your
manipulations
of the event handlers avoids it:

This is for me a known "Listbox Hell" it is even more a "Hell" with the
Treeview
"Look good at the sample, because setSelected does an indexchange event
and
gives than without preventing firing an endless loop,"

It is not an endless loop it start in my opinion everytime again
recursevely, did you debug your program step by step.

And I told you that this (where the inside methode effects the event) is the
only place where I am not using a boolean however delete the handler that
catches the event.
When I posted my example, you gave your opinion on why you thought your
version was better:

Yes while I improved it first with your version as I told. That is the way a
discussion goes, it is not a message "Larry what are you good". It has to
improve going on.
"However I think that the deleting and adding of the handler will be more
efficient in this case, because otherwise it is all the time catching a
fired event."

Since this is a discussion group, I was willing to discuss the pros and
cons
but if you are going to take offense at someone questioning your opinion,
or read into the words, more than is there:

When you are giving indirect answers and not answer on the questions asked,
however give answer from what you would know that I know them, than you can
get these reactions.
"What do you mean with "early bound" that looks as it is in my samples not
"early bound"?"

Did you answer that question already, are there in my samples late bound
parts?
It is not going to be very enlightening to anyone when such bickering goes
on.

You can say that, it is in my opinion not enligthen to give answers that
seems to tell something, however tells endless times something else than is
asked.
Quite simply: "Those are all early bound, and known quantities."

What has that early bound to do in this message thread, I really do not
understand that.
Where is there not early binding and what is the addition?
I said nothing about your code not being early bound, yet you seem to say
I
said they were not. What I did say was that adding and removing handlers
will
include an unknown amount of CPU instructions.

What is than the reason to tell that what you are using is early bound. And
what does the last sentence tell. I don't understand what you want to prove
with that sentence.
I would suggest you start looking at posts in the NG as being a discussion
amoung friends and not read into them derogatory meanings, or other
abusive
conversation, until it is plainly evident.

That is what I do, however friends give answers, I did give my open opinion
to you, and than you started teaching me, that is not how grown up people
act.
This makes twice now, that you have said (approximately) that I have
insulted
you when it never started out like that. I am always open for discussion,
but if
you are going to take a simple discussion as a personal attack, then my
best
move would be to stop discussing things with you....

I do not believe you did insult me expressely, however teaching me something
I already know for a long time, is not something I and I assume other people
like. I do that not when not asked to other people and hope others will not
do that to me.

I am too open for discussion, so I ask you again what I am al the time
asking in this thread. "Did you already step by step debug your program. I
did that and that is my reason of the discussion all the time."

It is not the goal to show I am the best in this thread (than I would not
have said that a part of your solution was better). I have add and remove
those handlers with a reason instead of the use of a boolean. You give me
all the time the idea to avoid checking why I did that.

Cor
 
L

Larry Serflaten

No however when you add to an answer from me and start teaching me that
early binding is better than late binding, than you can not say that it is
more for everybody.

There are some methods that are late bound, (see DynamicInvoke), all I said
was that in this case these events are early bound. How is that teaching you?
It is simply stating (an obvious) fact. I can't help it if you think it means
something else. I said the amount of code that will be processed is pretty
well known, because you can see exactly what will be called during the
recursion, (it is the same event code) which was next to nothing (one simple
If test for all but the first call). I then said adding and removing handlers
involves a section of code that has an unknown length. For all we know it
may be a very expensive call, or in may not. The point is that it is unknown.
And finally I added that timed tests may be the way to see which is more
efficient:

"To verify the efficiency, we'd need to count CPU cycles (or time the
events) to see which is the shorter."

That was my side of the discussion, why have you gone off about who
is teaching who? It is a discussion, we can mention several things in a
discussion, even if you already know it. Things may be mentioned just to
remind everyone of critical points.

From which I all the time are telling that that does in my opinion not fit
in this case and ask you if you step by step debug your program, however
untill now you have not given any answer on that.

Yes I have:

--------------
Did you debug your sample, than you will probably see what I mean

I saw what it did, and I mentioned that:
--------------

I followed that with an explaination of what it does during recursion.

What did you see that you think I did not see? I said the recursive calls
do very little, they test the busy flag, and exit. That is a known amount of
work, and it is not very much. Adding and removing handlers is an unknown
amount of work. How many times can the event be recursively called before
it reaches the same amount of work as manipulating handlers? That also is
unknown. So how can it be said that one is more efficient than the other?

You said you would guess yours is better, and I have said I'd use the code
that is more easily known....

LFS
 
C

Cor Ligthert

Larry,

You said you would guess yours is better, and I have said I'd use the code
that is more easily known....
(Only in the part of the handlers, for the rest I have told yours was better
than my first)

However I do not haveany problem with that last sentence of you.

I only wanted to show that in this case adding and removing handlers was
special done with a purpose, while it mostly has in my opinion almost no
sense and can be done with a boolean.

:)

Cor
 
C

Cor Ligthert

Larry,

To give a more objective idea what takes it to add and remove a handler have
I made this testprogram.

It looks a little bit crazy, however when I had made it completly shared it
can give another (faster) behaviour I saw yesterday with Herfried.

(The time is of course relative to your computer)

Give it a try.

Cor

\\\
Public Class thisClass
Public Shared Sub main()
Dim mymain As New theprogram
mymain.Run()
End Sub
End Class
Public Class theprogram
Friend mylistbox As New ListBox
Public Sub Run()
Dim start As Integer = Environment.TickCount
Dim times As Integer = 99999
For i As Integer = 0 To times
AddHandler mylistbox.Click, AddressOf mylistbox2
AddHandler mylistbox.Click, AddressOf mylistbox2
Next
MessageBox.Show((times + 1).ToString & _
" times Adding and removing Handlers takes " & _
(Environment.TickCount - start).ToString & " Ms")
End Sub
Private Sub mylistbox2(ByVal _
sender As Object, ByVal e As System.EventArgs)
End Sub
End Class
///
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top