Multiple Adressof's to 1 sub - vb.net

I'm trying to make a dynamic input form. But to do this I need to be able to pass multiple adressof's to 1 sub. Is this possible?
Here is my code:
Public Function AddNewcombobox() 'As System.Windows.Forms.ComboBox
Dim cmbSoort As New System.Windows.Forms.ComboBox()
Me.Controls.Add(cmbSoort)
cmbSoort.Top = cLeft
cmbSoort.Left = 62
cmbSoort.Items.Add("Maak een keuze")
cmbSoort.Items.Add("Behuizingen")
cmbSoort.Items.Add("Moederborden")
cmbSoort.Items.Add("Processoren")
cmbSoort.Items.Add("Grafische kaarten")
cmbSoort.Items.Add("Geheugen")
cmbSoort.Items.Add("DVD/Blu-ray")
cmbSoort.Items.Add("Harddisks")
cmbSoort.Items.Add("SSD")
cmbSoort.Items.Add("Voedingen")
cmbSoort.Items.Add("Invoerapparaten")
cmbSoort.Items.Add("Monitoren")
cmbSoort.SelectedIndex = 0
cmbSoort.Name = "Soort" & mintI
AddHandler cmbSoort.SelectedIndexChanged, AddressOf IndexVeranderd
Return cmbSoort
End Function
Public Sub AddNewName()
Dim cmbName As New System.Windows.Forms.ComboBox()
Me.Controls.Add(cmbName)
cmbName.Top = cLeft
cmbName.Left = 292
cmbName.Items.Add("Maak een keuze")
cmbName.Name = "Naam" & mintI
cmbName.Enabled = False
CmbPrijs.Enabled = False
txtStuks.Enabled = False
'AddHandler AddNewcombobox.SelectedIndexChanged, AddressOf IndexVeranderd
cLeft = cLeft + 40
mintI += 1
End Sub
Private Sub cmbNaam_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
'CmbPrijs.SelectedIndex = CmbNaam.SelectedIndex
End Sub
Private Sub IndexVeranderd(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim ComboVeranderd = DirectCast(sender, ComboBox)
Dim combonaam = DirectCast(sender, ComboBox)
MsgBox(combonaam.ToString)
If ComboVeranderd.SelectedIndex = 0 Then
'ComboNaam.Enabled = False
txtStuks.Enabled = False
End If
For i = 0 To EasybyteDataSet.Stock.Rows.Count - 1
If ComboVeranderd.SelectedItem = EasybyteDataSet.Stock.Rows(i)("Soort") Then
'ComboNaam.Enabled = True
txtStuks.Enabled = True
'ComboNaam.Items.Add(EasybyteDataSet.Stock.Rows(i)("Product naam"))
CmbPrijs.Items.Add(EasybyteDataSet.Stock.Rows(i)("Prijs"))
End If
Next
End Sub
When cmbSoort's index changes, it should send both cmbSoort and cmbName to the sub IndexVeranderd.
The trick is, cmbSoort and cmbName are generated by the functions when the user presses a button.
Is this possible?

To make a Sub handle multi combobox ..
In your case :
Public Sub AddNewcombobox()
Dim cmbSoort as New ComboBox
Dim cmbName as New ComboBox
'.......... fill cmbSoort properties
'.......... fill cmbName properties
Controls.Add(cmbSoort)
AddHandler cmbSoort.SelectedIndexChanged, AddressOf IndexVeranderd
Controls.Add(cmbname)
AddHandler cmbName.SelectedIndexChanged, AddressOf IndexVeranderd
End Sub
And the Sub handler
Private Sub IndexVeranderd(ByVal sender As System.Object, ByVal e As System.EventArgs)
Select Case oCB
Case cmbSoort
' ................. code here
Case cmbName
' ................. code here
End Select
End Sub

The names seem to have an number added to them if they are the same so that Soort1 is tied to Naam1 then just separate out the number and access the control directly. This way you only need the handler for cmbSoort.
Dim ComboVeranderd = DirectCast(sender, ComboBox)
Dim combonaam = Me.Controls("Naam"+ComboVeranderd.Name.Substring(ComboVeranderd.Name.Length-1))
I assumed the number is only 1 digit, if not you might have to adjust for more.
If the names don't include a number this would be an efficient way to pair them up

Related

Add Event to Picture Box dynamically vb.net

I'm trying to add pictureboxes dynamically in vb.net.
If i play with the vars, changing the "i" value i can add the images and the event to the last picturebox created (i can only click the last images).
But when i use the code below, it says the there's something out of boundaries ( Index outside the bounds of the matrix ).
What am i doing wrong? Tks
Imports System.IO
Public Class FormMain
Dim Path1 As String = Path.GetDirectoryName(Application.ExecutablePath) & "\Source\Images\1.png"
Dim Path2 As String = Path.GetDirectoryName(Application.ExecutablePath) & "\Source\Images\2.png"
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateImages()
End Sub
Dim i As Integer
Dim Logo(i) As PictureBox
Sub CreateImages()
Dim i As Integer = TextBoxNumberImages.Text
For i = 0 To i - 1
Logo(i) = New PictureBox
Logo(i).Name = "Image" + Str(i)
Panel1.Controls.Add(Logo(i))
Logo(i).Image = Image.FromFile(Path1)
Logo(i).SizeMode = PictureBoxSizeMode.StretchImage
AddHandler Logo(i).Click, AddressOf _Click
Next
End Sub
'------ADD EVENT----
Dim IsImageSelected(i) As Boolean
Private Sub _Click(ByVal sender As Object, ByVal e As EventArgs)
If IsImageSelected(i) = False Then
Logo(i).Image = Image.FromFile(Path2)
IsImageSelected(i) = True
Else
Logo(i).Image = Image.FromFile(Path1)
IsImageSelected(i) = False
End If
End Sub
----EDIT----
I just changed the var declaration to inside of the function:
Sub CreateImages()
Dim i As Integer = TextBoxNumberImages.Text
Dim Logo(i) As PictureBox
For i = 0 To i - 1
Logo(i) = New PictureBox
Logo(i).Name = "Image" + Str(i)
Panel1.Controls.Add(Logo(i))
Logo(i).Image = Image.FromFile(Path1)
Logo(i).SizeMode = PictureBoxSizeMode.StretchImage
AddHandler Logo(i).Click, AddressOf _Click
Next
End Sub
Now it creates the images the way i want, but i can't access the pictureboxes in the event. Help?
Don't use an array, use a List(Of PictureBox) instead. You could also store the selected state in the Tag() of the PictureBox. To get a reference to the PictureBox that was clicked, cast the Sender parameter. All together it would look something like this:
Private Logo As New List(Of PictureBox)
Sub CreateImages()
Dim i As Integer = TextBoxNumberImages.Text
For i = 0 To i - 1
Dim pb As New PictureBox
pb = New PictureBox
pb.Tag = False ' <-- initial not selected state
pb.Name = "Image" + Str(i)
Panel1.Controls.Add(pb)
pb.Image = Image.FromFile(Path1)
pb.SizeMode = PictureBoxSizeMode.StretchImage
AddHandler pb.Click, AddressOf _Click
Logo.Add(pb)
Next
End Sub
Private Sub _Click(ByVal sender As Object, ByVal e As EventArgs)
Dim pb As PictureBox = DirectCast(sender, PictureBox)
Dim selected As Boolean = DirectCast(pb.Tag, Boolean)
If selected = False Then
pb.Image = Image.FromFile(Path2)
Else
pb.Image = Image.FromFile(Path1)
End If
pb.Tag = Not selected ' toggle selected state
End Sub

VB.NET: Code runs without error, but does not add item to listbox

I've got this embedded CMD on my form which I created using another person's code and everything works right. Inside one of the Private Subs (that seems to run every time a new line is written in the CMD output textbox), I've got a line which adds a item to a listbox (listboxs name is txtPlayerList) on another form labelled Status.
When this area of the code runs, it doesn't throw up any errors (and if I put a msgbox() on the same line, the msgbox() works). If I put the add to listbox line on form_load it works perfectly?
Here is my code, I've included everything from that form just in case (it is in the third sub from the top with the asterisks and comment "Get players and maybe other stuff as well"
Imports System.IO
Public Class Console
Public WithEvents MyProcess As Process
Private Delegate Sub AppendOutputTextDelegate(ByVal text As String)
Public LastLine As String
Public LastLineFormatted As String
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim LocalpathParent As String = Application.StartupPath() + "\MCserver"
'loads embed cmd
Me.AcceptButton = ExecuteButton
MyProcess = New Process
With MyProcess.StartInfo
.FileName = "CMD.EXE"
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardInput = True
.RedirectStandardOutput = True
.RedirectStandardError = True
.WorkingDirectory = LocalpathParent
End With
MyProcess.Start()
MyProcess.BeginErrorReadLine()
MyProcess.BeginOutputReadLine()
AppendOutputText("Process Started at: " & MyProcess.StartTime.ToString)
'Resize with parent mdi container. Needs to be anchored & StartPosition = manual in properties
Me.WindowState = FormWindowState.Maximized
End Sub
Private Sub MyProcess_ErrorDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.ErrorDataReceived
AppendOutputText(vbCrLf & "Error: " & e.Data)
End Sub
Private Sub MyProcess_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.OutputDataReceived
AppendOutputText(vbCrLf & e.Data)
'*****************************************
'Get Players and maybe other stuff as well
'*****************************************
LastLine = Me.OutputTextBox.Lines.Last
If Status.ServerStarted = True Then
If Me.LastLine.Contains(" joined the game") Then
LastLineFormatted = Me.LastLine
LastLineFormatted = LastLineFormatted.Replace(" joined the game", "")
'***THIS LINE BELOW WORKS IN FORM LOAD, BUT NOT HERE FOR SOME REASON???***
Status.txtPlayersList.Items.Add(LastLineFormatted)
MsgBox("add lastlineformatted")
ElseIf Me.LastLine.Contains(" left the game") Then
LastLineFormatted = Me.LastLine
LastLineFormatted = LastLineFormatted.Replace(" left the game", "")
Status.txtPlayersList.Items.Remove(LastLineFormatted)
End If
End If
End Sub
Private Sub ExecuteButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExecuteButton.Click
MyProcess.StandardInput.WriteLine(InputTextBox.Text)
MyProcess.StandardInput.Flush()
InputTextBox.Text = ""
End Sub
Private Sub AppendOutputText(ByVal text As String)
If OutputTextBox.InvokeRequired Then
Dim myDelegate As New AppendOutputTextDelegate(AddressOf AppendOutputText)
Try
Me.Invoke(myDelegate, text)
Catch
End Try
Else
Try
OutputTextBox.AppendText(text)
Catch
End Try
End If
End Sub
End Class
EDIT: Below is the code I have for form1 per request
'code
Public Class Form1
Public Localpath As String
Public Downloadpath As String
Public LocalpathParent As String
'when this form is closing, send stop to console to make sure it has closed and saved
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Console.MyProcess.StandardInput.WriteLine("stop") 'send an EXIT command to the Command Prompt
Application.Exit()
End
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'load stuff in background n stuff
Me.Show()
Me.Focus()
Configure.Show()
Configure.Hide()
Status.Show()
Status.Hide()
Console.Show()
Console.Hide()
End Sub
'CONSOLE.form
Private Sub ConsoleToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConsoleToolStripMenuItem1.Click
'Hide all forms
Status.Hide()
Configure.Hide()
'Shown Form that you want to load
Console.Opacity = 100
Console.Show()
WindowState = FormWindowState.Normal
Console.MdiParent = Me
Console.OutputTextBox.SelectionStart = Console.OutputTextBox.Text.Length
Console.OutputTextBox.ScrollToCaret()
End Sub
'STATUS.form
Private Sub StatusToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles StatusToolStripMenuItem1.Click
'hide all forms
Console.Hide()
Configure.Hide()
'Show Form that you want to load
Status.Opacity = 100
Status.Show()
WindowState = FormWindowState.Maximized
Configure.Size = Me.Size
Status.MdiParent = Me
End Sub
'CONFIGURE.form
Private Sub ConfigurationToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConfigurationToolStripMenuItem1.Click
'hide all forms
Status.Hide()
Console.Hide()
'Show form that you want to load
Configure.Opacity = 100
Configure.Show()
WindowState = FormWindowState.Maximized
Configure.Size = Me.Size
Configure.MdiParent = Me
End Sub
End Class
'code
It seems that your original code to create an embeded CMD window was interfering with the code to update the listbox in another mdi child. After finding another way to embed a cmd console, and some fiddling around, It seems to be working Ok. I haven't been able to test pure server output yet though.
THere have been quite a few changes to the code that are too big to post here, but the Alternative embedded CMD is this.
Place this in general form declarations
'command prompt variables
Private strResults As String
Private intStop As Integer
Private swWriter As System.IO.StreamWriter
Friend thrdCMD As System.Threading.Thread
Private Delegate Sub cmdUpdate()
Private uFin As New cmdUpdate(AddressOf UpdateText)
Public WithEvents procCMDWin As New Process
This in your form_load Sub
thrdCMD = New System.Threading.Thread(AddressOf Prompt)
thrdCMD.IsBackground = True
thrdCMD.Start()
and these declarations within your form Class
Private Sub Prompt()
AddHandler procCMDWin.OutputDataReceived, AddressOf CMDOutput
AddHandler procCMDWin.ErrorDataReceived, AddressOf CMDOutput
procCMDWin.StartInfo.RedirectStandardOutput = True
procCMDWin.StartInfo.RedirectStandardInput = True
procCMDWin.StartInfo.CreateNoWindow = True
procCMDWin.StartInfo.UseShellExecute = False
procCMDWin.StartInfo.FileName = "cmd.exe"
procCMDWin.StartInfo.WorkingDirectory = LocalpathParent
procCMDWin.Start()
procCMDWin.BeginOutputReadLine()
swWriter = procCMDWin.StandardInput
Do Until (procCMDWin.HasExited)
Loop
procCMDWin.Dispose()
End Sub
Private Sub UpdateText()
OutputTextBox.Text += strResults
OutputTextBox.SelectionStart = OutputTextBox.TextLength - 1
InputTextBox.Focus()
intStop = OutputTextBox.SelectionStart
OutputTextBox.ScrollToCaret()
If OutputTextBox.Lines.Count > 2 Then
LastLine = OutputTextBox.Lines.ElementAt(OutputTextBox.Lines.Count - 2)
If Status.ServerStarted = True Then
'get element 1 of split
If LastLine.Contains(" joined the game") Then
LastLineFormatted = ExtractName(LastLine, " joined the game")
'If listlineformatted.contains(Players.allitems) then do
Status.txtPlayersList.Items.Add(LastLineFormatted)
Status.Show()
ElseIf Me.LastLine.Contains(" left the game") Then
LastLineFormatted = ExtractName(LastLine, " left the game")
'If listlineformatted.contains(Players.allitems) then do
Status.txtPlayersList.Items.Remove(LastLineFormatted)
MsgBox("remove lastlineformatted")
End If
End If
End If
End Sub
Private Function ExtractName(unformattedString As String, stringToRemove As String) As String
Dim temp As String = Split(unformattedString, "Server]")(1).ToString
ExtractName = temp.Replace(stringToRemove, "")
End Function
Private Sub CMDOutput(ByVal Sender As Object, ByVal OutputLine As DataReceivedEventArgs)
strResults = OutputLine.Data & Environment.NewLine
Invoke(uFin)
End Sub

access to new dynamically controls in vb.net

First of all excuse me for my poor grammar and vocabulary :)
please see this source and run it:
Public Class Form1
Public pointX As Integer
Public pointY As Integer = 32
Public dynamicText As TextBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
pointX = 330
For i = 1 To 4
dynamicText = New Windows.Forms.TextBox
dynamicText.Name = "T" + Trim(Str(i))
dynamicText.Text = ""
dynamicText.Location = New Point(pointX, pointY)
dynamicText.Size = New Size(100, 20)
Me.Controls.Add(dynamicText)
pointX = pointX - 106
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
pointX = 330
pointY = pointY + 26
For i = 1 To 4
dynamicText = New Windows.Forms.TextBox
dynamicText.Name = "T" + Trim(Str(i))
dynamicText.Text = ""
dynamicText.Location = New Point(pointX, pointY)
dynamicText.Size = New Size(100, 20)
Me.Controls.Add(dynamicText)
pointX = pointX - 106
AddHandler dynamicText.Click, AddressOf printHello1
Next
End Sub
Private Sub printHello1(ByVal sender As System.Object, ByVal e As System.EventArgs)
MsgBox(dynamicText.Name)
If dynamicText.Name = "T1" Then MsgBox("Oh! this is T1")
End Sub
End Class
why If never is not true?!
why MsgBox(dynamicText.Name) always return T4?!
i want all controlls to be access by name or array of names.
please help me thank you. :)
The global variable dynamicText takes the value of the last TextBox added in the loop inside the Button1_Click event. This happens to be the control named T4. You don't really need a global variable in this case. You can cast the sender parameter to a TextBox instance because the sender parameter is the control that has raised the event.
Private Sub printHello1(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim txt = CType(sender, "TextBox")
if txt IsNot Nothing then
MsgBox(txt.Name)
If txt.Name = "T1" Then MsgBox("Oh! this is T1")
End If
End Sub
You also don't need to recreate the controls again in the button click event. The action executed in the form load event is enough (You could add the AddHandler there). Global variables are dangerous, avoid them when possible.
See if this is acceptable. Place a panel at the bottom of your form, set Dock to Bottom, add a single button to the panel and a TextBox. Place a FlowLayoutPanel onto the form, Dock = Fill, AutoScroll = True.
The code below creates the amount of TextBox controls as inputted into TextBox. Each newly created TextBox a click event is added with simple logic.
Form code
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim count As Integer = 0
If Integer.TryParse(TextBox1.Text, count) Then
Dim demo = New TextBoxCreate(FlowLayoutPanel1, "Demos", count)
demo.CreateTextBoxes()
End If
End Sub
End Class
Class code (add a new class to the project, name it TextBoxCreate.vb)
Public Class TextBoxCreate
Public Property TextBoxes As TextBox()
Public Property TextBoxBaseName As String
Public Property TextBoxCount As Integer
Public Property ParentControl As Control
Public Sub New(
ByVal ParentControl As Control,
ByVal BaseName As String,
ByVal Count As Integer)
Me.ParentControl = ParentControl
Me.TextBoxBaseName = BaseName
Me.TextBoxCount = Count
End Sub
Public Sub CreateTextBoxes()
Dim Base As Integer = 10
TextBoxes = Enumerable.Range(0, TextBoxCount).Select(
Function(Indexer)
Dim b As New TextBox With
{
.Name = String.Concat(TextBoxBaseName, Indexer + 1),
.Text = (Indexer + 1).ToString,
.Width = 150,
.Location = New Point(25, Base),
.Parent = Me.ParentControl,
.Visible = True
}
AddHandler b.Click, Sub(sender As Object, e As EventArgs)
Dim tb As TextBox = CType(sender, TextBox)
If tb.Name = TextBoxBaseName & "1" Then
tb.Text = "Got it"
Else
MessageBox.Show(tb.Name)
End If
End Sub
Me.ParentControl.Controls.Add(b)
Base += 30
Return b
End Function).ToArray
End Sub
End Class

Adding Handler using 'AddressOf'

When trying to add an event handler to a dynamically created button I get an an error:
Dim Itm As New Button
Itm.Name = "Itm" & i
Itm.Height = 62
Itm.Width = 159
Itm.Text = Temp(i, 0).ToUpper
Itm.Left = (F * 165)
Itm.Visible = True
Itm.BackColor = Colour
Itm.ForeColor = Color.Black
AddHandler Itm.Click, AddressOf Me.Itm_Click
Me.pnlItemButton1.Controls.Add(Itm)
i = i + 1
If i > Temp.Length - 1 Then
GoTo Exit1
End If
I get an error on the AddressOf line:
"Item_Click is not a member of windowsapplication1.main"
I feel this is because I have set the name to be "Itm" & i but using AddressOf Me.Itm(i)_Click also presents an error. Any thoughts?
You have to declare the event handler Itm_Click and it must be accessible.
For example (presuming that your array Temp exists somewhere):
Public Class Demo
Protected Sub Itm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
End Sub
Public Sub DemoMethod()
For i As Int32 = 1 To Temp.Length - 1
Dim Itm As New System.Windows.Forms.Button()
Itm.Name = "Itm" & i
Itm.Height = 62
Itm.Width = 159
Itm.Text = Temp(i, 0).ToUpper
Itm.Left = (F * 165)
Itm.Visible = True
Itm.BackColor = Colour.White
Itm.ForeColor = Color.Black
AddHandler Itm.Click, AddressOf Me.Itm_Click
Me.pnlItemButton1.Controls.Add(Itm)
Next
End Sub
End Class
You can use this event handler for all dynamically created buttons. You get the button that was clicked from the sender argument:
Protected Sub Itm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim actualButton = Ctype(sender, System.Windows.Forms.Button)
Dim name = actualButton.Name
End Sub

How can I reduce this code to a single procedure

I am relatively new to the whole .NET thing, coming from a VB classic background.
On my form I have a tabcontrol, with 4 tabs. Most of the code is handled using a shared handler, but for the others I have to write a handler for each.
How can I optimize these routines into a single procedure?
Private Sub cboCalc0_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboCalc0.SelectedIndexChanged
'Page 0
If (Not (IsNothing(trvSignals0.SelectedNode)) And txtSignalName0.Enabled = True) AndAlso trvSignals0.SelectedNode.Level = 3 Then
tempChannelProp(0, trvSignals0.SelectedNode.Tag).CalcVariant = cboCalc0.SelectedIndex
End If
End Sub
Private Sub cboCalc1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboCalc1.SelectedIndexChanged
'Page 1
If (Not (IsNothing(trvSignals1.SelectedNode)) And txtSignalName0.Enabled = True) AndAlso trvSignals1.SelectedNode.Level = 3 Then
tempChannelProp(1, trvSignals1.SelectedNode.Tag).CalcVariant = cboCalc1.SelectedIndex
End If
End Sub
Private Sub cboCalc2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboCalc2.SelectedIndexChanged
'Page 2
If (Not (IsNothing(trvSignals2.SelectedNode)) And txtSignalName2.Enabled = True) AndAlso trvSignals2.SelectedNode.Level = 3 Then
tempChannelProp(2, trvSignals2.SelectedNode.Tag).CalcVariant = cboCalc2.SelectedIndex
End If
End Sub
Private Sub cboCalc3_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboCalc3.SelectedIndexChanged
'Page 3
If (Not (IsNothing(trvSignals3.SelectedNode)) And txtSignalName3.Enabled = True) AndAlso trvSignals3.SelectedNode.Level = 3 Then
tempChannelProp(3, trvSignals3.SelectedNode.Tag).CalcVariant = cboCalc3.SelectedIndex
End If
End Sub
I have handled the other bits as follows, and it works great, but I just cannot figure out how to do it with code like that above.
Private Sub trvSignals_AfterCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles trvSignals0.AfterCheck, trvSignals1.AfterCheck, trvSignals2.AfterCheck, trvSignals3.AfterCheck
'Handles Page 0,1,2,3
sender.SelectedNode = e.Node
If e.Node.Level = 3 Then
tempChannelProp(sender.tag, e.Node.Tag).Active = e.Node.Checked
End If
End Sub
I use the tag property of the control of each page to hold either 0,1,2 or 3 as appropriate.
Thanks
Graham
Create control arrays that you can reference by index, and put the index in each controls' Tag.
Class MyForm
Private ReadOnly cboCalcArray As ComboBox()
Private ReadOnly trvSignalsArray As TreeView()
Private ReadOnly txtSignalNameArray As TextBox()
Public Sub New()
InitializeComponent()
cboCalcArray = new ComboBox() {cboCalc0, cboCalc1, cboCalc2, cboCalc3}
trvSignalsArray = new TreeView() {trvSignals0, trvSignals1, trvSignals2, trvSignals3}
txtSignalNameArray = new TextBox() {txtSignalName0, txtSignalName1, txtSignalName2, txtSignalName3}
End Sub
Private Sub cboCalcX_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles cboCalc0.SelectedIndexChanged,
cboCalc1.SelectedIndexChanged,
cboCalc2.SelectedIndexChanged,
cboCalc3.SelectedIndexChanged
Dim index As Integer = sender.Tag
If (Not (IsNothing(trvSignalsArray(index).SelectedNode)) And txtSignalNameArray(index).Enabled = True) AndAlso trvSignals2.SelectedNode.Level = 3 Then
tempChannelProp(index, trvSignalsArray(index).SelectedNode.Tag).CalcVariant = cboCalcArray(index).SelectedIndex
End If
End Sub
End Class
You can leverage a couple of features:
1) The VB Handles statement can hook multiple control events to the same method.
2) You can get the combobox from the sender, then extract the index.
3) From the index, you can find the other associated controls.
Private Sub cboCalc_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboCalc0.SelectedIndexChanged, cboCalc1.SelectedIndexChanged, cboCalc2.SelectedIndexChanged, cboCalc3.SelectedIndexChanged
Dim oCombo As ComboBox
oCombo = DirectCast(sender, ComboBox)
Dim wIndex As Integer
Dim oTree As TreeView
Dim oTextBox As TextBox
wIndex = CInt(oCombo.Name.Substring(oCombo.Name.Length - 1))
oTree = DirectCast(Me.Controls.Find("trvSignals" & wIndex.ToString, True)(0), TreeView)
oTextBox = DirectCast(Me.Controls.Find("txtSignalName" & wIndex.ToString, True)(0), TextBox)
If oTree.SelectedNode IsNot Nothing AndAlso oTextBox.Enabled AndAlso oTree.SelectedNode.Level = 3 Then
tempChannelProp(wIndex, oTree.SelectedNode.Tag).CalcVariant = oCombo.SelectedIndex
End If
End Sub
There is likely a more elegant solution to your problem somewhere. I find that, if I am defining the same controls and methods for multiplpe tabs on a tab control, it might be time to examine my design . . . Not always, though. :-)
This might be a little less clumsy, although using Select Case to choose between otherwise identical configurations of UI elements gives me the heebie-jeebies (It DOES get all your code into one handler, however):
Private Sub PerformCalcs(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles _
cboCalc0.SelectedIndexChanged,
cboCalc1.SelectedIndexChanged,
cboCalc2.SelectedIndexChanged,
cboCalc3.SelectedIndexChanged
Dim cboCalc As ComboBox = DirectCast(sender, ComboBox)
' The Parent of the combo box is the TabPage, and the Parent of the TabPage is the TabControl:
Dim t As TabControl = cboCalc.Parent.Parent
Dim SelectedNode As TreeNode
Dim TxtSignalName As TextBox
' The TabControl knows the index value of the currently selected tab:
Select Case t.SelectedIndex
Case 0 'Page 0
SelectedNode = trvSignals0.SelectedNode
TxtSignalName = txtSignalName0
Case 1 ' Page 1
SelectedNode = trvSignals1.SelectedNode
TxtSignalName = txtSignalName1
Case 2 ' Page 2
SelectedNode = trvSignals2.SelectedNode
TxtSignalName = txtSignalName2
Case 3 ' Page 3
SelectedNode = trvSignals3.SelectedNode
TxtSignalName = txtSignalName3
Case Else ' Ooops! Something horrible happened!
Throw New System.Exception("You have passed an invalid Control as a parameter")
End Select
If (Not (IsNothing(SelectedNode)) And TxtSignalName.Enabled = True) AndAlso trvSignals3.SelectedNode.Level = 3 Then
tempChannelProp(3, SelectedNode.Tag).CalcVariant = cboCalc.SelectedIndex
End If
End Sub