pachjo Posted January 7, 2007 Posted January 7, 2007 I have made a button click handler to be generic to enable it to handle two buttons. One button saves a record to the transactions table and the other to the transactions_weekly table. Now if the record begin saved when running a call to the event handler for the transactions is of type "SHOPPING" the app prompts the user to ask do they want it also saved to the transactions_weekly table. If the answer is yes I believe I need to recall the event handler I am currently in? So to do this I create an object reference to the button on the form that would save a transaction_weekly record and then call the click event and pass it the reference object. Problem is the error appears saying that objSender is not initialised when an attempt is made to reference it? Am on on the right track or totally off beam? Private Sub btnSaveTransaction_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btnSaveTransaction1.Click, btnSaveTransaction2.Click ' check to see if a valid entry has been made If Not ValidateEntry(sender) Then Exit Sub End If ' create a control object to access the name of the button making the call Dim ctlSender As Control = DirectCast(sender, System.Windows.Forms.Control) ' controls to make this sub generic Dim ctlDateTimePicker As New DateTimePicker, ctlComboBox As New ComboBox, ctlTextBox As New TextBox Dim ctlCheckBox1 As New CheckBox, ctlCheckBox2 As New CheckBox ' create an SQL command object to write changes to the database Dim cmdTransactions As New System.Data.SqlClient.SqlCommand ' string to pass table name to dynamic sql Dim strTableName As String = "" ' object to reference the save button on the transactions weekly page Dim objSender As Object = DirectCast(Me.Controls("btnSaveTransaction2"), Object) ' query callers name to setup the sql staement and controls Select Case ctlSender.Name Case "btnSaveTransaction1" strTableName = "transactions" cmdTransactions.CommandText = "INSERT INTO transactions (tran_date, tran_id, tran_amount, tran_balance, tran_save, " & _ "tran_withdrawal) VALUES (@TransDate, @TransDesc, @TranAmount, 0, @Saved, @WithDraw)" ctlDateTimePicker = Me.dtmTransDate1 ctlComboBox = Me.cboTransDescription1 ctlTextBox = Me.txtAmount1 ctlCheckBox1 = Me.chkSave ctlCheckBox2 = Me.chkWithDraw ' detailed monthly has these but detailed weekly does not cmdTransactions.Parameters.Add("@Saved", SqlDbType.Decimal).Value = ctlCheckBox1.Checked cmdTransactions.Parameters.Add("@WithDraw", SqlDbType.Decimal).Value = ctlCheckBox2.Checked ' when the transaction type is shopping ask do we want to save to transactions weekly also If ctlComboBox.Text = "SHOPPING" Then If MessageBox.Show("Do you want this transaction written to the weekly transaction page", _ "Copy Transaction", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) _ = Windows.Forms.DialogResult.Yes Then ' set the fields on the transactions weekly page to the ones on the transaction page ' so when we call this event handler the values will be there as if the user had entered them Me.dtmTransDate2.Text = ctlDateTimePicker.Text Me.txtAmount2.Text = ctlTextBox.Text Me.cboTransDescription2.Text = ctlComboBox.Text ' simulate the user clicking the save button on the transactions weekly page btnSaveTransaction_Click(objSender, e) ' reset the transactions weekly fields Me.dtmTransDate2.Text = Now.ToString Me.txtAmount2.Text = "" End If End If Case "btnSaveTransaction2" strTableName = "transactions_weekly" cmdTransactions.CommandText = "INSERT INTO transactions_weekly (tran_date, tran_id, tran_amount, tran_balance) " & _ "VALUES (@TransDate, @TransDesc, @TranAmount, 0)" ctlDateTimePicker = Me.dtmTransDate2 ctlComboBox = Me.cboTransDescription2 ctlTextBox = Me.txtAmount2 End Select Try ' link the command to the database connection cmdTransactions.Connection = glb_cnMB2007 ' add the parameters to the command cmdTransactions.Parameters.Add("@TransDate", SqlDbType.DateTime).Value = ctlDateTimePicker.Text cmdTransactions.Parameters.Add("@TransDesc", SqlDbType.VarChar).Value = ctlComboBox.SelectedValue.ToString cmdTransactions.Parameters.Add("@TranAmount", SqlDbType.Decimal).Value = ctlTextBox.Text ' if the record was appended successfully then update the transaction display If cmdTransactions.ExecuteNonQuery() = 1 Then ' refresh the rolling balance in transaction table CalculateRollingBalance(strTableName) If Not RefreshTransactionLists(Me.tbcMain.SelectedIndex) Then Me.Controls("btnSaveTransaction" & Me.tbcMain.SelectedIndex).Enabled = False Me.Controls("btnClearTransaction" & Me.tbcMain.SelectedIndex).Enabled = False End If End If ' reset the transaction fields ctlDateTimePicker.Value = Now ctlTextBox.Text = "" ctlTextBox.Select() Catch objError As Exception ' tell user no connection made MessageBox.Show("Failed to save transaction to the database" & vbCrLf & vbCrLf & objError.Message, _ "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub Quote
Administrators PlausiblyDamp Posted January 7, 2007 Administrators Posted January 7, 2007 Rather than explicity calling the btnSaveTransaction_Click(objSender, e) method directly you might want to use the PerformClick on the btnSaveTransaction2 control. Also I notice you are creating a lot of controls in the code i.e. Dim ctlDateTimePicker As New DateTimePicker, ctlComboBox As New ComboBox, ctlTextBox As New TextBox Dim ctlCheckBox1 As New CheckBox, ctlCheckBox2 As New CheckBox if you are going to assign existing controls to these variables you do not need the New keyword - this will prevent you creating the unused instances of the controls and will keep the memory utilisation down. In the line Dim objSender As Object = DirectCast(Me.Controls("btnSaveTransaction2"), Object) the direct cast isn't required as everything is an object and therefore the cast is always safe and going to succeed. In the long run though it might be easier to have two separate methods - one to update the transactions table and one to update the transactions_weekly table and simply call the correct method(s) from the appropriate button click event. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
MrPaul Posted January 7, 2007 Posted January 7, 2007 Code refactoring Generally, instead of using the same method to handle both clicks, I would suggest moving the shared code (code that would be executed by both handlers) to a seperate sub or function which is called by both handlers. Your Select block shows that there is quite a bit of button-specific code, so two handlers would make more sense. This would also allieviate your problem since the handlers would not need to check the sender parameter. There are other ways you could refactor your code, such as putting the code for btnSaveTransaction2 into its own sub and calling it directly. Either way, I think some sort of refactoring would be the best solution, if only to make the code easier to understand. As far as your current code goes: Dim objSender As Object = DirectCast(Me.Controls("btnSaveTransaction2"), Object) You never need to explicitly cast something to Object as all upcasts are implicit, and casting to Object is the ultimate upcast. I would suggest you use Me.controlname rather than Me.Controls("controlname") as this is more efficient, less prone to errors, and does not require a cast. Quote Never trouble another for what you can do for yourself.
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.