Re: Control Arrays in VB.NET
Looks good, although I don't have any need for it like yourself.
I do remember that in VB6 you would create control arrays by giving multiple controls the same name. They would then become a control array automatically if I remember correctly. That also means that copy/pasting a control in the designer would give the copy the same name, but naturally a different index. Since in .NET you can't have multiple controls with the same name I don't think implementing this feature is possible though. Perhaps with an extension for Visual Studio itself, but that would involve an effort much greater than just learning to live without control arrays :p
Re: Control Arrays in VB.NET
I missed control arrays for about 30 seconds after going into VB.Net (and/or C#). When I discovered that you can use a method for multiple controls that problem vanished.
-Max :D
Re: Control Arrays in VB.NET
Hi
Many thanks for your great app! I was just what I was looking for when I started a new project recently. The forms have multiple sets of checkboxes and radiobuttons and your class has simplified the design considerably.
However, I have had a problem with the sequence of the controls not following the index defined at the design stage. It appears to be related to the way the controls are defined in Designer.vb.
I solved the problem in my design by manually changing the designer code which, of course, is not ideal.
I can post a simple app showing the problem if required.
Also, is there a simple way at design time of removing the index from a group of selected controls?
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
Exem
I can post a simple app showing the problem if required.
That would be a good idea. I had a quick look at the code and didn;t see anything that would explain that.
Quote:
Originally Posted by
Exem
Also, is there a simple way at design time of removing the index from a group of selected controls?
Not as it stands. Because all controls must have different indexes, if you select multiple controls then the Index property will display blank. If you try to set a single value for multiple controls, which you could then clear, it will not work because the actual indexes used will be determined by the number of elements in the array. You might be able to change the implementation but you would lose something else as a result. You could add a designer function to the array itself to clear it. Maybe I'll try that some time as it's something I've never done before.
2 Attachment(s)
Re: Control Arrays in VB.NET
Thanks for your speedy reply.
You will see I have attached two zips - a 'Good' and a 'Bad'.
In both apps the form displays eight radiobuttons with only the first four having an index set. In the 'Good' app they sequence properly but not in the 'Bad' app where the sequence is 1, 4, 2, 3.
You can apparently change the index in the designer but the sequence is still wrong. If you close the solution and re-open the design then shows the wrong sequence.
Hope this is clear.
Re: Control Arrays in VB.NET
question... what do you mean by "Sequence" ? I'm asking because it sounds like you might be mistaking the Index value for the TabOrder value... but I haven't looked at your code yet either.
-tg
Re: Control Arrays in VB.NET
What I mean by sequence is the order the controls are returned by the code:
Code:
For Each rb In Me.RadioButtons1
rb.Select()
MessageBox.Show(rb.Name, String.Format("RadioButtons({0})", Me.RadioButtons1.IndexOf(rb)))
Next
I'm not confusing TabIndex but the values are set in order too.
Re: Control Arrays in VB.NET
fair enough... just wanted to eliminate the possibilities. I've seen some confuse one for the other.
-tg
Re: Control Arrays in VB.NET
I decided to try to fix the issue myself and found that the order of the controls in the list did not agree with the sequence set in the designer.
Here is my modification:
Code:
Public Overridable Sub SetIndex(ByVal control As TControl, ByVal index As Integer?)
If Not index.Equals(Me.GetIndex(control)) Then
'The control is either being moved to a different index or removed altogether, so remove it from its current index.
Me.Remove(control)
End If
If index.HasValue Then
'Insert the control at its new index, or to the end of the list if the index is invalid.
'was - Me.Insert(Math.Min(index.Value, Me.Count), control)
If index.Value > Me.Count - 1 Then
For i = Me.Count To index.Value
Me.Add(control)
Next
End If
Me.RemoveAt(index.Value)
Me.Insert(index.Value, control)
End If
End Sub
There may be a more elegant way of fixing the problem but this does appear to work for now.
Re: Control Arrays in VB.NET
Really you a professional.
Thanks...:)
Re: Control Arrays in VB.NET
Hi...
The ProvideProperty name became "Index on RadioButtons".
How can I get the name be "Index" without "on RadioButtons"?
Thanks...
-----------------------------------------------------------------------
-----------------------------------------------------------------------
Quote:
Originally Posted by
jmcilhinney
Please don't ask the same question in two different places. I've already answered this question in your own thread.
Sorry ..
Will not be repeated again.
Thanks..
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
a1024
Hi...
The ProvideProperty name became "Index on RadioButtons".
How can I get the name be "Index" without "on RadioButtons"?
Thanks...
Please don't ask the same question in two different places. I've already answered this question in your own thread.
Re: Control Arrays in VB.NET
How to share one procedure for all control in an array?
I know i can do with
Code:
For Each b In Buttons
AddHandler b.Click, AddressOf Buttons_Click
Next
Is it possible in code editor if i select Buttons from controls dropdown list, all events related to Button control appear in events dropdown list, selecting one will auto generate a procedure (Buttons_Click, Buttons_MouseMove, Buttons_KeyDown etc...) that will used by all buttons in Buttons array.
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
Absolute_Zero
How to share one procedure for all control in an array?
I know i can do with
Code:
For Each b In Buttons
AddHandler b.Click, AddressOf Buttons_Click
Next
Is it possible in code editor if i select Buttons from controls dropdown list, all events related to Button control appear in events dropdown list, selecting one will auto generate a procedure (Buttons_Click, Buttons_MouseMove, Buttons_KeyDown etc...) that will used by all buttons in Buttons array.
If you want to create a handler for the same event for multiple controls then simply select those multiple controls and then use the Properties window to create or select an event handler. This functionality has been available for over a decade and possibly back to the original VS.NET. The fact that it exists is one of the primary reasons that you don't need control arrays in VB.NET in the first place.
If you wanted this control array class to do it for you then you'd have to add a corresponding event to the array class and then use AddHandler as a control was added to the array and RemoveHandler as one was removed.
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
jmcilhinney
If you wanted this control array class to do it for you then you'd have to add a corresponding event to the array class and then use AddHandler as a control was added to the array and RemoveHandler as one was removed.
I do it like this, first added declaration for events i want
Code:
Public Event Click As EventHandler
Private Sub Click_internal(sender As Object, e As EventArgs)
RaiseEvent Click(sender, e)
End Sub
Public Event MouseMove As MouseEventHandler
Private Sub MouseMove_internal(sender As Object, e As MouseEventArgs)
RaiseEvent MouseMove(sender, e)
End Sub
Public Event KeyDown As KeyEventHandler
Private Sub KeyDown_internal(sender As Object, e As KeyEventArgs)
RaiseEvent KeyDown(sender, e)
End Sub
second added two methods to add/remove handlers
Code:
Private Sub AddEventHandelers(control As TControl)
AddHandler control.Click, AddressOf Click_internal
AddHandler control.MouseMove, AddressOf MouseMove_internal
AddHandler control.KeyDown, AddressOf KeyDown_internal
End Sub
Private Sub RemoveEventHandelers(control As TControl)
RemoveHandler control.Click, AddressOf Click_internal
RemoveHandler control.MouseMove, AddressOf MouseMove_internal
RemoveHandler control.KeyDown, AddressOf KeyDown_internal
End Sub
third call AddEventHandelers & RemoveEventHandelers from Add and SetIndex methods
Code:
Public Overridable Sub Add(ByVal item As TControl) Implements ICollection(Of TControl).Add
Me.items.Add(item)
AddEventHandelers(item)
End Sub
Public Overridable Sub SetIndex(ByVal control As TControl, ByVal index As Integer?)
If Not index.Equals(Me.GetIndex(control)) Then
'The control is either being moved to a different index or removed altogether, so remove it from its current index.
RemoveEventHandelers(control)
Me.Remove(control)
End If
If index.HasValue Then
'Insert the control at its new index, or to the end of the list if the index is invalid.
Me.Insert(Math.Min(index.Value, Me.Count), control)
AddEventHandelers(control)
End If
End Sub
It works well, but i wonder is this the correct way to do it?
You are so professional and your advise is appreciated :)
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
Absolute_Zero
I do it like this, first added declaration for events i want
Code:
Public Event Click As EventHandler
Private Sub Click_internal(sender As Object, e As EventArgs)
RaiseEvent Click(sender, e)
End Sub
Public Event MouseMove As MouseEventHandler
Private Sub MouseMove_internal(sender As Object, e As MouseEventArgs)
RaiseEvent MouseMove(sender, e)
End Sub
Public Event KeyDown As KeyEventHandler
Private Sub KeyDown_internal(sender As Object, e As KeyEventArgs)
RaiseEvent KeyDown(sender, e)
End Sub
second added two methods to add/remove handlers
Code:
Private Sub AddEventHandelers(control As TControl)
AddHandler control.Click, AddressOf Click_internal
AddHandler control.MouseMove, AddressOf MouseMove_internal
AddHandler control.KeyDown, AddressOf KeyDown_internal
End Sub
Private Sub RemoveEventHandelers(control As TControl)
RemoveHandler control.Click, AddressOf Click_internal
RemoveHandler control.MouseMove, AddressOf MouseMove_internal
RemoveHandler control.KeyDown, AddressOf KeyDown_internal
End Sub
third call
AddEventHandelers &
RemoveEventHandelers from Add and SetIndex methods
Code:
Public Overridable Sub Add(ByVal item As TControl) Implements ICollection(Of TControl).Add
Me.items.Add(item)
AddEventHandelers(item)
End Sub
Public Overridable Sub SetIndex(ByVal control As TControl, ByVal index As Integer?)
If Not index.Equals(Me.GetIndex(control)) Then
'The control is either being moved to a different index or removed altogether, so remove it from its current index.
RemoveEventHandelers(control)
Me.Remove(control)
End If
If index.HasValue Then
'Insert the control at its new index, or to the end of the list if the index is invalid.
Me.Insert(Math.Min(index.Value, Me.Count), control)
AddEventHandelers(control)
End If
End Sub
It works well, but i wonder is this the correct way to do it?
You are so professional and your advise is appreciated :)
That's basically it but there are a couple of things to note there.
1. There are more locations than you have shown that you need to use AddHandler and RemoveHandler. Check out the RadioButtonControlArray class in the provided solution to see all those locations.
2. It might work for you to simply pass through the 'sender' and 'e' arguments from one event handler to another but you're actually breaking the usual convention by doing so. The 'sender' should be the object that raised the event so you should always pass Me to RaiseEvent. That would mean creating a new type for 'e' that had a property for the control that raised the original event. That's going to be more trouble but is more correct in that it follows the standard conventions for events.
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
jmcilhinney
2. It might work for you to simply pass through the 'sender' and 'e' arguments from one event handler to another but you're actually breaking the usual convention by doing so. The 'sender' should be the object that raised the event so you should always pass Me to RaiseEvent. That would mean creating a new type for 'e' that had a property for the control that raised the original event. That's going to be more trouble but is more correct in that it follows the standard conventions for events.
Have to do just to follow the standard conventions for events or there is performance issue?
Re: Control Arrays in VB.NET
Performance would not be an issue.
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
jmcilhinney
Performance would not be an issue.
Then let the standard conventions go to hell for now. :D
Re: Control Arrays in VB.NET
What is the meaning of question mark used in GetIndex and SetIndex methods?
Code:
Public Function GetIndex(ByVal control As TControl) As Integer?
Return If(Me.Contains(control), Me.IndexOf(control), DirectCast(Nothing, Integer?))
End Function
Re: Control Arrays in VB.NET
Quote:
Originally Posted by
Absolute_Zero
What is the meaning of question mark used in
GetIndex and
SetIndex methods?
Code:
Public Function GetIndex(ByVal control As TControl) As Integer?
Return If(Me.Contains(control), Me.IndexOf(control), DirectCast(Nothing, Integer?))
End Function
Appending a question mark to a value type denotes that it is nullable. 'Integer?' is shorthand for 'Nullable(Of Integer)'.
Re: Control Arrays in VB.NET