Removing Dynamic Controls

G

Guest

I have a form where I have created created between 1 and 20 buttons on the
form via code. Each button shows a customer name based on that customer
having an open order. This form must update itself every 1 minute to display
any new customers that may have opened orders. Now, I have no problem
initially displaying the buttons accordingly. But, when I attempt to refresh
the screen I get unexpected results. So, my goal is to remove the buttons
every 1 minute and redisplay the new set. Thus, if a new button must be
added, it will appear, or if one needs to be taken away it will be gone.

I've used the following code to create the buttons.

Dim btn as Button
For x = 1 to intNumberOfCustomers
btn.text = CustomerName
btn.name = "btn" & x
controls.add(btn)
Next x

This displays the buttons perfectly. What I need is a procedure that will
remove all of these buttons before I refresh them. The reason I need to do
this si because if I just rerun the procedure the names on the buttons are
not always correct. The number of buttons are correct, but not the labels.

So, my thought was to delete/remove all the buttons before recreating them
again. I used the following code, which does nothing.

Dim btn as button
For x = 1 to intNumberOfOrders
btn.Name = "btn" & x
Controls.Remove(btn)
Next x

What can I do to have all the dynamicly created buttons removed so I can
start all over?
 
A

Armin Zingler

Greg said:
What can I do to have all the dynamicly created buttons removed so I
can start all over?

When adding them, put them all into a panel. Later, you can remove all
controls in the panel (ThePanel.Controls).


Armin
 
R

rowe_newsgroups

Dim btn as button
For x = 1 to intNumberOfOrders
btn.Name = "btn" & x
Controls.Remove(btn)
Next x

Since Armin already told you a great way to fix your problem I figured
I'd try to enlighten you as to why this code failed.

What your code is effectively doing is creating a new button that
shares a name with a button already on the form. Unfortunately, this
will not magically link your button object to the one on the form, as
the Name property can be shared by multiple controls. Instead what you
need to do is to find the button by it's name. For that you can use:

/////////////////
For i As Integer = 1 To intNumberOfOrders
'// Since Me.Controls.Find(...) returns an array of
'// controls that match the name, we must search the
'// entire array for the button(s) to remove.
Dim matchedControls As Control() = Me.Controls.Find("btn" &
i.ToString(), False)
For Each control As Control In matchedControls
'// Only remove the buttons
If TypeOf (control) Is Button Then
Me.Controls.Remove(control)
End If
Next
Next
/////////////////

As you see that is a fairly complicated process to just get a control
to remove. If you're certain all the controls with a certain name need
to be removed, you can use the RemoveByKey method to greatly simplify
your code:

/////////////////
For i As Integer = 1 To intNumberOfOrders
'// This might be .Net 2.0 specific
Me.Controls.RemoveByKey(String.Format("btn{0}", i.ToString()))
Next
/////////////////

As you can see, Armin's method is much simpler, and much easier to
understand. I just wanted to explain why your code didn't work.

By the way you appear to have Option Strict turned off, you should
turn it on immediately and leave it on for all of your projects.

Thanks,

Seth Rowe
 
G

Guest

Regarding your comment on Option Strict. One, I did not realize it was off.
But, when I set it to On, my functioning project generated tons of errors.
The most common error message is "Option Strict On disallows implicit
conversions from Integer to Boolean" and so on.

The following statement became invalid for the same reason

If Me.cboOrderPartProcessID.EditValue = _

g_objCustomerOrdersDS.Tables("CustomerOrders").Rows(i).Item("OrderPartProcessID").ToString Then

The DataSet is returning an Integer value. Plus, I cannot get rid of the
..ToString item. Without Option Strict On, this works fine. Maybe if I
understood why this line won't work and what the alternative must be I will
turn it on. I even moved the DataSet value into an Integer variable and set
the EditVlue=IntegerValue and it was still worng. It mentioned something
about using "IS". Not quite sure how to do that.

I hipe I have been clear enough.
 
A

Armin Zingler

Greg said:
Regarding your comment on Option Strict. One, I did not realize it
was off.
But, when I set it to On, my functioning project generated tons of
errors.

Often, one ton would have created runtime errors because you were not aware
of the implicit, unwanted conversions done otherwise. Possible.
The most common error message is "Option Strict On disallows
implicit
conversions from Integer to Boolean" and so on.

The following statement became invalid for the same reason

If Me.cboOrderPartProcessID.EditValue = _

g_objCustomerOrdersDS.Tables("CustomerOrders").Rows(i).Item("OrderPartProcessID").ToString
Then

The DataSet is returning an Integer value. Plus, I cannot get rid of
the
.ToString item.

I don't know what EditValue and it's type is because symbol search doesn't
find this property. I'd say that I wouldn't use .Tostring because it's an
Integer unless you want to display the value. Probably CInt or
Directcast(..., integer) is better. Typed datasets solve this problem.
Without Option Strict On, this works fine. Maybe if
I
understood why this line won't work and what the alternative must be
I will
turn it on. I even moved the DataSet value into an Integer variable

ah, ok
and set
the EditVlue=IntegerValue and it was still worng. It mentioned
something
about using "IS". Not quite sure how to do that.

I hipe I have been clear enough.

Can you post the code? (Only declaration, assignment, comparison)


Armin
 
G

Guest

I just now have been getting around to follow up on this subject. I was
pulled of my project for a couple of weeks and am now resuming where I left
off.

Anyway, I've found everyone's suggestions to be useful. But, I've decided
I'm going to approach my specific situation a little differently.

Here's what I'm working on. I have a form that creates and displays buttons
dynamically. Each button represents a customer with an open order. As long as
a customer has an open order, they will have a button on the screen. But, I
am going to update this screen about every 10 or 15 seconds. What I was going
to do was remove all buttons and recreate them everytime, since I have the
procedures to do both. The problem with this is the screen flickers everytime
the buttons are deleted and added again.

What I have decided to do instead is rather than delete and add every 15
seconds, I shoudl instead just update my existing buttons. If a customer is
to be added, then I'll create an additional button, or if a customer leaves,
I will remove a button. But, each time I do this, I will step though all the
customers who have open orders and reset the buttons captions instead. I
think this will look much smoother since I won't be refreshing the buttons
everytime.

So, somehow I need to be able to determine how many buttons I have on the
screen with the "btnButton_" name prefix and then remove the highest ones
when customer leave the list. Or, I need to determine what the last button is
and add an additional button. Then, after figuring this out I need to step
through all of the buttons and update the captions appropriately.

So, in closing, I need to know how I can step through each control on the
form, determine if its a button I created dymanically (i.e. starts with
"btnButton_" following by a number)? Once I'm able to step throught each
button on the form, I think I should be able to figure the rest out.

Thanks.
 
J

Jack Jackson

In the form class:

For Each ctl as System.Windows.Forms.Control in Me.Controls
If ctl.Name.Length >= 10 AndAlso _
ctl.Name.Substring(0, 10) = "btnButton_" Then
...
End If
Next

If your buttons are your own class, say MyButton, then you could do
this inside the For loop:

Dim btn As MyButton = TryCast(ctl, MyButton)

If btn IsNot Nothing Then
...
End If
 

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