0

我正在開發一個開發票應用程序。我在FlowLayoutPanel(pnlEntries)內的UserControl(InvoiceEntry)中有一個標籤(lblCost)。 InvoiceEntry表示發票上的行項目,而pnlEntries是發票的「正文」。 pnlEntries可以容納幾個InvoiceEntry控件。FlowLayoutPanel裏面的UserControl內部的控件的處理值改變

我試圖從每個InvoiceEntry控件中總結所有lblCost值以創建一個小計,並且如果成本發生變化(例如,訂購數量發生變化),我希望小計會自動更改。有什麼方法可以處理pnlEntries中包含的任何InvoiceEntry控件的lblCost.Text屬性何時發生更改?

InvoiceAdd.vb:

' Instantiate objects of the various database interaction classes. 
Private mCustomer As New Customers 
Private mItem As New Items 
Private mInvoices As New Invoices 
Private mInvoiceItem As New InvoiceItems 

' An array of InvoiceEntries for DB processing 
Private Entries() As InvoiceEntry 
Private numEntries As Integer = 0 

Private Sub InvoiceAdd_Load(sender As System.Object, e As System.EventArgs) _ 
      Handles MyBase.Load 

    Me.CustomersTableAdapter.Fill(Me.Bauer_BusinessDataSet.Customers) 

    ' Set the DataSource properties of the invEntry control. 
    ' NOTE: For some reason, if this is done inside the 
    ' control code, the program attempts to look in the 
    ' wrong directory for the database. I'm not entirely 
    ' sure why this is. Setting these properties in the form code, 
    ' rather than in the control code, is a successful workaround. 
    With invEntry.cboItem 
     .DataSource = mItem.Items 
     .DisplayMember = "ItemName" 
     .ValueMember = "Id" 
    End With 
End Sub 

Private Sub UpdateTotal() Handles nudTaxRate.TextChanged, _ 
            pnlEntries.GotFocus 

    Dim total As Decimal = 0 

    If Entries IsNot Nothing Then 

     For Each x In Entries 
      total += CDec(x.lblTotal.Text) 
     Next 
     lblSubtotal.Text = total.ToString("C") 
     lblTax.Text = (lblSubtotal.Text * (nudTaxRate.Text/100)).ToString("C") 

     Dim subtotal As Decimal = 0 
     Dim tax As Decimal = 0 
     If Not lblSubtotal.Text = Nothing And Not lblTax.Text = Nothing Then 
      Decimal.TryParse(lblSubtotal.Text.Substring(1), subtotal) 
      Decimal.TryParse(lblTax.Text.Substring(1), tax) 
     End If 

     lblGrandTotal.Text = (subtotal + tax).ToString("C") 
    End If 
End Sub 

Public Sub invEntry_ItemSelected() Handles invEntry.ItemSelected 

    ' Increment the number of entries to reflect the addition of a new entry. 
    numEntries += 1 

    ' ReDim the Entries array to compensate for a new item being added. 
    ReDim Preserve Entries(numEntries - 1) 

    ' Store the line item that was selected in the Entries array. 
    Entries(numEntries - 1) = invEntry 

    ' Set the selected line item to a new blank line item and 
    ' add it to the pnlEntries' Controls Collection. 
    invEntry = New InvoiceEntry 
    With invEntry 
     .Name = "Textbox" & numEntries - 1 
     .Location = New Point(10, (numEntries - 1) * (.Height + 30)) 
     With .cboItem 
      .DataSource = mItem.Items 
      .DisplayMember = "ItemName" 
      .ValueMember = "Id" 
     End With 
    End With 
    pnlEntries.Controls.Add(invEntry) 

    ' Enable the remove button on the previous list item, as 
    ' it is no longer an empty entry. 
    Entries(numEntries - 1).btnRemove.Enabled = True 

End Sub 

Public Sub pnlEntries_ControlRemoved() Handles pnlEntries.ControlRemoved 
    numEntries -= 1 
    ReDim Preserve Entries(numEntries - 1) 

    ' As the Entries array does not know which control was removed, 
    ' repopulate it with the controls from the panel. 
    ' NOTE: This intentionally leaves the blank line item (invEntry) 
    '  out of the array, as this array will be used to add 
    '  the invoice line items to the database. 
    For x As Integer = 0 To Entries.Count - 1 
     Entries(x) = pnlEntries.Controls(x) 
    Next 
End Sub 

InvoiceEntry.vb:

' Instantiate an object to interact with the Item table. 
Private mItem As New Items 

Public Event ItemSelected As EventHandler 

Private Sub cboItem_SelectionChangeCommitted(sender As System.Object, _ 
        e As System.EventArgs) _ 
        Handles cboItem.SelectionChangeCommitted 
    RaiseEvent ItemSelected(Me, EventArgs.Empty) 
End Sub 

Private Sub InvoiceEntry_Load(sender As System.Object, _ 
           e As System.EventArgs) _ 
           Handles MyBase.Load 

    ' Set the various properties of the Item combobox. 
    With cboItem 
     .SelectedIndex = -1 
     .DropDownStyle = ComboBoxStyle.DropDownList 
    End With 

    ' Set the Remove button to be disabled by default. 
    btnRemove.Enabled = False 
End Sub 

Private Sub cboItem_SelectedIndexChanged(sender As System.Object, _ 
        e As System.EventArgs) _ 
        Handles cboItem.SelectedIndexChanged 

    ' If nothing is selected, clear and disable all relevant controls. 
    If cboItem.SelectedIndex = -1 Or cboItem.Text = "" Then 
     lblDescription.Text = "" 
     lblTotal.Text = "" 
     nudQuantity.Enabled = False 
     lblPrice.Text = "" 
    Else 

     ' Else, set the control texts to their respective values. 
     lblDescription.Text = _ 
      cboItem.DataSource.Rows(cboItem.SelectedIndex)("Description") 
     lblPrice.Text = cboItem.DataSource.Rows(cboItem.SelectedIndex)("Price") 
     lblTotal.Text = (lblPrice.Text * nudQuantity.Value).ToString("C") 
     nudQuantity.Enabled = True 
    End If 
End Sub 

Private Sub lblTotal_TextChanged(sender As System.Object, _ 
           e As System.EventArgs) _ 
           Handles lblTotal.TextChanged 

    ' This is part of my workaround that I describe in the comments section 
    ' of this StackOverflow question. 
    Parent.Focus() 
End Sub 

Private Sub nudQuantity_ValueChanged(sender As System.Object, _ 
            e As System.EventArgs) _ 
            Handles nudQuantity.TextChanged 

    ' If the quantity changes, set the total price to reflect this. 
    lblTotal.Text = (lblPrice.Text * nudQuantity.Value).ToString("C") 
End Sub 

Private Sub btnRemove_Click(sender As System.Object, _ 
          e As System.EventArgs) _ 
          Handles btnRemove.Click 

    ' Remove the control from the parent design. 
    Me.Parent.Controls.Remove(Me) 
End Sub 

回答

2

既然你已經得到了內InvoiceEntry TextChanged事件處理程序,您可以輕鬆地調用InvoiceAdd的UpdateTotal函數形式

InvoiceEntry.vb

Private Sub lblTotal_TextChanged(sender As System.Object, _ 
           e As System.EventArgs) _ 
           Handles lblTotal.TextChanged 

    ' This is part of my workaround that I describe in the comments section 
    ' of this StackOverflow question. 

    'Parent.Focus() 
    'Me.Parent could give you the parent control which is pnlEntry not InvocieAdd form 
    'you need to use FindForm here 
    Dim MyParentForm As InvoiceAdd = CType(Me.FindForm(), InvoiceAdd) 
    MyParentForm.UpdateTotal() 
End Sub 

InvoiceAdd.vb

Public Sub UpdateTotal() Handles nudTaxRate.TextChanged, _ 
            pnlEntries.GotFocus 

    'Change the function to Public 

    Dim total As Decimal = 0 

    If Entries IsNot Nothing Then 

     For Each x In Entries 
      total += CDec(x.lblTotal.Text) 
     Next 
     lblSubtotal.Text = total.ToString("C") 
     lblTax.Text = (lblSubtotal.Text * (nudTaxRate.Text/100)).ToString("C") 

     Dim subtotal As Decimal = 0 
     Dim tax As Decimal = 0 
     If Not lblSubtotal.Text = Nothing And Not lblTax.Text = Nothing Then 
      Decimal.TryParse(lblSubtotal.Text.Substring(1), subtotal) 
      Decimal.TryParse(lblTax.Text.Substring(1), tax) 
     End If 

     lblGrandTotal.Text = (subtotal + tax).ToString("C") 
    End If 
End Sub 
+0

不幸的是,沒有。該標籤在UserControl中生成,並通過將數據庫中找到的項目價格乘以數量來分配一個值。我通過讓UserControl執行Parent.Focus(),然後在pnlResults.GotFocus()的表單中添加一個處理程序來解決問題,但我敢肯定,這比合法代碼更像是一種黑客攻擊。 –

+0

因此,您無法觸摸UserControl源代碼,只能使用父對象? – Nick

+0

如果是這種情況,我建議你爲父對象添加一個KeysUp事件處理程序,並檢查文本是否改變了lblCost – Nick

相關問題