How to refresh data while saving in vb.net? - vb.net

I want to refresh my data while clicking save button. I am using a datagridview but it won't refresh automatically. How can I code it?
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sql As String = "INSERT INTO tblproduct (product, Supplierprice, Projectprice) VALUES (#product, #Supplierprice, #Projectprice)"
cmd = New MySqlCommand(sql, con)
'parameters()
cmd.Parameters.AddWithValue("#product", txtproductname.Text)
cmd.Parameters.AddWithValue("#Supplierprice", txtsupprice.Text)
cmd.Parameters.AddWithValue("#Projectprice", txtproprice.Text)
Try
con.Open()
If MessageBox.Show("Are You Sure To Save This?", "SAVE", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
If cmd.ExecuteNonQuery() > 0 Then
MsgBox("Successfully Saved")
End If
End If
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
con.Close()
End Try
Refresh()
Hide()
End Sub

This is the way I would do it.
First create a class.
Public Class Product
Public Sub New(productName As String, supplierPrice As String, projectPrice As String)
Me.ProductName = productName
Me.SupplierPrice = supplierPrice
Me.ProjectPrice = projectPrice
End Sub
Public Property ProductName As String
Public Property SupplierPrice As String
Public Property ProjectPrice As String
End Class
Declare a BindingList of the class and use that as the datasource. When adding an item, just add to the BindingList. The grid will automatically be refreshed.
Public Class Form1
Private Products As New BindingList(Of Product)
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
dgvProducts.DataSource = Products
End Sub
Private Sub bnAdd_Click(sender As Object, e As EventArgs) Handles bnAdd.Click
Dim item As Product = New Product(tbProductName.Text, tbSupplierPrice.Text, tbProjectPrice.Text)
If MessageBox.Show($"Are You Sure To Save the product : {item.ProductName}?", "SAVE", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
SaveProduct(item)
Products.Add(item)
End If
End Sub
Private Sub SaveProduct(item As Product)
'Add database insert code
End Sub
End Class

Related

Filtering a data grid view using a combo box

When I select an element from the combo box, the DGV clears.
There is an Access database that has a table with room booking details, the code is supposed to use the combo box to filter the data to only show the selected room type.
I'm not sure if this code is on the right lines, so any help is appreciated.
Code for the form:
Imports System.Data.OleDb
Public Class frmViewEditBookings
Private DB As New DBControl
Private CurrentRecord As Integer = 0
'Error checking and reporting
Private Function NoErrors(Optional Report As Boolean = False) As Boolean
If Not String.IsNullOrEmpty(DB.Exception) Then
If Report = True Then MsgBox(DB.Exception)
Return False
Else
Return True
End If
End Function
Private Function NotEmpty(text As String) As Boolean
Return Not String.IsNullOrEmpty(text)
End Function
Public Sub RefreshGrid()
'Run query
DB.ExecQuery("SELECT * FROM tblRoomBookings")
'Report and abort on errors
If NoErrors(True) = False Then Exit Sub
'Fill combo box
For Each R As DataRow In DB.DT.Rows
cboRoomType.Items.Add(R("RoomType"))
Next
'If data is returned populate DGV and build update command
If DB.RecordCount > 0 Then
dgvBookings.DataSource = DB.DS.Tables(0)
dgvBookings.Rows(0).Selected = True
End If
End Sub
Private Sub frmViewEditBookings_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
'Perform subroutine RefreshGrid
RefreshGrid()
'Display specified room
If DB.RecordCount > 0 Then cboRoomType.SelectedIndex = 0
'Disable Save Button
btnSave.Enabled = False
End Sub
Private Sub SearchRoomType(RoomType As String)
'Add parameters and run query
DB.AddParam("#RoomType", RoomType)
DB.ExecQuery("SELECT * FROM tblRoomBookings WHERE RoomType =#RoomType")
'Report and abort on errors
If NotEmpty(DB.Exception) Then MsgBox(DB.Exception) : Exit Sub
'Report and abort on errors
If NoErrors(True) = False OrElse DB.RecordCount < 1 Then Exit Sub
End Sub
Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
'Run subroutine SearchRoomType
SearchRoomType(cboRoomType.Text)
End Sub
Private Sub cboRoomType_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cboRoomType.SelectedIndexChanged
If Not String.IsNullOrEmpty(cboRoomType.Text) Then SearchRoomType(cboRoomType.Text)
'Hide lblSearch
lblSearchRoomType.Visible = False
End Sub
Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click
'Close the form
Me.Close()
End Sub
End Class
DBControl class:
Imports System.Data.OleDb
Public Class DBControl
'Create connection to the database
Private DBCon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" &
"Data Source=|DataDirectory|\NewHotel.mdb;")
'Prepare the database command
Private DBCmd As OleDbCommand
'Database data
Public DBDA As OleDbDataAdapter
Public DT As DataTable
Public DS As DataSet
'Query parameters
Public Params As New List(Of OleDbParameter)
'Query stats
Public RecordCount As Integer
Public Exception As String
Public Sub ExecQuery(Query As String)
'Reset query stats
RecordCount = 0
Exception = ""
Try
'Open database connection
DBCon.Open()
'Create database command
DBCmd = New OleDbCommand(Query, DBCon)
'Load params into database command
Params.ForEach(Sub(x) DBCmd.Parameters.Add(x))
'Clear params list
Params.Clear()
'Execute command and fill database
DS = New DataSet
DT = New DataTable
DBDA = New OleDbDataAdapter(DBCmd)
RecordCount = DBDA.Fill(DS)
DBCon.Close()
Catch ex As Exception
Exception = ex.Message
End Try
'Close connection to database
If DBCon.State = ConnectionState.Open Then DBCon.Close()
End Sub
'Include query and command parameters
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New OleDbParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
Thank you for your time :)

Pass content from a datagridview to another datagridview using a button

Good day.
I am trying to pass all the content of a datagridview from the child form to another datagridview from the parent form in the following way.
I have managed to pass the data through the gridview button, but this time it is only passing me 1 record but I am trying to pass all the records of that datadriview
This is my code that I have implemented.
child form
Private Function BuscarProductos() As DataTable
Dim dt As New DataTable
Try
dt.Columns.Add("IDPRODUCTO")
dt.Columns.Add("DESCRIPCION")
dt.Rows.Add(If(IsDBNull(dgvdetalleproduc.CurrentRow.Cells(0).Value), "", dgvdetalleproduc.CurrentRow.Cells(0).Value),
If(IsDBNull(dgvdetalleproduc.CurrentRow.Cells(0).Value), "", dgvdetalleproduc.CurrentRow.Cells(1).Value))
Catch ex1 As SqlClient.SqlException : MessageBox.Show(ex1.Message, "AUTONORT S.A.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Catch ex As Exception : MessageBox.Show(ex.Message, "AUTONORT S.A.", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Return dt
End Function
add button
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Dim _dataTable As DataTable = BuscarProductos()
Dim estadoOperacion As Boolean = Me.Openerproducs.BusquedadProduct(_dataTable)
'e.Cancel = Not estadoOperacion
Me.Close()
End Sub
and in the parent form it receives it with this method
Public Function BusquedadPRODUC(ByVal dataTableParam As DataTable) As Boolean Implements IFormProduc.BusquedadProduct 'BUSCAR POr afiliado
Try
dgvdetalle.Rows.Add(dataTableParam.Rows(0).Item(0), dataTableParam.Rows(0).Item(1))
'Me.dgvdetalle.Columns.Add(dataTableParam.Rows(0).Item(0))
' txtnomproducto.Text = dataTableParam.Rows(0).Item(1)
'dgvMantenimiento.Rows.Add(dataTableParam.Rows(0).Item(0), dataTableParam.Rows(0).Item(1))
'txtCliente.Text =
'dgvRequerimiento.Rows.Add(If(dgvRequerimiento.Rows(dgvRequerimiento.Rows.Count - 1).Cells(0).Value + 1 <= 9, "00" + (dgvRequerimiento.Rows(dgvRequerimiento.Rows.Count - 1).Cells(0).Value + 1).ToString, "0" + (dgvRequerimiento.Rows(dgvRequerimiento.Rows.Count - 1).Cells(0).Value + 1).ToString), rows.Item(2), rows.Item(3), rows.Item(4), rows.Item(6), rows.Item(5))
'Dim formAdd As New frmLineaCredito
'formAdd.MdiParent = Me.MdiParent
'formAdd.Opener = CType(Me, IFormVH)
'formAdd.Text = "Linea de Credito : " + VGlobales.Empresa
'formAdd.frmLineaCredito(lblCodigoClie.Text.Trim)
'formAdd.Show()
Catch ex1 As SqlClient.SqlException : MessageBox.Show(ex1.Message, "hola", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Catch ex As Exception : MessageBox.Show(ex.Message, "hola", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Return True
End Function
Here's a simple example of what I described in the comments above. Form1 creates and displays two MDI children. One of those child forms raises an event on the Click of a Button that the parent form handles. The parent then pulls the data from that child, pushes it to the other child and then the second child displays that data.
Parent:
Public Class Form1
'Source child form
Private WithEvents f2 As Form2
'Destination child form
Private f3 As Form3
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
f2 = New Form2
f2.MdiParent = Me
f2.Show()
f3 = New Form3
f3.MdiParent = Me
f3.Show()
End Sub
Private Sub f2_DataAvailable(sender As Object, e As EventArgs) Handles f2.DataAvailable
'Pull data from source
Dim table = f2.GetData()
'Push data to destination
f3.SetData(table)
End Sub
End Class
Source child:
Public Class Form2
Private table As DataTable
Public Event DataAvailable As EventHandler
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
table = New DataTable()
With table.Columns
.Add("Number", GetType(Integer))
.Add("Text", GetType(String))
End With
BindingSource1.DataSource = table
DataGridView1.DataSource = BindingSource1
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
OnDataAvailable(EventArgs.Empty)
End Sub
Protected Overridable Sub OnDataAvailable(e As EventArgs)
RaiseEvent DataAvailable(Me, e)
End Sub
Public Function GetData() As DataTable
Return table.Copy()
End Function
End Class
Destination child:
Public Class Form3
Public Sub SetData(table As DataTable)
BindingSource1.DataSource = table
DataGridView1.DataSource = BindingSource1
End Sub
End Class
You can test that code for yourself very easily. Just create a project with three form, make the first an MDI parent, add a DataGridView, a BindingSource and a Button to the second and a DataGridView and a BindingSource to the third and you're good to go.

how to display data from database into separate textbox in a new form, when user clicks an item that is in the listbox

i am making a stock management system as part of my college project. i have a search bar and the result is outputted into a listbox. when the searched product is clicked the user will be taken to a new form where they will be able to view product information such as product name, price, quantity, stock. Also the user can delete and add stock. I have provided a screenshot of how it will look below.
I'm new to Visual Studio, my problem is that i am unsure how to display the product information into the textbox, can someone please help.
This is my code so far in Form4, which is the homepage that contains the search result and listbox.
'Importing System.Data.OleDb, this is needed for connection with database and is needed for database requirements.
Imports System.Data.OleDb
'This is the homepage
Public Class FrmHomePage
'this code runs when the user searches for a certain product - " the search button event"
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles btnSearch.Click
'The code below is used to open the database connection.
Dim con As New OleDbConnection("Provider=Microsoft.jet.oledb.4.0;data source=C:\Users\jacob\Desktop\MS Office\project.mdb")
Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM tblProduct WHERE productID LIKE '" & txtSearch_Bar.Text & "'", con)
con.Open()
Dim sdr As OleDbDataReader = cmd.ExecuteReader()
'This if statement makes sure that the product the user is searching for is inside the database, if it isnt then a "no matches" message is displayed.
If Not sdr.HasRows Then
MessageBox.Show("No Matches")
Exit Sub
End If
'this clears the listbox so, if the user searches same product again, it wouldn't duplicate.
lstbSearchResult.Items.Clear()
'Checking for the item in database and outputting it to the listbox.
While (sdr.Read())
lstbSearchResult.Items.Add(sdr("ProductID"))
End While
'closing the database connection
con.Close()
End Sub
'this private sub is basically a side menu which slides out when the user clicks the button "menu".
'Inside the menu the user will have different options such As settings, About us, And more.
Private Sub btnMenu_Click(sender As System.Object, e As System.EventArgs) Handles btnMenu.Click
PnlSide_Menu.Location = New Point(-183, 0)
Do Until PnlSide_Menu.Location.X = -10
PnlSide_Menu.Location = New Point(PnlSide_Menu.Location.X + 1, 0)
Loop
Do Until PnlSide_Menu.Location.X = 0
PnlSide_Menu.Location = New Point(PnlSide_Menu.Location.X + 1, 0)
Refresh()
System.Threading.Thread.Sleep(20)
Loop
End Sub
'private sub for closing the the side menu/side bar.
Private Sub BtnBack_Click(sender As System.Object, e As System.EventArgs) Handles BtnBack.Click
PnlSide_Menu.Location = New Point(0, 0)
Do Until PnlSide_Menu.Location.X = -170
PnlSide_Menu.Location = New Point(PnlSide_Menu.Location.X - 1, 0)
Refresh()
Loop
Do Until PnlSide_Menu.Location.X = -183
PnlSide_Menu.Location = New Point(PnlSide_Menu.Location.X - 1, 0)
System.Threading.Thread.Sleep(20)
Loop
End Sub
'this is the logout button function.
'when clicked the user will be taken back to the login page.
Private Sub btnLogOut_Click(sender As Object, e As EventArgs) Handles btnLogOut.Click
Me.Close()
FrmLogin.Show()
End Sub
Private Sub lstbSearchResult_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstbSearchResult.SelectedIndexChanged
End Sub
This code below is where i am planning to do the things mentioned above.
'Click event of the result in listbox.
Private Sub lstbSearchResult_Click(sender As Object, e As EventArgs) Handles lstbSearchResult.Click
Dim con As New OleDbConnection("Provider=Microsoft.jet.oledb.4.0;data source=C:\Users\jacob\Desktop\MS Office\project.mdb")
Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM tblProduct WHERE productID LIKE '" & txtSearch_Bar.Text & "'", con)
con.Open()
Dim sdr As OleDbDataReader = cmd.ExecuteReader()
con.Close()
frmProductForm.Show()
End Sub
End Class
I put my explanations in with the code.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles btnSearch.Click
'The code below is used to open the database connection.
'Change Dim to Using - this takes care of disposing of objects you create with the End Using
Using con As New OleDbConnection("Provider=Microsoft.jet.oledb.4.0;data source=C:\Users\jacob\Desktop\MS Office\project.mdb")
'You download every field in the table but you only use the productID field
'the idea with database communication is to get in and out as quickly as possible
'only ask for the data you need
'Your user is actually typing in and searching for a productID?
'A productID in a database is usually an Integer of a Long
'Check what datatype this is. If this is a number, what does it mean to find a number LIKE another number?
Using cmd As OleDbCommand = New OleDbCommand("SELECT * FROM tblProduct WHERE productID LIKE '" & txtSearch_Bar.Text & "'", con)
con.Open()
Using sdr As OleDbDataReader = cmd.ExecuteReader()
'This if statement makes sure that the product the user is searching for is inside the database, if it isnt then a "no matches" message is displayed.
If Not sdr.HasRows Then
MessageBox.Show("No Matches")
Exit Sub
End If
'this clears the listbox so, if the user searches same product again, it wouldn't duplicate.
lstbSearchResult.Items.Clear()
'Checking for the item in database and outputting it to the listbox.
While (sdr.Read())
'Use a class to hold all your Product data
Dim p As New Product
p.ProductID = sdr.GetInt32(0) 'I am just guessing at the order of your fields
p.ProductName = sdr.GetString(1)
p.Price = sdr.GetDouble(2)
p.Section = sdr.GetInt32(3)
p.Supplier = sdr.GetString(4)
lstbSearchResult.Items.Add(p)
End While
End Using
End Using
'closing the database connection
con.Close()
End Using
End Sub
'Click event of the result in listbox.
Private Sub lstbSearchResult_Click(sender As Object, e As EventArgs) Handles lstbSearchResult.Click
'Dim con As New OleDbConnection("Provider=Microsoft.jet.oledb.4.0;data source=C:\Users\jacob\Desktop\MS Office\project.mdb")
'Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM tblProduct WHERE productID LIKE '" & txtSearch_Bar.Text & "'", con)
'con.Open()
'Dim sdr As OleDbDataReader = cmd.ExecuteReader()
'con.Close()
'You just got all this info in Button1.Click
'and it is all saved in your list box
frmProductForm.Show()
Dim p As Product = DirectCast(lstbSearchResult.SelectedItem, Product)
frmProductForm.txtProductName.Text = p.ProductName 'The names of the text boxes are guesses
frmProductForm.txtProductID.Text = p.ProductID
'etc.
End Sub
End Class
Public Class Product
Public Sub New()
'Default constructor
End Sub
Public Sub New(intProductID As Integer, strProductName As String, dblPrice As Double, intCurrentStock As Integer, intSection As Integer, strSupplier As String)
ProductID = intProductID
ProductName = strProductName
Price = dblPrice
CurrentStock = intCurrentStock
Section = intSection
Supplier = strSupplier
End Sub
Private _ProductID As Integer
Public Property ProductID As Integer
Get
Return _ProductID
End Get
Set(value As Integer)
_ProductID = value
End Set
End Property
Private _ProductName As String
Public Property ProductName As String
Get
Return _ProductName
End Get
Set(value As String)
_ProductName = value
End Set
End Property
Private _Price As Double
Public Property Price As Double
Get
Return _Price
End Get
Set(value As Double)
_Price = value
End Set
End Property
Private _CurrentStock As Integer
Public Property CurrentStock As Integer
Get
Return _CurrentStock
End Get
Set(value As Integer)
_CurrentStock = value
End Set
End Property
Private _Section As Integer
Public Property Section As Integer
Get
Return _Section
End Get
Set(value As Integer)
_Section = value
End Set
End Property
Private _Supplier As String
Public Property Supplier As String
Get
Return _Supplier
End Get
Set(value As String)
_Supplier = value
End Set
End Property
Public Overrides Function ToString() As String 'This is what the list box calls to get what to put in its text
Return $"{_ProductID} {_ProductName}"
End Function
End Class

Binding an observable collection to a printer queue

I am trying to monitor a print queue using a Observable Collection however when an item is added to the printer queue it does not updated. am I missing something. Here is my code so far.
Imports System.Printing
Imports System.Text
Imports System.IO
Imports System.Collections
Imports System.Management
Imports System.Drawing.Printing
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Public Class Form1
Dim localPrintServer2 As LocalPrintServer
Dim defaultPrintQueue2 As PrintQueue
Dim listSentToPrinter As New List(Of String)()
Dim listPrinterQueue As New List(Of String)()
Dim listJobsInQueue As New List(Of String)()
' Private m_queueObList As New ObservableCollection(Of String)
Public queueObList As New ObservableCollection(Of String)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler queueObList.CollectionChanged, AddressOf Me.OnCollectionChanged
End Sub
Private Sub OnCollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
Try
Dim obsSender As ObservableCollection(Of String) = TryCast(sender, ObservableCollection(Of String))
Dim editedOrRemovedItems As New List(Of String)()
getPrintQueue()
If e.Action = NotifyCollectionChangedAction.Add Then
MsgBox("Item Added")
'search listSentToPrinter
End If
If e.Action = NotifyCollectionChangedAction.Remove Then
MsgBox("Item Removed")
End If
'Label1.Text = queueObList.Count
Dim action As NotifyCollectionChangedAction = e.Action
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub getPrintQueue()
Try
localPrintServer2 = New LocalPrintServer()
defaultPrintQueue2 = LocalPrintServer.GetDefaultPrintQueue()
Timer1.Enabled = True
Timer1.Interval = 50
Dim jobs As PrintJobInfoCollection = defaultPrintQueue2.GetPrintJobInfoCollection
For Each job As PrintSystemJobInfo In jobs
'listPrinterQueue.Add(job.Name)
queueObList.Add(job.Name)
Label1.Text = queueObList.Count
'lstPrinterQueue.Items.Add(job.Name & " " & job.JobStatus)
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub Iletarerate()
ListBox1.Items.Clear()
For Each item As String In queueObList
ListBox1.Items.Add(item)
Next
End Sub
Public Sub FindJobInQueue(ByVal item As String)
If listJobsInQueue.Contains(item) Then
Else
If (listPrinterQueue.Count >= 1) Then
If listPrinterQueue.Contains(item) Then
lstJobInQueue.Items.Add("Found " & item)
listJobsInQueue.Add(item)
'Update stutus if successfully updated
listSentToPrinter.Remove(item)
End If
Else
' list is empty
End If
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
queueObList.RemoveAt(0)
Iletarerate()
End Sub
End Class
The code works to add everything to the observable collection which is in the queue. The buttons work to add and remove items. The actual print queue does not update the collection

Close form from second form

My first form is login form, when user correctly log in i am hiding login form and showing up second form. Now instead of hiding login form i want to close it from second form. I thought i will be able to do it but somehow i got troubles with it.
So far i did like this below.
I made interface which my FrmLogin implements:
Public Class FrmLogin
Implements ICloseLogin
Interface:
Public Interface ICloseLogin
Sub Close()
End Interface
FrmLogin implementing interface:
Private Sub ICloseLogin_Close() Implements ICloseLogin.Close
Me.Close()
End Sub
Now i am passing FrmLogin (Me) to second form constructor:
Private Sub ShowMainForm()
Dim FrmMain As New FrmMainMDI(Me)
FrmMain.IsMdiContainer = True
FrmMain.StartPosition = FormStartPosition.CenterScreen
FrmMain.Show()
'Me.Hide() 'not anymore
End Sub
Second form:
Public Class FrmMainMDI
Private closeloginfform As ICloseLogin
Sub New(frmlogin As ICloseLogin)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
closeloginfform = frmlogin
End Sub
Private Sub FrmMainMDI_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
closeloginfform.Close()
End Sub
and when i debug and when it comes to line: closeloginfform.Close() i suppose to see only FrmLogin to be closed, but all is closing somehow. Why?
For further discussion:
Imports DataAccessLayer
Imports FormsUtils
Imports BusinessLayer
Imports System.Data.SqlClient
Imports System.Configuration
Imports System.Reflection
Imports System.IO
Imports Microsoft.WindowsAPICodePack.Dialogs
Imports Probix
Public Class FrmLogin
Private Property Form As New FormUtils
Private Property DB As New Procs
Private Property _login As String
Private Property _password As String
Private Sub btnLogin_Click(sender As System.Object, e As System.EventArgs) Handles btnLogin.Click
CheckAccess()
End Sub
Private Sub btnClose_Click(sender As System.Object, e As System.EventArgs) Handles btnClose.Click
Me.Close()
End Sub
Private Sub FrmLogin_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Try
DB.OpenConn()
If DB.conn.State = ConnectionState.Open Then
Call Form.InitCombo(CboLogin, "SELECT * from tbLogin", DB.conn, "Login", "Login")
Call Form.InitCombo(CboLanguage, "SELECT * from tbLanguage where Active = 1", DB.conn, "Language", "Id")
Lang.name = DirectCast([Enum].Parse(GetType(Lang.LangShortcut), CboLanguage.GetItemText(CboLanguage.SelectedItem)), Lang.LangShortcut)
Else
Logger.LogIt(Modules.FrmLogin.ToString & ": " & Methods.FrmLogin_Load.ToString, WriteMsg.Write(IssueCode.SqlServerConnectionError_pl), Application.StartupPath & "\log.txt", False)
Application.Exit()
End If
Catch ex As Exception
Logger.LogIt(ex.tostring)
Application.Exit()
Finally
DB.CloseConn()
End Try
End Sub
Private Sub CheckAccess()
Try
_login = CboLogin.SelectedValue
_password = txtPassword.Text
If Not String.IsNullOrEmpty(txtPassword.Text) And Form.WybranoCombo(CboLogin, "Zaznacz login") Then
Dim strcon = New AppSettingsReader().GetValue("ConnectionString", GetType(System.String)).ToString()
Using con As New SqlConnection(strcon)
Using cmd As New SqlCommand("Select COUNT(*) FROM tbLogin WHERE Login = #Login And Password = #Password", con)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#Login", _login)
cmd.Parameters.AddWithValue("#Password", _password)
con.Open()
Dim o As Integer = cmd.ExecuteScalar()
'--CREDENTIALS OK
If o > 0 Then
CboLogin.Hide()
txtPassword.Hide()
btnLogin.Hide()
Label1.Hide()
Label2.Hide()
Try
Catch ex As Exception
MsgBox(ex.ToString)
End
End Try
'--CREDENTIALS NOT OK !!
Else
MsgBox("Wrong credentials")
End If
End Using
End Using
Else
MsgBox("Write some password !!")
End If
Catch ex As Exception
Logger.LogIt(Modules.FrmLogin.ToString & ":" & Methods.FrmLogin_Load.ToString, WriteMsg.Write(IssueCode.Unknown_pl) & " ------> EX-MESSAGE: " & ex.ToString, Application.StartupPath & " \log.txt", False)
Return
End Try
End Sub
Public Sub taskDialog_Opened(sender As Object, e As EventArgs)
Dim taskDialog As TaskDialog = TryCast(sender, TaskDialog)
taskDialog.Icon = taskDialog.Icon
If Not taskDialog.FooterIcon = TaskDialogStandardIcon.None Then
taskDialog.FooterIcon = taskDialog.FooterIcon
End If
taskDialog.InstructionText = taskDialog.InstructionText
End Sub
End Class
Module Program:
Module Program
Public Sub main()
Application.EnableVisualStyles()
Dim result As DialogResult
Using frmL As New FrmLogin
result = frmL.ShowDialog
End Using
If result = DialogResult.OK Then
Dim FrmMainMDI As New FrmMainMDI()
Application.Run(FrmMain)
End If
End Sub
End Module
Further discussion 2
Solved???: I've added line within CheckAccess() sub, this line:
Me.DialogResult = DialogResult.OK
so this peace of code has been changed only:
...
'--CREDENTIALS OK
If o > 0 Then
CboLogin.Hide()
txtPassword.Hide()
btnLogin.Hide()
Label1.Hide()
Label2.Hide()
Try
'*************************************
Me.DialogResult = DialogResult.OK '<=========================================
'*************************************
Catch ex As Exception
MsgBox(ex.ToString)
End
End Try
'--CREDENTIALS NOT OK !!
Else
MsgBox("Wrong credentials")
End If
...
A less involved way to do this is to start your app from Sub Main and only start the app if the LogIn is correct. For this:
Add a module to your App, and name it Program. Add a Public Sub Main to it
Go to Project Properties and Uncheck Enable Application Framework
Now, for the Startup Object, select "Sub Main"
You can actually name the module anything, "Program" is descriptive and the convention used in C#. Then the Sub Main code:
Public Sub Main()
Application.EnableVisualStyles()
Dim result As DialogResult
Using frmL As New frmLogin
result = frmL.ShowDialog
End Using
If result = DialogResult.OK Then
frmMain = New MainFrm()
Application.Run(frmMain)
End If
End Sub
Now, your two forms don't even have to know about each other. The MainForm will not even exist if/when the login fails. Whatever overhead there is related to starting/Loading the MainForm is also delayed until (and unless) the log in passes.
Your login button would be something like this (depending on how many failed attempts are allowed):
Private Sub btnLogIn_Click(sender As Object, e As EventArgs) Handles btnLogIn.Click
If IsValidUser(tbName.Text, tbPW.Text) Then
DialogResult = Windows.Forms.DialogResult.OK
Else
If tries >= 3 Then
DialogResult = Windows.Forms.DialogResult.Cancel
Else
tries += 1
Exit Sub
End If
End If
Me.Hide()
End Sub