Need some advice on putting data into DataGridView in vb.Net - vb.net

I need a little advice in manipulating DataGridView in Visual Basic .Net. This is my first time playing with DataGridView. My program is to load a .txt file containing data of every room in a building and display them in the DataGridView.
Here is a portion of the file showing 2 rooms:
1;1812;1812;F18;T1;26808.16;.00;.00;.00;.00;.00;.00;
1;1813;1813;F18;T1;24000.00;3500.00;.00;300.00;.00;.00;.00
A room is a one-line string that ends with an endline character.
I have no problem with loading the file and getting all these information. I store data of each room into an object of class Room, and put them in a list.
Right now, I put all of the properties of the room into the data grid's columns like this:
Now, how can I put all these rooms' data into the grid? I tried follow http://www.dotnetperls.com/datagridview-vbnet at first, but setting DataSource to a list of class Room imitating from the given link doesn't show anything in the grid view. How can we tell the program to link rows of the grid to a list of objects? Or am I doing it wrong?
So any advise is appreciated. How do we do this?

I think you'll be pleasantly surprised at how easy this is to do with BindingSources and Visual Studio.
Create your Room Class (already done I presume)
Build your project
Set your Class as your DGV's DataSource:
Click the DGV's smart tag (or the DataSource field in the DGV's property sheet) and on the 'Choose Data Source' pulldown select 'Add Project Data Source...'
On the 'Data Source Config Wizard' select Object and click Next
Navigate your assembly's class structure to select the Class you created in step 1 and click Next
Click Finish to close the Wizard
You'll notice that a new BindingSource has been added to your project. You'll use this BindingSource to bind your List of Room objects to your DGV. Your code will look something like this after you fill your List of Rooms:
roomBindingSource.DataSource = roomList
Note that you'll start with a DataGridView with no columns. After you follow the steps above your DGV will be populated with columns based on the accessibility of the fields in the class you're binding to. At this point you can customize the appearance of the columns such as including removing/adding, etc.

Your problem is that you are using the designer to create your columns and then not linking the DataSource properties to these columns.
The link you posted is talking about automatically generating columns based upon the DataSource which is a list of objects, in that link they do not create the columns in the designer, but instead rely upon the AutoGenerateColumns property being set to true for the DataGridView.
There is a forum post here which talks about what you need to do. It is also described quite well on MSDN.
Basically you need to set the DataPropertyName for each column to match the desired property from your object.
So if your object looks like:
class Room
{
public string RoomName() {get; set;}
}
You need to set the DataPropertyName property to RoomName for the room name column in the grid designer.

Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' Uses Test class from above.
Dim list = New List(Of Test)
list.Add(New Test("Mac", 2200))
list.Add(New Test("PC", 1100))
DataGridView1.DataSource = list
End Sub
Private Sub DataGridView1_SelectionChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles DataGridView1.SelectionChanged
' Get the current cell location.
Dim y As Integer = DataGridView1.CurrentCellAddress.Y
Dim x As Integer = DataGridView1.CurrentCellAddress.X
' Write coordinates to console.
Console.WriteLine(y.ToString + " " + x.ToString)
End Sub
End Class

Related

Needing Assistance with vb.NET Application

I don't normally post on forums because I try to find information for myself, and ask as an absolute last resort. I've tried scouring the net for answers, but I'm only receiving about half of the answer I'm looking for.
I'm currently building an application that deals with state law. There's one combo box and one text box. One for the offense title, and one for the numerical code for that particular code section. So say if I select "Kidnapping", it prepopulates the text box below it with "11-5-77", for example.
The method I've been using for, oh, about the last hour now, is:
If AWOffenseTitle.Text = "Kidnapping" Then
AWCN.Text = "11-5-77"
ElseIf AWOffenseTitle.Text = "False Imprisonment" Then
AWCN.Text = "11-5-78"
With AWOffenseTitle being the combo box name, and AWCN being the text box name. While this has proved to work perfectly well so far, I'm sure you can imagine with hundreds of offense titles, this is going to take a ridiculously long time. Well, I finally found a spreadsheet with offense titles and their respective title codes. What I'm looking to do is create two text files within a folder in the local directory "Offenses". One with a vertical list of offenses, and one with a vertical list of offense code numbers that populate the same lines in each. What I'm looking to do is populate the combo box with the contents of text file one (which I can do already), but then selecting an offense title will read the second text file and display it's proper title code. That's what has me at a loss. I'm relatively well-versed with vb.NET, but I'm not an expert by any means.
I'm hoping someone here will be able to provide a code example and explain it to me line-by-line so I can gain a better understanding. I want to get more proficient with VB although it's not so popular anymore. I've been using VB since 6.0, but not on a regular basis. More on a sporadic project kind of basis.
I really appreciate any assistance anyone might be able to provide, and if you need more information, I'd be glad to answer any questions. I tried to be as thorough as I could.
Thank you in advance!
First, you need to retrieve your data. I demonstrated using an Sql Server database containing a table named Offenses with columns named OffenseTitle and OffenseCode. You will have to change this code to match your situation.
Private Function GetOffenseData() As DataTable
Dim dt As New DataTable
Using cn As New SqlConnection("Your connection string"),
cmd As New SqlCommand("Select OffenseTitle, OffenseCode From Offenses;")
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
As the Form loads, set the properties of the ComboBox. DisplayMember matches the name of the title column and ValueMember is the name of the code column.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = GetOffenseData()
ComboBox1.DisplayMember = "OffenseTitle"
ComboBox1.ValueMember = "OffenseCode"
ComboBox1.DataSource = dt
End Sub
Then when the selected item in the combo changes, just set the .Text property of TextBox to the SelectedValue in the combo and your code appears.
Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
TextBox1.Text = ComboBox1.SelectedValue.ToString
End Sub
There are other ways to do this if your data source is other than a database. Please advise if you need additional help.
In addition to HardCode's comment and Mary's detailed answer, I can only add an answer that's somewhere in between them.
It might be the case, that the information is not taken from a database, but from another source, like a text/data file or a web service. So it might be useful to create an abstraction for the data source you actually use.
First, I create a class or struct that will hold the data for each combo box item.
Class Offense
Public ReadOnly Property Title As String
Public ReadOnly Property Code As String
Public Sub New(title As String, code As String)
Me.Title = title
Me.Code = code
End Sub
End Class
Next, you need a method that retrieves a list of offenses that you can bind to your combo box. It's entirely up to you how you fill/fetch the offenses list. I have simply hard coded your two values here.
Private Function GetOffenseData() As List(Of Offense)
Dim offenses As New List(Of Offense)
offenses.Add(New Offense("Kidnapping", "11-5-77"))
offenses.Add(New Offense("False Imprisonment", "11-5-78"))
Return offenses
End Function
At a certain moment (probably in your form's Load event handler), you need to initialize your combo box. Just like Mary did, I use data binding.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AWOffenseTitle.DropDownStyle = ComboBoxStyle.DropDownList
AWCN.ReadOnly = True
AWOffenseTitle.DisplayMember = NameOf(Offense.Title)
AWOffenseTitle.ValueMember = NameOf(Offense.Code)
AWOffenseTitle.DataSource = GetOffenseData()
End Sub
Note that I use the NameOf operator to get the desired property names of the Offense class. If you ever decide to rename the properties of your Offense class, you will be able to easily detect where they are used, since the compiler will complain if your code still uses the wrong property names somewhere.
Finally, the app needs to react to combo box value changes, so that the text box will show the corresponding offense code. Mary used an event handler for the SelectionChangeCommitted event, but I use a handler for the SelectedIndexChanged event instead:
Private Sub AWOffenseTitle_SelectedIndexChanged(sender As Object, e As EventArgs) Handles AWOffenseTitle.SelectedIndexChanged
AWCN.Text = AWOffenseTitle.SelectedValue
End Sub
(Up to now, I was not aware of the SelectionChangeCommitted event of the ComboBox control. I will need to look into this event to see if it is actually a better choice for this scenario, but I found that the SelectedIndexChanged event does the job just fine, so for now I sticked with that event, since I am more familiar with it.)

Connect Treeview Child Node to Database Details

I'm working with VB.net 2010 & have a Treeview that's being populated from a MySQL table via a Dataset in the Form1_Load.
The treeview loads the test data from the database table fine but I want to be able to click a treeview Child Node & display the matching data from the MySQL table Row inside multiple textbox.
I know I need to have a textbox for each table Cell in a Row but I can't figure out how to connect the table Row ID column to the treeview (child node). My table ID column is named UserID in the screenshot below.
I also know I need to add code to the TreeView1_AfterSelect. I think I might be able to use the treeview node Tag to connect to the table UserID column, but I'm just not sure about the code.
My treeview root node is set in design view.
I only have a Binding Navigator & Datagrid on the Form while testing the treeview/table-details, those will eventually be removed from the Form.
Here's some background on how I'm loading the treeview with my test data from the MySQL table.
Here's some screenshots of my Table data & the VB.NET Form, this site won't let me post images.
MySQL Table Data
VB.NET Form image
I've been trying to get this to work for at least a week with no luck. Any help would be very much appreciated.
Private Sub AddNode(parentNode As String, nodeText As String)
Dim node As New List(Of TreeNode)
node.AddRange(TreeView1.Nodes.Find(parentNode, True))
If Not node.Any Then
'' '' ''This is the Parent Treeview Node
node.Add(TreeView1.Nodes(0).Nodes.Add(parentNode, parentNode))
End If
'' '' ''This is the Child Treeview Node
node.Add(TreeView1.Nodes(0).Nodes(parentNode).Nodes.Add(nodeText, nodeText))
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'Database1DataSet.Table44' table. You can move, or remove it, as needed.
Me.Table44TableAdapter.Fill(Me.Database1DataSet.Table44)
For Each dr As DataRow In Database1DataSet.Table44.Rows
AddNode(dr("ParentNode").ToString, dr("ChildNode").ToString)
Next
TreeView1.ExpandAll()
End Sub
Your database structure doesn't quite make sense to me. Can there be more than one city per state? Or is it always one user and one city. It's not clear.
Anyway, you can use the node's Key parameter to set the Name property, and see what you clicked on:
Private Sub AddNode(parentNode As String, nodeText As String, userID As String)
Dim node As New List(Of TreeNode)
node.AddRange(TreeView1.Nodes.Find(parentNode, True))
If Not node.Any Then
node.Add(TreeView1.Nodes(0).Nodes.Add(parentNode, parentNode))
End If
node.Add(TreeView1.Nodes(0).Nodes(parentNode).Nodes.Add(userID, nodeText))
End Sub
Then in your AfterSelect event, see if your key is a number:
Private Sub TreeView1_AfterSelect(sender As Object, e As TreeViewEventArgs) _
Handles TreeView1.AfterSelect
Dim userID As Integer = 0
If Integer.TryParse(e.Node.Name, userID) Then
' do something with userID
End If
End Sub

my program is not adding items to listbox and is freezing up

im trying to add a very large amount of items to list box and what i need it for is i'm using to add selected items to itextsharp table report im using filters in the table just to display either the sales person who handled the customer or the date at which the incident occurred (or Issue was reported with the product) my filter system is as follows i have 4 categories which is 4 listboxes customer name, customer code(named listBox1 i have not got around to changing it yet) species name, and the error type my filter is placed under the searchBtn_Click event my filter and item adding code is as follows:
Private Sub searchBtn_Click(sender As Object, e As EventArgs) Handles searchBtn.Click
For Each obj As contactObject In custList
For Each item As speciesObject In speciesList
'loadLists()
If Trim(fromDate.Value) < Trim(obj.eventDate) Then
If Trim(toDate.Value) > Trim(obj.eventDate) Then
If Trim(fromDate.Value) < Trim(item.compDate) Then
If Trim(toDate.Value) > Trim(item.compDate) Then
End If
If Not customerListBox.Items.Contains(obj.customerName) Then
customerListBox.Items.Add(obj.customerName)
End If
If Not ListBox1.Items.Contains(obj.customer) Then
ListBox1.Items.Add(obj.customer)
End If
If Not speciesListBox.Items.Contains(item.name) Then
If ListBox1.Items.Contains(item.customerCode) Then
speciesListBox.Items.Add(Trim(item.name).ToUpper)
End If
End If
If Not errorListBox.Items.Contains(obj.issue + " - " + obj.issueDescription) Then
errorListBox.Items.Add(Trim(obj.issue + " - " + obj.issueDescription).ToUpper)
End If
End If
End If
End If
Next
Next
countErrors()
End Sub
then i have the query which is set up to get the customer info from the database system
Dim SqlText As String = "SELECT DISTINCT QEE.[EventID] ,QEE.[EventDate] ,QEE.[Employee] ,QEE.[Communication] ,QEE.[OtherCommunication] ,QEE.[Issue] ,QEE.[IssueDescription] ,QEE.[IssueComments] ,QEE.[Resolution] ,QEE.[ResolutionComments] ,QEE.[SalesOrderNumber] ,QEE.[CustomerPO] ,QEE.[SOStatus] ,QEE.[Customer] ,QEE.[CustomerName] ,QEE.[SalesPersonName] ,QEE.[IsResolved] ,QEE.[IssueValue] ,QEE.[DateAndTimeAdded] ,DATEDIFF(day, SOR.ReqShipDate, QEE.[EventDate]) AS Elapsed, SOR.ReqShipDate FROM [QualityTracking].[dbo].[tblQualityEventEntry] QEE INNER JOIN SysproCompanyC.dbo.SorMaster SOR ON QEE.SalesOrderNumber = SOR.SalesOrder COLLATE Latin1_General_CI_AS ORDER BY EventDate ASC, CustomerName ASC, SalesOrderNumber ASC;"
I could not fit all code on here
if you could also just general things to help as well i am new to vb.net but for other information things i have tried :
*listbox.startUpdate/endUpdate
*changing querys
*changing the sorted property (Right now its set for false)
*the issue happens when i choose select all and then hit search the database is holding almost 2Mil items and i need to be able to get it to move once i get it work stop freezing i will be able to increase the speed i just cant figure out totally where the issue is i know the query could be better probably (if you have any suggestions please feel free i'm learning)
*but i also see alot of people having this issue with listbox as being kinda a broken down way of listing items
*i have tried researching it and people have said use something else i cant do that for listbox is committed
Assuming Windows Forms.
You program might not be responding because of too many records to add, and each time you add an item into the ListBox.Items collection, the UI is refreshed.
You may either SuspendLayout while adding the lines into your Listbox, and ResumeLayout afterwards.
Private Sub searchBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
customerListBox.SuspendLayout();
// Place your code to populate the ListBox control here...
customerListBox.ResumeLayout();
End sub
This shall avoid a lot of refreshes from occuring while adding the items one by one and allow the application to lighten the add of items, then you resume the layout so that it refreshes the controls to display adequate information to the screen.
OR
You may use the ListBox.Items.AddRange() method along with List.ToArray().
Private Sub searchBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim custList As List(Of ConstactObject) = loadYourCustomers();
customerListBox.Items.AddRange(custList.ToArray());
Dim speciesList As List(Of SpeciesObject) = loadYourSpecies();
speciesListBox.Items.AddRange(speciesList.ToArray());
End sub
OR ELSE
I recommend using a DataGridView and setting its DataSource property to your list of objects.
So, in order to have the correct data, you'll have to:
Drop two DataGridView on your Form
Rename both DataGridView to a meaningful name (e.g. custListDataGridView, speciesListDataGridview)
Drop two BindingSource on your Form
Rename both BindingSource to a meaningful name (e.g. custListBindingSource, speciesListBindingSource)
In the designer, set the DataGridView.DataSource property to your respective BindingSource (e.g. custListDataGridview.DataSource = custListBindingsource, speciesListDataGridView.DataSource = speciesListBindingSource)
In the backing code, that is, in your searchBtn.Click event, you may set both your binding sources DataSource property
Private Sub searchBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim custList As IList(Of ContactObject) = loadYourContactObjects();
custListBindingSource.DataSource = custList;
Dim speciesList As IList(Of SpeciesObject) = loadYourSpeciesObject();
speciesListBindingSource.DataSource = speciesList;
End Sub
And your information data should be listed automatically without you having to manually add each record.

How can I keep items in ComboBox after close the application

Public Class Form1
Private Sub btnAddCat_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddCat.Click
If txtAdd.Text <> "" Then
comboBox1.Items.Add(txtAdd.Text)
txtAdd.Clear()
Else
MessageBox.Show("Fill the blanket")
End If
End Sub
End Class
If user close application should see the items but there is no items
Can anyone help?
thanks
If you want the application to remember the value the next time it is run, you will need to save the value to disk. There are many different options for how to do that (e.g. text file, XML, database, registry), but for simple tasks, I'd recommend just using the built-in Settings feature.
To use the Settings feature, first you need to open your project properties screen. Then select the Settings tab. Add a new setting by typing in the name and selecting a data type. For instance, you could type MyItems for the name, and then select System.Collections.Specialized.StringCollection as the data type. Then, in your code, you can read the current value of the setting like this (perhaps in your form's Load event handler):
For Each i As String In My.Settings.MyItems
ComboBox1.Items.Add(i)
Next
And then you could save the list to the setting, like this (perhaps in your form's FormClosed event handler):
My.Settings.MyItems.Clear()
For Each i As String In ComboBox1.Items
My.Settings.MyItems.Add(i)
Next
You need to persist the data to a data store (either the database or the file system) so that the next time the application runs, then it can check the data store and display the items to the user.

Vb.net + AutoComplete in textboxes

So I was reading a bit on AutoComplete of textboxes in VB.NET, but I can't really understand where these are stored? Is it a fully built in feature, or do I have to write some code for it to work? I've found the AutoCompleteMode and AutoCompleteSource properties of textboxes. But I want to append whatever I've written in the textbox to the autocomplete source. Do I connect the source to My.Settings or something? Wouldn't I have to use an array as well? Any help would be appreciated :)
You would have to add new entries to your auto-complete data source manually... which makes sense, when you think about it: How is Windows Forms supposed to know when a new entry should be added to the list of suggestions and when the text entered is only something temporary?
You could add new values e.g. when validation of the input field happens, or when the user presses an OK / Apply button, or whatever fits your need best. But you will have to do this yourself.
The properties you've already discovered are the right ones.
Dim suggestions As New List(Of String)
suggestions.Add("Abba")
suggestions.Add("Nirvana")
suggestions.Add("Rolling Stones")
...
textBox.AutoCompleteSource = suggestions
You can bind AutoCompleteSource to almost anything; this is very similar to data-binding. One thing to keep in mind is that if you're adding new entries to the auto-complete data source, the UI control might not immediately notice if your data source doesn't implement the INotifyCollectionChanged interface.
first create the list to use as the custom source.
Dim MySource As New AutoCompleteStringCollection()
and then set the property of the textbox
With MyTextbox
.AutoCompleteCustomSource = MySource
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.AutoCompleteSource = AutoCompleteSource.CustomSource
End With
put this code in eventlistener you use for validating the input field, e.g. btnOK.Click
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
MySource.Add(txtinput.text)
End Sub