Issue when binding combobox and listbox to List (VB.NET) - vb.net

I'm trying to bind a ComboBox and a ListBox to a List(Of String) in Vb.Net (VS2013), this is for a WinForms application, the thing is that after setting the DataSource property on both the ComboBox and the ListBox, selecting one item on either one of them affects the other control, for example, after the controls have been populated with the information if I select an item from the ListBox, then the same item gets selected in the ComboBox, and this goes the same way for the ComboBox, if I select an item from it, then that item gets also selected in the ListBox, so my question is... how can I bind the combobox and listbox to the same List(Of String) without affecting the behavior on the controls, the purpose is to keep all the controls within that form syncronized based on the contents of the List, I declared the List in a module like this:
Public listaAreas As New List(Of String)
then the controls are populated like this on form load:
cmbArea.DataSource = listaAreas
lstAreas.DataSource = listaAreas
And I run this method whenever I need to update the information:
Private Sub RefreshLists()
lstAreas.DataSource = Nothing
lstAreas.DataSource = listaAreas
cmbArea.DataSource = Nothing
cmbArea.DataSource = listaAreas
End Sub
Please let me know if I'm missing some information, this is my first post but I think it is clear enough so you get the idea of what I'm trying to accomplish here ... =)
Thanks in advance!

Try setting up separate BindingSources and try using a BindingList(Of String) instead of just a List, which won't report item changes:
Private listaAreas As New BindingList(Of String)
Private cbSource As New BindingSource(listaAreas, String.Empty)
Private lbSource As New BindingSource(listaAreas, String.Empty)
Public Sub New()
InitializeComponent()
cmbArea.DataSource = cbSource
lstAreas.DataSource = lbSource
End Sub
The same currency position is being used in your code, but by defining two separate binding sources, each one will have its own position property.

Related

How to save data into database from dynamically created text boxes

I have dynamically created text boxes on flowlayout panel. The text box can be any number. I am trying to save those value(integer) from text box into database. It takes me a day to achieve this, and i am a newbie by the way. Please guide me how to achieve this. Thank you so much. I try to save into List(Of...) collection but it only returns last value.Here is how i am trying to achieve this. I declare shared list of List type in another class called clsHelper.
Private Sub saveIntoList(flp As FlowLayoutPanel)
clsHelper.list = New List(Of String)
For Each tb in flp.Controls
If TypeOf tb Is TextBox Then
txtNo = DirectCast(tb,TextBox)
If txtNo.Name = "txtNo" Then
clsHelper.list.Add(txtNo.Text)
End If
End If
Next
End Sub
FlowLayoutPanel with six text boxes
The problem is probably this If statement. Only the content of the TextBox whose name is "txtNo" is added to your list. The content of other TextBoxes with different names are not added. Remove the If and the content all TextBoxes will be added to your list.
If txtNo.Name = "txtNo" Then
clsHelper.list.Add(txtNo.Text)
End If
If TextBoxes are not all immediate children of the FlowLayoutPanel, you will need to modify your code as follows, to recursively iterate all the controls hierarchy below the FlowLayoutPanel.
Private Sub saveIntoList(flp As FlowLayoutPanel)
clsHelper.list = New List(Of String)
_saveIntoList(flp)
End Sub
Private Sub _saveIntoList(control As Control)
If TypeOf control Is TextBox Then
clsHelper.list.Add(DirectCast(control, TextBox).Text)
Return
End If
For Each child As Control In control.Controls
_saveIntoList(child)
Next
End Sub

How do I do stuff with my form objects from another module?

First of all, Why are forms classes?
But now on to the main question.
I have:
Form1.vb
Module1.vb
On the form there is a textbox, progress bar, labels etc.
I want to be able to change the properties of these objects on my form from module1, but I cant seem to access them.
These things on the form are objects, right? So do they have a certain scope? and how can I change it?
Wait but according to my solution explorer, these things are properties of a class??
But the form shows up when I run the program?? Wouldn't the form class have to be instantiated so that the form1 object is created?
Not that it matters, but here is a snippet from module1
Sub WriteObjectsToCSV()
Dim props As PropertyInfo() = MyCompanies(1).GetType().GetProperties()
Dim sw As StreamWriter =
My.Computer.FileSystem.OpenTextFileWriter(SaveAs, False)
Dim csv As New CsvHelper.CsvWriter(sw)
csv.WriteHeader(Of Company)()
csv.NextRecord()
For Each company In MyCompanies
'>>> want to write to my text box and change my progress bar here <<<
For Each prop In props
csv.WriteField(prop.GetValue(company))
Next
csv.NextRecord()
Next
End Sub
Forms are classes because they are created dynamically. You can instantiate and open the same form class serveral times and leave the instances open at the same time.
VB automatically instantiates the main form.
You can access the open forms through My.Application.OpenForms. The main form is always the first
Dim mainForm As Form1
mainForm = DirectCast(My.Application.OpenForms(0), Form1)
mainForm.txtOutput.Text = "hello"
To be able to access the controls of the form from outside, they must be declared Public or Internal. You can change the access modifier from the properties window (Modifiers property).
Instead, you can also declare a property in the form to make the text accessible outside
Public Property OutputText() As String
Get
Return txtOutput.Text
End Get
Set(ByVal value As String)
txtOutput.Text = value
End Set
End Property
Now you can write this in the module
mainForm.OutputText = "hello"

Making a List(Of ...) from multiple form object

So I'm trying to make a list of more than one type of object, which I done a research on and found out it's, but I also researched into structures and found I can possibly make a use of that instead, but it doesn't return itself as a list.
Imports WinText = System.Windows.Forms.TextBox
Imports WinCombo = System.Windows.Forms.ComboBox
Public Class PSS
Public EntryItems = New List(Of Elements)
Structure Elements
Dim xSchool As WinCombo
Dim xClass As WinCombo
Dim xID As WinCombo
Dim xName As WinText
End Structure
End Class
Edit: So on a form I have a set of ComboBoxes and TextBoxes (about 20 more than on the example here). I want to put them into a list so that when I will be retrieving their results, or getting their names for SQL references, or anything similar, I will be able put them into a loop, thus making the code more efficient and shorter to do.
Structure has similarities to Class and is not a list.
(Read more about here)
You can create a List(Of Structure) but you need to populate it first, like djv stated already in comments.
Private Sub Populate()
Dim list As New List(Of Elements)
list.Add(New Elements)
'Add as much Elements as you want
End Sub
Assuming your Controls are placed on a Form named Form1.
For Each ctrl As Control In Form1.Controls
If TypeOf ctrl Is TextBox Then
Dim tb As TextBox = DirectCast(ctrl, TextBox)
'Do whatever you want with the current TextBox
ElseIf TypeOf ctrl Is ComboBox Then
Dim chk As ComboBox = DirectCast(ctrl, ComboBox)
'Do whatever you want with the current ComboBox
End If
Next
At first, credits to MatSnow.
Taking his concept of As Control I was able to make a List(Of Control) which allowed me to make and add items to it.
Dim ControlList As New List(Of Control)
ControlList.Add(ComboBox1)
ControlList.Add(TextBox1)
'And so on

Programmatically Change the text of a Combox

I have a user form with a combobox, with 5 unbound data items. The value of each item is of the following format: "## Explanation", a 2-digit numeric code and an explanation of the code. After the user selects an item, I would like to have the 2-digit numeric code displayed only. I have tried the following
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
ComboBox1.Text = Mid(ComboBox1.Text, 1, 2)
End Sub
However after selecting an item, the assignment doesn't seem to be working properly because ComboBox1.Text remains unchanged. Any ideas? Thanks in advance
To me, it sounds that you are not really using combo box to full potential. Looks like you want to have items with multiple pieces of info, which you're trying to combine. But here what you can do instead
Private Class ComboItem
Public Property Code As Integer
Public Property Description As String
Public ReadOnly Property Display As String
Get
Return Code & " " & Description
End Get
End Property
End Class
Dim lst As New List(Of ComboItem)()
lst.Add(New ComboItem()....) ' add your items
cboList.DataSource = lst
cboList.DisplayMember = "Display"
cboList.ValueMember = "Code"
Here where the best part starts - once user selects an item, by typing or clicking, you can do this
Dim item As ComboItem = DirectCast(cboList.SelectedItem, ComboItem)
txtCode.Text = item.Code
txtDescription.Text = item.Description
I feel, this is what you really need.
You would have to change the value in the combobox's Items collection. If you just change the Text property this is what happens:
Setting the Text property to null or an empty string ("") sets the SelectedIndex to -1. Setting the Text property to a value that is in the Items collection sets the SelectedIndex to the index of that item. Setting the Text property to a value that is not in the collection leaves the SelectedIndex unchanged.

how to reference to data from listviews on different tabpages?

i have several tabpages in one tabcontrol, each contains nothing but a listview. I need to get the data/items from the listview in the selected tab. My problem is, I can't refer to the listview. I tried
exportpath = TabControl1.SelectedTab.Controls(0).
but at this point, the IDE doesn't know that there's a listview, so I can't choose the
.items(i).tostring
The variables to create the tabpage and the listviews are already overwritten at this moment. Do you think I should choose another way to create the tabs and the listview (maybe create a list(of listviews) to remember the stuff), or is there a way close to my example try?
Best regards, Jan
dim lst as listview = TabControl1.SelectedTab.Controls(0)
dim exportpath as string = lst.items(i).tostring
? Would that work.
edit: assuming the listview is the only control you have there.
I wouldn't load the control based off index in the collection.
I'm assuming since you are trying to access these dynamically you are also creating them dynamically?
Add a tag that can be referenced on the control or use the same naming convention. listview for the name ie MainListView# where # is just incremented or just assign all the tags on the listview to something consistent.
Then use helper function to loop through the controls collection for that tab and find the actual control.
Then loop through the collection of controls and find the one you want to target.
Dim lstView As ListView = ControlNameStartsWith(TabControl1.SelectedTab, "MainListView")
lstView.Items.Add("test")
FUNCTIONS:
Function ControlByTag(ByRef parent As Control, ByVal tag As String)
For Each Cntl As Control In parent.Controls
If Cntl.Tag.ToString.ToLower = tag.ToLower Then
Return Cntl
Exit For
End If
Next
Return Nothing
End Function
Function ControlNameStartsWith(ByRef parent As Control, ByVal likePhrase As String)
For Each Cntl As Control In parent.Controls
If Cntl.Name.ToLower.StartsWith(likePhrase.ToLower) Then
Return Cntl
Exit For
End If
Next
Return Nothing
End Function
Function ControlByName(ByRef parent As Control, ByVal name As String)
For Each Cntl As Control In parent.Controls
If Cntl.Name.ToLower = name.ToLower Then
Return Cntl
Exit For
End If
Next
Return Nothing
End Function