I have a variable that is being passed from my first form, to my second form. However, when I try to use this variable inside my ComboBox event handler method, it's showing up blank and I can't figure out why.
Public CellValue As String
Public Sub New(ByVal CellValue As String)
InitializeComponent()
MsgBox(CellValue)
End Sub
This works just fine, I am able to bring up the messagebox with the Cell Value. However, when I try to access this CellValue in my combo box method that is on the same Form, the variable is blank, and I can't figure out why.
Public Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
MsgBox(CellValue)
End Sub
I've tried putting the "ByVal CellValue As String" as an argument in the combobox but that does not work, I get an error that it can not handle the event.
I have the variable set as public so I don't understand what is going on. Any help in the right direction would be great because I have been searching the net for hours.
Here is the Form1 if that helps:
Imports MySql.Data.MySqlClient
Public Class Form1
Dim MysqlConn As MySqlConnection
Dim COMMAND As MySqlCommand
Dim value As String
Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MysqlConn = New MySqlConnection
MysqlConn.ConnectionString = "server=0.0.0.0;
userid=username;
password=******;
database=password"
Dim SDA As New MySqlDataAdapter
Dim dbDataSet As New DataTable
Dim bSource As New BindingSource
Try
MysqlConn.Open()
Dim Query As String
Query = "select CaseNumber, FirstName, LastName from customer"
COMMAND = New MySqlCommand(Query, MysqlConn)
SDA.SelectCommand = COMMAND
SDA.Fill(dbDataSet)
bSource.DataSource = dbDataSet
DataGridView1.DataSource = bSource
SDA.Update(dbDataSet)
MysqlConn.Close()
Catch ex As MySqlException
MessageBox.Show(ex.Message)
Finally
MysqlConn.Dispose()
End Try
End Sub
Public Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
If e.ColumnIndex = 0 Then
Dim CellValue As Object = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
If IsDBNull(value) Then
MsgBox("No Case Number for this particular record.")
Else
Dim ThirdForm As New Form2(CellValue)
Me.Hide()
ThirdForm.Show()
End If
End If
End Sub
End Class
The following worked for me thanks to Plutonix in comment section. Thank you.
Me.CellValue = CellValue
Related
I made a Sub that will populate my combobox with loan descriptions. I want to get the loancode of the loandescription on selectedindexchanged without querying again the database. Is this possible? Or should I query the database to get the indicated loancode?
Private Sub LoanProducts()
Using cmd As New SqlClient.SqlCommand("SELECT loancode,loandescription FROM LoanProducts", gSQlConn)
Dim dt As New DataTable
Dim da As New SqlClient.SqlDataAdapter
dt.Clear()
da.SelectCommand = cmd
da.Fill(dt)
For Each row As DataRow In dt.Rows
CmbLoanAvail.Items.Add(row("loandescription"))
Next row
End Using
End Sub
Expected output:
Everytime the combobox index changed, the loancode of the selected loandescription will be displayed to a textbox.
Set DataTable to combobox .DataSource property and populate .ValueMember and .DisplayMember properties with corresponding column names.
Private Sub LoanProducts()
Dim query As String = "SELECT loancode, loandescription FROM LoanProducts"
Using command As New SqlCommand(query, gSQlConn)
Dim data As New DataTable
Dim adapter As New SqlClient.SqlDataAdapter With
{
.SelectCommand = cmd
}
adapter.Fill(data)
CmbLoanAvail.ValueMember = "loancode"
CmbLoanAvail.DisplayMember = "loandescription"
CmbLoanAvail.DataSource = data
End Using
End Sub
You can use SelectionChangeCommitted event to execute some action when user made a selection
Private Sub comboBox1_SelectionChangeCommitted(
ByVal sender As Object, ByVal e As EventArgs) Handles comboBox1.SelectionChangeCommitted
Dim combobox As ComboBox = DirectCast(sender, ComboBox)
Dim selectedCode As String = combobox.SelectedValue.ToString() // returns 'loancode'
End Sub
If you could get DB rows as strongly typed classes, you could make use of ItemSource, DisplayMember and ValueMember, which would solve your problem.
In case you presented, you can use SelectedIndex property of ComboBox. Also, you need to store resultset in some class field (preferably Pirvate one). See example code below:
Public Class Form4
Private _result As DataTable
Private Sub Form4_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As New DataTable
dt.Columns.Add("col1")
dt.Columns.Add("col2")
dt.Rows.Add("val11", "val12")
dt.Rows.Add("val21", "val22")
' at this point, we got our result from DB
_result = dt
For Each row As DataRow In dt.Rows
ComboBox1.Items.Add(row("col1"))
Next
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim selectedIndex = ComboBox1.SelectedIndex
Dim selectedRow = _result(selectedIndex)
End Sub
End Class
Keep your database objects local to the method where they are used so you can ensure that they are closed and disposed. Note the comma at the end of the first Using line. This includes the command in the same Using block.
Set the DataSource, DisplayMember and ValueMember after the Using block so the user interface code doesn't run until the connection is disposed.
To get the loan code you simply access the SelectValue of the ComboBox.
Private Sub LoanProducts()
Dim dt As New DataTable
Using gSqlConn As New SqlConnection("Your connection string"),
cmd As New SqlClient.SqlCommand("SELECT loancode,loandescription FROM LoanProducts", gSqlConn)
gSqlConn.Open()
dt.Load(cmd.ExecuteReader)
End Using
ComboBox1.DataSource = dt
ComboBox1.DisplayMember = "loandescription"
ComboBox1.ValueMember = "loancode"
End Sub
Private Sub ComboBox1_SelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
MessageBox.Show($"The Loan Code is {ComboBox1.SelectedValue}")
End Sub
I am trying to edit customers using my C# project to learn how to implement this code in VB.net. The project was successful in adding customers, but when it got to editing customers, things got a bit more complicated because I needed to get the id of the row selected and pass it to a string. I have the MainForm.vb which could open CustomerForm.vb when I click on 'Edit'. When CustomerForm.vb opens, it failed to show the customer's info. I am not sure if FillDataTable() function is necassary, I would like to know if there is an improvement to this.
CustomerForm.vb
Imports System.Data.SqlClient
Public Class CustomerForm
Private objConnection As SqlConnection
Public objDataTable As DataTable = New DataTable()
Public objSqlCommand As SqlCommand = New SqlCommand()
Public editMode As Boolean = False
Public id As String = ""
Public FName As String = ""
Public LName As String = ""
Public PhNumber As String = ""
Public ReadOnly Property Connection As SqlConnection
Get
Return Me.objConnection
End Get
End Property
Dim CS As String = ("server=CASHAMERICA;Trusted_Connection=yes;database=ProductsDatabase2; connection timeout=30")
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Try
If editMode = False Then
If txtFirstName.Text = "" Then
MessageBox.Show("First Name Is required")
ElseIf txtLastName.Text = "" Then
MessageBox.Show("Last Name Is required")
Else
Dim con As New SqlConnection(CS)
con.Open()
Dim cmd As New SqlCommand("INSERT INTO Customers(FIrstName,LastName,PhoneNumber) VALUES(#FName, #LName, #PhNumber)", con)
cmd.Parameters.AddWithValue("#FName", txtFirstName.Text)
cmd.Parameters.AddWithValue("#LName", txtLastName.Text)
cmd.Parameters.AddWithValue("#PhNumber", txtPhoneNumber.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("Customer has been added!")
con.Close()
End If
ElseIf editMode = True Then
If txtFirstName.Text = "" Then
MessageBox.Show("First Name Is required")
ElseIf txtLastName.Text = "" Then
MessageBox.Show("Last Name Is required")
Else
Dim con As New SqlConnection(CS)
con.Open()
Dim cmd As New SqlCommand("UPDATE Customers SET FIrstName = #FName, LastName = #LName, PhoneNumber = #PhNumber WHERE Id = #Id", con)
cmd.Parameters.AddWithValue("#Id", id)
cmd.Parameters.AddWithValue("#FName", txtFirstName.Text)
cmd.Parameters.AddWithValue("#LName", txtLastName.Text)
cmd.Parameters.AddWithValue("#PhNumber", txtPhoneNumber.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("Customer has been edited.")
con.Close()
End If
End If
Catch ex As Exception
MessageBox.Show(Me, ex.Message, "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
Private Sub CustomerForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If editMode = False Then
GetId()
Else
textId.Text = id
txtFirstName.Text = FName
txtLastName.Text = LName
txtPhoneNumber.Text = PhNumber
End If
End Sub
Private Sub GetId()
Dim con As New SqlConnection(CS)
con.Open()
Dim cmd As New SqlCommand("SELECT MAX(id)+1 FROM Customers")
textId.Text = FillDataTable().Rows(0)(0).ToString()
If textId.Text = "" Then
textId.Text = "1"
End If
End Sub
Public Property CommandText As String
Get
Return CommandText
End Get
Set(ByVal value As String)
CommandText = value
End Set
End Property
Public Sub OpenDBConnection()
objConnection = New SqlConnection(CS)
objConnection.Open()
End Sub
Public Sub CreateCommandObject()
objSqlCommand = objConnection.CreateCommand()
objSqlCommand.CommandText = CommandText
objSqlCommand.CommandType = CommandType.Text
End Sub
Public Function FillDataTable() As DataTable
objDataTable = New DataTable()
objSqlCommand.CommandText = CommandText
objSqlCommand.Connection = objConnection
objSqlCommand.CommandType = CommandType.Text
objDataTable.Load(objSqlCommand.ExecuteReader())
objConnection.Close()
Return objDataTable
End Function
Public Sub CloseConnection()
If objConnection IsNot Nothing Then objConnection.Close()
End Sub
End Class
MainForm.vb
Imports System.Windows.Forms.LinkLabel
Public Class MainForm
Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
Me.Close()
End Sub
Private Sub AddToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AddToolStripMenuItem.Click
CustomerForm.ShowDialog()
End Sub
Private Sub AddToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles AddToolStripMenuItem1.Click
ProductForm.ShowDialog()
End Sub
Private Sub ViewProductsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ViewProductsToolStripMenuItem.Click
ManageProductsForm.ShowDialog()
End Sub
Private Sub AboutToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AboutToolStripMenuItem.Click
AboutForm.Show()
End Sub
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'ProductsDatabase2DataSet1.Customers' table. You can move, or remove it, as needed.
Me.CustomersTableAdapter.Fill(Me.ProductsDatabase2DataSet1.Customers)
End Sub
Private Sub gridCustomers_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles gridCustomers.MouseUp
Try
Dim f As CustomerForm = New CustomerForm()
f.editMode = True
Dim rowIndex As Integer = gridCustomers.CurrentCell.RowIndex
f.id = gridCustomers.Rows(rowIndex).Cells("colId").Value.ToString()
f.FName = gridCustomers.Rows(rowIndex).Cells("colFirstName").Value.ToString()
f.LName = gridCustomers.Rows(rowIndex).Cells("colLastName").Value.ToString()
f.PhNumber = gridCustomers.Rows(rowIndex).Cells("colPhoneNumber").Value.ToString()
f.Show()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub gridCustomers_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles gridCustomers.CellContentClick
Dim f As CustomerForm = New CustomerForm()
f.ShowDialog(Me)
f.editMode = True
End Sub
End Class
Error Message:
Customer Info not displayed:
As mentioned, it seems like you have several things potentially going on.
The first thing I would change is your public sql objects. You don't need them to be public. It also increases the chances for issues if you're using the same objects in multiple places.
SqlCommand, SqlConnection, and SqlDataAdapters can be immediately disposed of (in most cases) as soon as they are used.
One easy method to handling all of that is to throw everything inside of a USING block.
Dim sqlResult As New Datatable()
Using cn As New SqlConnection("Connection String here"),
cmd As New SqlCommand(sql, cn),
adapt As New SqlDataAdapter(cmd)
cn.Open()
'Handle stored procedure vs select options
If sql.Contains("SELECT") Then
cmd.CommandType = CommandType.Text
Else
cmd.CommandType = CommandType.StoredProcedure
End If
'If parameters passed, else comment out
cmd.Parameters.AddWithValue("#parameterName", parameterValue)
sqlResult = New DataTable(cmd.CommandText)
adapt.Fill(sqlResult)
End Using
Now all your objects are disposed of as soon as your datatable is filled.
*This example uses a datatable, but it is the same idea for anything interacting with sql objects.
If implemented, you may find out that some objects weren't being disposed of or initialized properly.
Another method for testing where things are going wrong is to query the states of the SQL objects before or around the error to see if something isn't set correctly or is uninitialized.
The code for my animated text already stored in my Table1 works very well without any error in my MDIParent1.But when I execute another code for exemple an print code when i click on Button_Print The animated text will stop Temporary and the animation of the text will be very heavy.Please How to run other code without effect on my animated text ?
My code in Module1
Public Sub Text_Panel_Animation()
Try
Dim da As New OleDbDataAdapter("Select * from Table1 order by Id", Con)
Dim dt As New DataTable
da.Fill(dt)
MDIParent1.Label1.Left = 0 - MDIParent1.Label1.Width
If dt.Rows.Count > 0 Then
For r As Integer = 1 To dt.Columns.Count - 1
MDIParent1.Label1.Text &= " " & (dt(0)(r).ToString)
Next
MDIParent1.Timer1.Start()
End If
Con.Close()
Catch ex As Exception
MsgBox(ex.Message(), MsgBoxStyle.Critical, "Error")
End Try
End Sub
In MDIParent1 Load .. I put this code :
Call Text_Panel_Animation()
And In MDIParent1 .. i have also :
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If Label1.Left >= Me.Panel1.Width Then Label1.Left = 0 - Label1.Width
Label1.Left += 1
End Sub
I tried with this code but i have a same problem :
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Task.Run(Sub()
Try
Dim Dt As New DataTable
Dim SQLstr As String = "Select * from Table1"
SQLstr = "Select * from Table1 order BY Id"
Dim Da As New OleDbDataAdapter(SQLstr, Con)
Da.Fill(Dt)
Dim Rpt As New Crystal1
Rpt.SetDataSource(Dt)
Dim frm As New Form1
Me.Dispose()
frm.Show()
Form1.CrystalReportViewer1.Zoom(100%)
Catch
End Try
End Sub)
End Sub
You can start the printing in a new task
Private Sub Button_Print_Click (sender As Object, e As EventArgs) Handles Button_Print.Click)
Task.Run(Sub()
'TODO: Do the printing here...
End Sub)
End Sub
Note that you have to take precautions to be able to access the UI from this other task. See: VB.NET: Invoke Method to update UI from secondary threads
I would not do any UI stuff in the other task, since this can lead to problems. Instead, I would only query the DB and render the report in another task and then await this task before doing UI-related things. I'm not using Crystal Reports myself, but it would probably be something like this
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Rpt As Crystal1
Await Task.Run(
Sub()
Try
Dim Dt As New DataTable
Dim SQLstr As String
SQLstr = "Select * from Table1 order BY Id"
Dim Da As New OleDbDataAdapter(SQLstr, Con)
Da.Fill(Dt)
Rpt = New Crystal1
Rpt.SetDataSource(Dt)
Catch
End Try
End Sub)
Dim frm As New Form1
Me.Dispose()
frm.Show()
Form1.CrystalReportViewer1.Zoom(100%)
Form1.CrystalReportViewer1.ReportSource = Rpt
End Sub
Do not forget the Async keyword in the method header.
Note: If Me is the main form, then Me.Dispose() will terminate the application.
I have created a Datagridview that displays all Data. I now want to be able to filter my data. I am using a DataSet, BindingSource and TableAdapter. I tried a few things but nothing seems to work. Currently I have a TextBox that should filter when written. When I execute and type in the box it doesnt filter or error out. Below is the code that I have. Am I missing Something?
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DataGridView1.AllowUserToAddRows = True
DataGridView1.AllowUserToDeleteRows = True
Dim cn As SqlConnection = New SqlConnection("")
adap = New SqlDataAdapter("SELECT res_snbr, First_Name, Last_Name, Item FROM Inventory_Details", cn)
Dim builder As New SqlCommandBuilder(adap)
adap.InsertCommand = builder.GetInsertCommand()
'adap.UpdateCommand = builder.GetUpdateCommand()
'adap.DeleteCommand = builder.GetDeleteCommand()
dt = New DataTable()
adap.Fill(dt)
DataGridView1.DataSource = dt
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If TextBox1.TextLength > 0 Then
InventoryDetailsBindingSource.Filter = _
String.Format("res_snbr Like '%" & TextBox1.Text) & "%'"
Else
InventoryDetailsBindingSource.Filter = String.Empty
End If
End Sub
Imports System.Data.SqlClient
Public Class Form1
Dim cn As New SqlConnection("Data Source=;Initial Catalog=;Persist Security Info=True;User ID=;Password=")
Dim adap As New SqlDataAdapter("SELECT res_snbr, First_Name, Last_Name, Item FROM Inventory_Details", cn)
Dim builder As New SqlCommandBuilder(adap)
Dim dt As New DataTable
Dim InventoryDetailsBindingSource As New BindingSource
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
adap.InsertCommand = builder.GetInsertCommand()
adap.Fill(dt)
InventoryDetailsBindingSource.DataSource = dt
DataGridView1.DataSource = InventoryDetailsBindingSource
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If TextBox1.TextLength > 0 Then
InventoryDetailsBindingSource.Filter = String.Format("res_snbr Like '%{0}%'", TextBox1.Text)
Else
InventoryDetailsBindingSource.Filter = String.Empty
End If
End Sub
End Class
There are a number of ways to accomplish what you wish to do here, the code above is how I would do it. Among other differences, please note that the BindingSource is being used as the the DataSource for the DataGridView, and the correct use of String.Format when setting the Filter property of the BindingSource.
Cheers!
If your datasource is a datatable you can try this.
TryCast(InventoryDetailsBindingSource, DataTable).DefaultView.RowFilter = String.Format("Field = '{0}'", textBoxFilter.Text)
You can use the row filter property on the datatable as shown here.
http://www.csharp-examples.net/dataview-rowfilter/
I have a DataGridview that displays the data and a TextBox that allows me to filter the BindingSource with an SQL query to display the data based on the input string. This is all working fine apart from once I have filtered the DataGridView the timer function I have is resetting it back so all the data is being displayed again. The timer is set on a 1000ms basis, so it will show the filtered result for a second, then revert back.
Heres my code:
Imports System.Data.OleDb
Public Class Form1
Dim duraGadgetDB As String = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source = C:\Users\Dave\Documents\duraGadget.mdb;"
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "dura"
DataGridView1.Columns(5).Width = 300
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
insert.Show()
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim currentRowID As Integer
Dim scrollPosition As Integer = DataGridView1.FirstDisplayedScrollingRowIndex
Try
If DataGridView1.CurrentRow IsNot Nothing Then
currentRowID = DataGridView1.CurrentRow.Index
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "dura"
DataGridView1.CurrentCell = DataGridView1.Item(1, currentRowID)
End If
Catch ex As Exception
End Try
DataGridView1.FirstDisplayedScrollingRowIndex = scrollPosition
End Sub
Private Sub txtSearchOnSku_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSearchOnSku.TextChanged
Dim currentRowID As Integer
Dim scrollPosition As Integer = DataGridView1.FirstDisplayedScrollingRowIndex
Try
If DataGridView1.CurrentRow IsNot Nothing Then
currentRowID = DataGridView1.CurrentRow.Index
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
Dim dsView As New DataView
Dim bs As New BindingSource()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
dsView = ds.Tables(0).DefaultView
bs.DataSource = dsView
bs.Filter = "skuNo LIKE'" & txtSearchOnSku.Text & "*'"
DataGridView1.DataSource = bs
DataGridView1.CurrentCell = DataGridView1.Item(1, currentRowID)
End If
Catch ex As Exception
End Try
DataGridView1.FirstDisplayedScrollingRowIndex = scrollPosition
End Sub
End Class
Can anyone tell me how to stop this happening?
Assuming you mean that, if you have entered a value in your text box to filter your results, that you then don't want you timer to fire and unfilter them...
You can either, check the contents of the TextBox in the Timer1_Tick routine;
If txtSearchOnSku.Text <> "" Then Exit Sub
Or you can disable your timer in the txtSearchOnSku_TextChanged routine;
If txtSearchOnSku.Text <> "" Then
Timer1.Stop
Else
Timer1.Start
End If
Or, if you want to update your results once a second, based on you search, you can include the Filtering code in your Timer1_Tick routine.
As a quick point, you have alot of repeated code there. It may be worthwhile refactoring the repeated code out into another sub.