I am trying to create an invoice from an order in XAF.
I follow the Add an Action that Displays a Pop-up Window from the devexpress web site
Using a View controller and an Action
I have an order class and order_Details class as a Collection of orders with an Invoice class and Invoice_Data class as a collection of Invoice
Private Sub Create_Invoice_Action_CustomizePopupWindowParams(sender As Object, e As CustomizePopupWindowParamsEventArgs) Handles Create_Invoice_Action.CustomizePopupWindowParams
Dim objectSpace As IObjectSpace = Application.CreateObjectSpace()
e.View = Application.CreateListView(Application.FindListViewId(GetType(elmts.OrderDetail)), _
New CollectionSource(objectSpace, GetType(elmts.OrderDetail)), True)
End Sub
Private Sub ShowNotesAction_Execute(ByVal sender As Object, _
ByVal e As PopupWindowShowActionExecuteEventArgs) Handles Create_Invoice_Action.Execute
Dim _invoiceDetails As elmts.InvoiceData = CType(View.CurrentObject, elmts.InvoiceData)
View.ObjectSpace.SetModified(_invoiceDetails)
For Each _nv_Det As elmts.OrderDetail In e.PopupWindow.View.SelectedObjects
If (Not String.IsNullOrEmpty(_invoiceDetails.ProductName)) Then
_invoiceDetails.ProductName += Environment.NewLine
End If
_invoiceDetails.ProductName += _nv_Det.Division
Next _nv_Det
Dim item As ViewItem = (CType(View, DetailView)).FindItem("ProductName")
CType(item, PropertyEditor).ReadValue()
'Save changes to the database if the current Detail View is displayed in the View mode
If TypeOf View Is DetailView AndAlso (CType(View, DetailView)).ViewEditMode = _
ViewEditMode.View Then
View.ObjectSpace.CommitChanges()
End If
End Sub
Private Sub PopupNotesController_Activated(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Activated
Create_Invoice_Action.Active.SetItemValue("ObjectType", DirectCast(View, DetailView).ObjectTypeInfo.Type Is GetType(elmts.Order))
End Sub
Another words I like to from the Order detailView with an OrderDetailsCollection view add an action that will
Create the new Invoice and Commit the changes to the database
grab the Oder.OrderDetail Collection currentview items and pass them to the Newly created Invoice.InvoiceData Collection
Set the Order as Invoiced
Thanks for any help provided.
I hope this helps:
Private Sub Create_Invoice_Action_CustomizePopupWindowParams(sender As Object, e As CustomizePopupWindowParamsEventArgs) Handles Create_Invoice_Action.CustomizePopupWindowParams
Dim objectSpace As IObjectSpace = Application.CreateObjectSpace()
e.View = Application.CreateListView(Application.FindListViewId(GetType(elmts.OrderDetail)), _
New CollectionSource(objectSpace, GetType(elmts.OrderDetail)), True)
End Sub
Private Sub ShowNotesAction_Execute(ByVal sender As Object, _ByVal e As PopupWindowShowActionExecuteEventArgs) Handles Create_Invoice_Action.Execute
'Dim _invoiceDetails As elmts.InvoiceData = CType(View.CurrentObject, elmts.InvoiceData) << Wrong, since View.CurrentObject is elmts.Order
Dim _order As elmts.Order = CType(View.CurrentObject, elmts.Order);
Dim _invoiceDetails As elmts.InvoiceData = _order.CreateInvoice(); 'creates a new InvoiceData
View.ObjectSpace.SetModified(_invoiceDetails)
For Each _nv_Det As elmts.OrderDetail In e.PopupWindow.View.SelectedObjects
If (Not String.IsNullOrEmpty(_invoiceDetails.ProductName)) Then
_invoiceDetails.ProductName += Environment.NewLine
End If
_invoiceDetails.ProductName += _nv_Det.Division
Next _nv_Det
Dim item As ViewItem = (CType(View, DetailView)).FindItem("ProductName")
CType(item, PropertyEditor).ReadValue()
'Save changes to the database if the current Detail View is displayed in the View mode
If TypeOf View Is DetailView AndAlso (CType(View, DetailView)).ViewEditMode = _
ViewEditMode.View Then
View.ObjectSpace.CommitChanges()
End If
End Sub
Private Sub PopupNotesController_Activated(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Activated
Create_Invoice_Action.Active.SetItemValue("ObjectType", DirectCast(View, DetailView).ObjectTypeInfo.Type Is GetType(elmts.Order))
End Sub
Related
I have two forms: frmMain and frmProduct
In the main form frmMain, I have a Datagridview1 and the buttons: tsbInsert_click, tsbAlter_click and tsbConsult_click.
When I open the main form frmMain, there is still no row in the Datagridview1 and when I click on any of the tsbAlter_click or tsbConsult_click buttons, the code displays the message "Select a product", which is correct , because there is still no product created in the register.
When I click on the tsbInsert_click button, the code opens the frmProduct to insert a record in the register and then returns to the main form frmMain, which, in the line of the Datagridview1, shows the record that was included.
The problem is that when I include a record in the register, the Datagridview1 ALWAYS returns with the state of the selected row, and the condition If DGProducts.CurrentRow Is Nothing is never true again ... so when I click on tsbAlter_click or tsbConsult_click, the "Select a product" message no longer appears and it should have since I didn't select any rows in Datagridview1.
frmMain Code:
Public Class frmMain
Private Sub tsbInsert_Click(sender As Object, e As EventArgs) Handles tsbInsert.Click
Using frm As New frmProduct("Insert", "")
frm.ShowDialog()
If frm.txtPrdCod.Text <> "" Then
DGProducts.Rows.Add(Campo(0), Campo(1), Campo(2))
End If
End Using
End Sub
Private Sub tsbAlter_Click(sender As Object, e As EventArgs) Handles tsbAlter.Click
If DGProducts.CurrentRow Is Nothing Then
MessageBox.Show("Select a product")
Exit Sub
End If
Dim codProd As String = DGProducts.CurrentRows.Cells("prdCod").Value
Using frm As New frmProduct("Alter", codProd)
frm.ShowDialog()
With DGProducts.Rows(DGProds.CurrentCell.RowIndex)
.Cells("prdCod").Value = Field(0)
.Cells("prdName").Value = Field(1)
.Cells("prdManufac").Value = Field(2)
End With
End Using
End Sub
Private Sub DGProducts_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DGProducts.CellEnter
With DGProducts.Rows(DGProducts.CurrentCell.RowIndex)
Campo(0) = .Cells("prdCod").Value
Campo(1) = .Cells("prdName").Value
Campo(2) = .Cells("prdManufac").Value
End With
End Sub
End Class
frmProduct code:
Public Class frmProduct
Private Sub frmProduct_Load(sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If _operation = "Alter" Then
txtPrdCod.Text = Campo(0)
txtPrdName.Text = Campo(1)
txtManufct.Text = Campo(2)
Else
txtPrdCod.Text = ""
txtPrdName.Text = ""
txtManufct.Text = ""
Enf If
End Sub
Dim _operation As String
Dim _codProd As String
Public Sub New(operation As String, codProd As String)
InitializeComponent()
Select Case operation
Case "Insert"
_operation = operation
Case "Alter"
_operation = operation
_codProd = codProd
Case Else
MessageBox.Show("Invalid option!")
Close()
End Select
End Sub
Private Sub tsbRecord_Click(sender As Object, e As EventArgs) Handles tsbRecord.Click
Field(0) = txtPrdCod.Text
Field(1) = txtPrdName.Text
Field(2) = txtManufct.Text
Me.Close()
End Sub
End Class
How do I make it so that when I add a product to the register, Datagridview1 DOES NOT return with the line in the SELECTED state and the message "Select a product" appears when I don't select a line from Datagridview1?
The command DGProducts.Rows.Add(Field(0), Field(1), Field(2)), automatically changes the value DGProducts.SelectedRows.Count to 1, so I set DGProducts.CurrentCell = Nothing after command DGProducts.Rows.Add in code:
Private Sub tsbInsert_Click(sender As Object, e As EventArgs) Handles tsbInsert.Click
Using frm As New frmProduct("Insert", "")
frm.ShowDialog()
If frm.txtPrdCod.Text <> "" Then
DGProducts.Rows.Add(Campo(0), Campo(1), Campo(2))
DGProducts.CurrentCell = Nothing
End If
End Using
End Sub
I created this piece of code to illustrate the idea, it uses a combobox and a textbox
Private Sub ComboBox2_DropDown(sender As Object, e As EventArgs) Handles ComboBox2.DropDown
ComboBox2.Items.Clear()
ComboBox2.Items.Add("0001 | Apple")
ComboBox2.Items.Add("0002 | Pear")
ComboBox2.Items.Add("0003 | Banana")
ComboBox2.Items.Add("0004 | Pineapple")
ComboBox2.Items.Add("0005 | Cherry")
End Sub
Private Sub ComboBox2_DropDownClosed(sender As Object, e As EventArgs) Handles ComboBox2.DropDownClosed
Dim selecteditem As String = ComboBox2.Items(ComboBox2.SelectedIndex)
ComboBox2.Text = Strings.Left(selecteditem,4)
TextBox2.Text = Strings.Left(selecteditem,4)
End Sub
When I select an item from the combobox what happens is that the combobox keeps showing the whole string while the textbox only shows the first 4 characters.
How can I overwrite the combobox text after I close the combobox?
* edit *
I tried a combo of the solutions but ran into a problem because the data was bound to a datasource so it's not possible to change the item.
This is the new code:
Private Sub ComboBox2_DropDown(sender As Object, e As EventArgs) Handles ComboBox2.DropDown
SQL.ExecQuery($"select ID, Name, RTRIM(ID + ' | ' + Name) as SingleColumn from GCCTEST.dbo.tblFruit")
ComboBox2.DataSource = SQL.DBDT
ComboBox2.DisplayMember = "SingleColumn"
End Sub
Private Sub ComboBox2_DropDownClosed(sender As Object, e As EventArgs) Handles ComboBox2.DropDownClosed
ComboBox2.DisplayMember = "ID"
ComboBox2.SelectedIndex = 0
End Sub
Now I only need to have the 0 be the index I chose...
The following should work.
If not necessary, don't populate the combobox on every drop-down, instead call the FillComboBox-method when loading the Form.
Private Sub FillComboBox()
SQL.ExecQuery($"select ID, Name, RTRIM(ID + ' | ' + Name) as SingleColumn from GCCTEST.dbo.tblFruit")
ComboBox2.DataSource = SQL.DBDT
ComboBox2.DisplayMember = "ID"
ComboBox2.ValueMember = "ID"
End Sub
Private Sub ComboBox2_DropDown(sender As Object, e As EventArgs) Handles ComboBox2.DropDown
Me.ComboBox2.DisplayMember = "SingleColumn"
End Sub
Private Sub ComboBox2_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox2.SelectionChangeCommitted
Dim selV As Object = Me.ComboBox2.SelectedValue
Me.TextBox2.Text = CStr(selV)
Me.ComboBox2.DisplayMember = "ID"
'Set the current value again, otherwise the combobox will always display the first item
Me.ComboBox2.SelectedValue = selV
End Sub
I used a few properties and .net String.SubString method instead of the old vb6 Strings.Left.
Private Sub ComboBox1_DropDownClosed(sender As Object, e As EventArgs) Handles ComboBox1.DropDownClosed
Dim SelectedString As String = ComboBox1.SelectedItem.ToString
Dim ChangedString As String = SelectedString.Substring(0, 4)
Dim index As Integer = ComboBox1.SelectedIndex
ComboBox1.Items(index) = ChangedString
End Sub
You can fill your combo box one by one to avoid binding problems as follows...
Private Sub ComboBox1_DropDown(sender As Object, e As EventArgs) Handles ComboBox1.DropDown
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand("Select ID, Name From tblFruit;", cn)
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader
ComboBox1.BeginUpdate()
While dr.Read
ComboBox1.Items.Add(dr(0).ToString & " | " & dr(1).ToString)
End While
ComboBox1.EndUpdate()
End Using
End Using
End Using
You can solve this graphical problem putting a Label in your Form and moving it over your ComboBox.
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.Label1.AutoSize = False
Me.Label1.BackColor = Me.ComboBox1.BackColor
Me.Label1.Location = New Point(Me.ComboBox1.Location.X + 1, Me.ComboBox1.Location.Y + 1)
Me.Label1.Size = New Size(Me.ComboBox1.Width - 18, Me.ComboBox1.Height - 2)
Me.ComboBox1.Items.Add("0001 | Apple")
Me.ComboBox1.Items.Add("0002 | Pear")
Me.ComboBox1.Items.Add("0003 | Banana")
Me.ComboBox1.Items.Add("0004 | Pineapple")
Me.ComboBox1.Items.Add("0005 | Cherry")
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Me.Label1.Text = Trim(Me.ComboBox1.SelectedItem.Split("|")(0))
End Sub
Please note that:
you can populate your ComboBox a single time during Form load event
you can use SelectedIndexChanged instead of DropDown and DropDownClosed event
if this is not a graphical problem please give a look at DisplayMember and ValueMember properties
Having some issues getting a form to populate based on a variable determined in current form.
I have a search result form that has a datagrid with all results, with an open form button for each row. When the user clicks this, the rowindex is used to pull out the ID of that record, which then feeds to the newly opened form and populates based on a SQL stored procedure run using the ID as a paramter.
However, at the moment the variable is not feeding through to the form, and am lost as to why that is. Stored procedure runs fine if i set the id within the code. Here is my form open code, with sci
Public Class SearchForm
Dim Open As New FormOpen
Dim data As New SQLConn
Public scid As Integer
Private Sub Search_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim sql As New SQLConn
Call sql.SearchData()
dgvSearch.DataSource = sql.dt.Tables(0)
End Sub
Private Sub dgvSearch_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvSearch.CellContentClick
Dim rowindex As Integer
Dim oform As New SprinklerCardOpen
rowindex = e.RowIndex.ToString
scid = dgvSearch.Rows(rowindex).Cells(1).Value
TextBox1.Text = scid
If e.ColumnIndex = 0 Then
oform.Show()
End If
End Sub
End Class
The form opening then has the follwing:
Private Sub SprinklerCard_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Populate fields from SQL
Try
Call Populate.SprinklerCardPopulate(ID)
cboInsured.Text = Populate.dt.Tables(0).Rows(0).Item(1)
txtAddress.Text = Populate.dt.Tables(0).Rows(0).Item(2)
txtContactName.Text = Populate.dt.Tables(0).Rows(0).Item(3)
txtContactPhone.Text = Populate.dt.Tables(0).Rows(0).Item(4)
txtContactEmail.Text = Populate.dt.Tables(0).Rows(0).Item(5)
numPumps.Value = Populate.dt.Tables(0).Rows(0).Item(6)
numValves.Value = Populate.dt.Tables(0).Rows(0).Item(7)
cboLeadFollow.Text = Populate.dt.Tables(0).Rows(0).Item(8)
cboImpairment.Text = Populate.dt.Tables(0).Rows(0).Item(9)
txtComments.Text = Populate.dt.Tables(0).Rows(0).Item(10)
Catch ex As Exception
MsgBox(ex.ToString & "SCID = " & ID)
End Try
End Sub
Set the ID variable in the form before you open it.
If e.ColumnIndex = 0 Then
oform.ID = scid
oform.Show()
End If
I have an order form I created in VB.NET and I have a ListBox that is populated by order. You can double click on the order and it populates the order number in the order form. The problem I'm having is that it populates the TextBox with both the order number and the persons name. How can I use a delimiter to only pull out the order number and not the name also.
Imports Business_Objects
Public Class frmSummary
Private ctrl As Controller
Dim listID As ArrayList
Private Sub frmSummary_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
ctrl = CType(MdiParent, frmMain).ctrl
Dim list As ArrayList
list = ctrl.GetOrders
Dim order As Business_Objects.Order
For Each order In list
lstOrders.Items.Add(order.ID & "," & " " & order.Server)
Next
End Sub
Private Sub lstOrders_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstOrders.DoubleClick
Dim result As Boolean = False
If lstOrders.Text <> "" Then
result = True
Dim frm As New OrderForm
frm.MdiParent = Me.MdiParent
frm.Show()
frm.txtOrderNo.Text = lstOrders.Text
frm.btnFetch.PerformClick()
Else
MessageBox.Show("there are no orders here to click")
End If
End Sub
Private Sub btnRefresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRefresh.Click
lstOrders.Items.Clear()
ctrl = CType(MdiParent, frmMain).ctrl
Dim list As ArrayList
list = ctrl.GetOrders
Dim order As Business_Objects.Order
For Each order In list
lstOrders.Items.Add(order.ID & " " & order.Server)
Next
End Sub
End Class
If all of your data is being stored as a single field, or something like:
4322305 John Smith Carrots $3.00
845825 Sam White Oranges $1.25
Then you can read each record as a string, and then use split that into an array based on " " as your delimiter.
The code would look something like:
dim myArray as string() = myLongTextRecord.Split(" ")
And in that format,
textBoxName.Text = myArray[1]
You're almost there. You could use the split function, but another approach would be to add the Order object directly to the listbox and not text.
Private Sub frmSummary_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
ctrl = CType(MdiParent, frmMain).ctrl
Dim list As ArrayList
list = ctrl.GetOrders
Dim order As Business_Objects.Order
For Each order In list
lstOrders.Items.Add(order)
Next
End Sub
Private Sub lstOrders_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstOrders.DoubleClick
Dim result As Boolean = False
If lstOrders.Text <> "" Then
result = True
Dim frm As New OrderForm
frm.MdiParent = Me.MdiParent
frm.Show()
frm.txtOrderNo.Text = DirectCast(lstOrders.SelectedItem, Order).ID.ToString
frm.btnFetch.PerformClick()
Else
MessageBox.Show("there are no orders here to click")
End If
End Sub
You'll need to go into the Order object and override the .ToString function so that the text in the Listbox displays whatever value you want (ie. Return ID & "," & " " & Server)
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