I search how to use Autocomplete [contains instead of starting with] in winform TextBox but apparently no such result that I want appear.
So I try this code here , no error but it wont appear. Am I missing something?
Private Sub txtSelection_TextChanged(sender As Object, e As EventArgs) Handles txtSelection.TextChanged
Dim suggestions As New AutoCompleteStringCollection()
Dim str As String = txtSelection.Text
... 'get dtselection from mysql'
For i As Integer = 0 To dtSelection.Rows.Count - 1
If dtSelection.Rows(i).Item(1).ToString().ToLower.Contains(str.ToLower) Then
suggestions.Add(dtSelection.Rows(i).Item(1).ToString())
End If
Next
txtSelection.AutoCompleteMode = AutoCompleteMode.Suggest
txtSelection.AutoCompleteSource = AutoCompleteSource.CustomSource
txtSelection.AutoCompleteCustomSource = suggestions
End Sub
I am running code to read text from pdf files and than create a WordCloud. To inform the user the process is on going I add a BackgroundWorker to my form that shows an image saying Loading. I get an error for operating across different threads.
Private Sub ButtonCreate_Click(sender As Object, e As EventArgs) Handles ButtonCreate.Click
bTextEmpty = False
ListView1.Items.Clear()
ResultPictureBox.Image = Nothing
If ListBox1.SelectedIndex > -1 Then
For Each Item As Object In ListBox1.SelectedItems
Dim ItemSelected = CType(Item("Path"), String)
Dim myTempFile As Boolean = File.Exists(ItemSelected + "\Words.txt")
If myTempFile = False Then
'when we load the form we first call the code to count words in all files in a directory
'lets check if the folder exists
If (Not System.IO.Directory.Exists(ItemSelected)) Then
Dim unused = MsgBox("The archive " + ItemSelected.Substring(ItemSelected.Length - 5, Length) + " was not found",, Title)
Exit Sub
Else
Call CreateWordList(ItemSelected)
End If
End If
'if the words file is empty we cant create a cloud so exit the sub
If bTextEmpty = True Then Exit Sub
'then we fill the wordcloud and Listview from the created textfile
Call CreateMyCloud(ItemSelected + "\Words.txt")
Next
Else
Dim unused = MsgBox("You have to choose an Archive to create the Word Cloud",, Title)
End If
Size = New Drawing.Size(1400, 800)
End Sub
I put above code in a Private Sub and called it from my BackgroundWorker. The error occured at this line: If ListBox1.SelectedIndex > -1 Then
After trying the suggested code I get the same error again:
Public Sub CreateMyCloud(ByVal sourcePDF As String)
Dim WordsFreqList As New List(Of WordsFrequencies)
For Each line As String In File.ReadLines(sourcePDF)
Dim splitText As String() = line.Split(","c)
If splitText IsNot Nothing AndAlso splitText.Length = 2 Then
Dim wordFrq As New WordsFrequencies
Dim freq As Integer
wordFrq.Word = splitText(0)
wordFrq.Frequency = If(Integer.TryParse(splitText(1), freq), freq, 0)
WordsFreqList.Add(wordFrq)
End If
Next
If WordsFreqList.Count > 0 Then
' Order the list based on the Frequency
WordsFreqList = WordsFreqList.OrderByDescending(Function(w) w.Frequency).ToList
' Add the sorted items to the listview
WordsFreqList.ForEach(Sub(wf)
error -> ListView1.Items.Add(New ListViewItem(New String() {wf.Word, wf.Frequency.ToString}, 0))
End Sub)
End If
Dim wc As WordCloudGen = New WordCloudGen(600, 400)
Dim i As Image = wc.Draw(WordsFreqList.Select(Function(wf) wf.Word).ToList, WordsFreqList.Select(Function(wf) wf.Frequency).ToList)
ResultPictureBox.Image = i
End Sub
Should look something more like:
Private Sub ButtonCreate_Click(sender As Object, e As EventArgs) Handles ButtonCreate.Click
If ListBox1.SelectedItems.Count > 0 Then
Dim data As New List(Of Object)
For Each Item As Object In ListBox1.SelectedItems
data.Add(Item)
Next
bTextEmpty = False
ListView1.Items.Clear()
ResultPictureBox.Image = Nothing
BackgroundWorker1.RunWorkerAsync(data)
Else
MessageBox.Show("You have to choose an Archive to create the Word Cloud",, Title)
End If
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim data As List(Of Object) = DirectCast(e.Argument, List(Of Object))
For Each Item As Object In data
Dim ItemSelected = CType(Item("Path"), String)
Dim myTempFile As Boolean = File.Exists(ItemSelected + "\Words.txt")
If myTempFile = False Then
'when we load the form we first call the code to count words in all files in a directory
'lets check if the folder exists
If (Not System.IO.Directory.Exists(ItemSelected)) Then
MessageBox.Show("The archive " + ItemSelected.Substring(ItemSelected.Length - 5, Length) + " was not found",, Title)
Exit Sub
Else
Call CreateWordList(ItemSelected)
End If
End If
'if the words file is empty we cant create a cloud so exit the sub
If bTextEmpty = True Then Exit Sub
'then we fill the wordcloud and Listview from the created textfile
Call CreateMyCloud(ItemSelected + "\Words.txt")
Next
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Size = New Drawing.Size(1400, 800)
End Sub
To fix the error in your second, edited post:
WordsFreqList.ForEach(Sub(wf)
ListView1.Invoke(Sub()
ListView1.Items.Add(New ListViewItem(New String() {wf.Word, wf.Frequency.ToString}, 0))
End Sub)
End Sub)
You cannot simply access controls outside of the current thread. You first need to call the Invoke method on the target control and then pass a delegate containing the instructions intended to modify the control outside of the current thread. See this article on MSDN on how to do this: https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls?view=netframeworkdesktop-4.8
I'm creating an inventory management system where the data is stored in a text file. I'm able to save data to the text file, however on the tracker screen it should show current inventory such as: Manufacturer, Processor, Video, Form, RAM, etc. However, all my text boxes remain blank and I'm not sure why. It's not reading properly or updating the text.
frmTracker.vb
Private Sub txtManufacturer_TextChanged(sender As Object, e As EventArgs) Handles txtManufacturer.TextChanged
Dim objMyStreamReader = System.IO.File.OpenText("inventory.txt")
Dim strInventory = objMyStreamReader.ReadLine()
objMyStreamReader.Close()
txtManufacturer.AppendText(strInventory)
End Sub
This is how I'm currently saving the data to the text file.
frmItemEntry.vb
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim objMyStreamReader As System.IO.StreamReader
Dim objMyStreamWriter As System.IO.StreamWriter = System.IO.File.CreateText("inventory.txt")
Dim strInventory As String
objMyStreamWriter.WriteLine(txtManufacturerEntry.Text)
objMyStreamWriter.WriteLine(txtProcessorEntry.Text)
objMyStreamWriter.WriteLine(txtVideoEntry.Text)
objMyStreamWriter.WriteLine(txtFormEntry.Text)
objMyStreamWriter.WriteLine(txtRamEntry.Text)
objMyStreamWriter.WriteLine(txtVramEntry.Text)
objMyStreamWriter.WriteLine(txtHdEntry.Text)
objMyStreamWriter.WriteLine(chkWirelessEntry.CheckState)
objMyStreamWriter.Close()
Me.Close()
End Sub
Example from inventory.txt
Dell
i5
Nvidia
Desktop
8
4
600
0
To be honest, controls should never be used as the primary store for your data in a program. You should really be creating a class and a list of that class to store your data.
You can then read your data into the list from your file, and then, display it from there in your form.
There are several ways of navigating through the data and saving updates. The suggestion below uses buttons for next item and previous item, and a button to save update the file.
It's all pretty self explanatory, but if there's something your not sure about, please have a google and learn something new :-D
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ReadDataFile()
DisplayItem(0)
End Sub
Private Class InventoryItem
Public Property Manufacturer As String
Public Property Processor As String
Public Property Video As String
Public Property FormFactor As String
Public Property Ram As String
Public Property VRam As String
Public Property Hd As String
Public Property Wireless As CheckState
Public Sub New()
Manufacturer = ""
Processor = ""
Video = ""
FormFactor = ""
Ram = ""
VRam = ""
Hd = ""
Wireless = CheckState.Unchecked
End Sub
End Class
Dim Inventory As New List(Of InventoryItem)
Dim currentItemIndex As Integer
Private Sub ReadDataFile()
Using objMyStreamReader As New StreamReader("k:\inventory.txt")
Do Until objMyStreamReader.EndOfStream
Dim newItem As New InventoryItem
newItem.Manufacturer = objMyStreamReader.ReadLine()
newItem.Processor = objMyStreamReader.ReadLine()
newItem.Video = objMyStreamReader.ReadLine()
newItem.FormFactor = objMyStreamReader.ReadLine()
newItem.Ram = objMyStreamReader.ReadLine()
newItem.VRam = objMyStreamReader.ReadLine()
newItem.Hd = objMyStreamReader.ReadLine()
Dim wirelessValue As String = objMyStreamReader.ReadLine()
If wirelessValue = "0" Then
newItem.Wireless = CheckState.Unchecked
ElseIf wirelessValue = "1" Then
newItem.Wireless = CheckState.Checked
End If
Inventory.Add(newItem)
Loop
End Using
End Sub
Private Sub SaveDataFile()
Using objMyStreamWriter As New System.IO.StreamWriter("k:\inventory.txt", False)
For Each item As InventoryItem In Inventory
objMyStreamWriter.WriteLine(item.Manufacturer)
objMyStreamWriter.WriteLine(item.Processor)
objMyStreamWriter.WriteLine(item.Video)
objMyStreamWriter.WriteLine(item.FormFactor)
objMyStreamWriter.WriteLine(item.Ram)
objMyStreamWriter.WriteLine(item.VRam)
objMyStreamWriter.WriteLine(item.Hd)
If item.Wireless = CheckState.Checked Then
objMyStreamWriter.WriteLine("1")
Else
objMyStreamWriter.WriteLine(0)
End If
Next
End Using
End Sub
Private Sub DisplayItem(index As Integer)
With Inventory(index)
txtManufacturerEntry.Text = .Manufacturer
txtProcessorEntry.Text = .Processor
txtVideoEntry.Text = .Video
txtFormEntry.Text = .FormFactor
txtRamEntry.Text = .Ram
txtVramEntry.Text = .VRam
txtHdEntry.Text = .Hd
chkWirelessEntry.CheckState = .Wireless
End With
End Sub
Private Sub BtnUpdateItem_Click(sender As Object, e As EventArgs) Handles BtnUpdateItem.Click
With Inventory(currentItemIndex)
.Manufacturer = txtManufacturerEntry.Text
.Processor = txtProcessorEntry.Text
.Video = txtVideoEntry.Text
.FormFactor = txtFormEntry.Text
.Ram = txtRamEntry.Text
.VRam = txtVramEntry.Text
.Hd = txtHdEntry.Text
.Wireless = chkWirelessEntry.CheckState
End With
SaveDataFile()
End Sub
Private Sub BtnPreviousItem_Click(sender As Object, e As EventArgs) Handles BtnPreviousItem.Click
If currentItemIndex > 0 Then
currentItemIndex -= 1
DisplayItem(currentItemIndex)
End If
End Sub
Private Sub BtnNextItem_Click(sender As Object, e As EventArgs) Handles BtnNextItem.Click
If currentItemIndex < Inventory.Count - 1 Then
currentItemIndex -= 1
DisplayItem(currentItemIndex)
End If
End Sub
First change the format of your text file.
Dell,i5,Nvidia,Desktop,8,2,600,True
Acer,i7,Intel,Desktop,16,4,1GB,True
HP,Pentium,Diamond Viper,Desktop,4,2,200,False
Surface Pro,i7,Intel,Laptop,8,2,500,True
Each line is a record and each field in the record is separated by a comma (no spaces so we don't have to .Trim in code) (a space within a field is fine, notice Surface Pro).
Now it is easier to read the file in code.
This solution uses a BindingSource and DataBindings. This simplifies Navigation and editing and saving the data.
Public Class Form5
Private bs As BindingSource
Private dt As New DataTable
#Region "Set Up the Form"
Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddColumnsToDataTable()
FillDataTable()
AddDataBindings()
End Sub
Private Sub AddColumnsToDataTable()
'Prepare the DataTable to hold data
dt.Columns.Add("Manufacturer", GetType(String))
dt.Columns.Add("Processor", GetType(String))
dt.Columns.Add("Video", GetType(String))
dt.Columns.Add("Form", GetType(String))
dt.Columns.Add("RAM", GetType(String))
dt.Columns.Add("VRAM", GetType(String))
dt.Columns.Add("HD", GetType(String))
dt.Columns.Add("Wireless", GetType(Boolean))
End Sub
Private Sub FillDataTable()
'ReadAllLines returns an array of the lines in a text file
'inventory.txt is stored in the bin\Debug folder of your project
'This is the current directory so it does not require a full path.
Dim lines = File.ReadAllLines("inventory.txt")
'Now it is easy to split each line into fields by using the comma
For Each line As String In lines
'Split returns an array of strings with the value of each field
Dim items = line.Split(","c)
'Each item in the array can be added as a field to the DataTable row
dt.Rows.Add(items(0), items(1), items(2), items(3), items(4), items(5), items(6), CBool(items(7)))
'Notice that the last element is changed from a string to a boolean. This is
'the Wireless field which is bound to the check box. The string "True" or "False" is
'changed to a Boolean so it can be used as the .Checked property (see bindings)
Next
End Sub
Private Sub AddDataBindings()
'Create a new instance of the BindingSource class
bs = New BindingSource()
'Set the DataSource to the DataTable we just filled
bs.DataSource = dt
'Now you can set the bindings of each control
'The .Add method takes (Name of Property to Bind, the BindingSource to use, The Field name
'from the DataTable.
txtForm.DataBindings.Add("Text", bs, "Form")
txtHd.DataBindings.Add("Text", bs, "HD")
txtManufacturer.DataBindings.Add("Text", bs, "Manufacturer")
txtProcessor.DataBindings.Add("Text", bs, "Processor")
txtRam.DataBindings.Add("Text", bs, "RAM")
txtVideo.DataBindings.Add("Text", bs, "Video")
txtVram.DataBindings.Add("Text", bs, "VRAM")
'Notice on the CheckBox we are using the Checked property.
chkWireless.DataBindings.Add("Checked", bs, "Wireless")
End Sub
#End Region
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
'Add a blank row to the DataTable
'A Boolean is like a number, a String can be Nothing but a Boolean must
'have a value so we pass in False.
dt.Rows.Add(Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, False)
'Find the position of the last row
Dim i As Integer = bs.Count - 1
'Move to the new empty row
bs.Position = i
End Sub
#Region "Navigation Code"
Private Sub btnPrevious_Click(sender As Object, e As EventArgs) Handles btnPrevious.Click
'The binding source Position determins where in the data you are
'It starts at zero
If bs.Position = 0 Then
MessageBox.Show("This is the first item.")
Return 'This exits the sub, you can use Exit Sub in vb
'but Return is common in other languages so it is good to learn
Else
'As the position of the BindingSource changes the boud TextBoxes
'change their data.
bs.Position = bs.Position - 1
End If
End Sub
Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click
' If you are not at the end of the list, move to the next item
' in the BindingSource.
If bs.Position + 1 < bs.Count Then
bs.MoveNext()
' Otherwise, move back to the first item.
Else
bs.MoveFirst()
End If
End Sub
#End Region
#Region "Save the Data"
Private Sub SaveDataTable()
'Resave the whole file if this was a real app you would use a database
Dim sb As New StringBuilder
'A string builder keeps the code from creating lots of new strings
'Strings are immutable (can't be changed) so every time you think you are
'changing a string, you are actually creating a new one.
'The string builder is mutable (changable)
For Each row As DataRow In dt.Rows
'The ItemsArray returns an array of objects containing all the
'values in each column of the data table.
Dim rowValues = row.ItemArray
'This is a bit of Linq magic that turns the values (objects) into strings
'Underneath it is performing a For loop on each object in the array
Dim strRowValues = From o In rowValues
Select Convert.ToString(o)
'Now that we have strings we can use the String.Join with the comma
'to get the format of the text file
sb.AppendLine(String.Join(",", strRowValues))
Next
'Finally we change the StringBuilder to a real String
'The inventory.txt is stored in the bin\Debug directory so it is current directory
'no additional path required
File.WriteAllText("inventory.txt", sb.ToString)
End Sub
Private Sub Form5_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
'Because our binding is two-way any additions or changes to the text
'in the text boxes or check box are reflected in the DataTable.
SaveDataTable()
End Sub
#End Region
End Class
Once you remove the comments, there is really very little code here. The #Region...#End Region tags make it easy to collapse code sections you are not working on and find areas quickly.
Here is my code :
I'm trying to have some value out from a TXT file to a combobox or label but i feel combobox would be easier.
here's my code :
please note, some config.txt will only have 1 value while other 5-6
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim IDinFile As String
Dim ID As String
If IO.File.Exists("config.txt") Then
Using StreamReader As New IO.StreamReader("config.txt")
Do
IDinFile = StreamReader.ReadLine
If (IDinFile.IndexOf("7656")) <> -1 Then
ID = IDinFile.Substring(2)
ID = ID.Trim().Remove(ID.Length - 1)
ComboBox1.Items.Add(ID)
Exit Do
End If
Loop Until IDinFile Is Nothing
End Using
End If
End Sub
the file here in .png :
https://i.stack.imgur.com/iYaqP.png
Re-written the code for you. Problem was wrongly placed Exit Do. Also, its advisable to check the line before entering the loop rather than at the end of the loop.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim IDinFile As String
Dim ID As String
Const FILENAME As String = "config.txt"
If IO.File.Exists(FILENAME) Then
Using StreamReader As New IO.StreamReader(FILENAME)
Do While StreamReader.Peek() >= 0
IDinFile = StreamReader.ReadLine.Trim()
If (IDinFile.IndexOf("7656")) <> -1 Then
ID = IDinFile.Substring(1, IDinFile.Length - 2)
ComboBox1.Items.Add(ID)
End If
Loop
End Using
End If
End Sub
After you add the first item to the combobox you have an Exit Do statement. It no longer continues checking further lines and adding them to the combobox.
You should remove that statement.
Try this. It'll work if the values are organized line by line in the txt file.
Dim srd as New StreamReader("config.txt")
If io.file.exists("config.txt") then
Dim str() = srd.ReadToEnd.split(environment.newline)
For i = 0 to str.count-1
Combobox.item.add(str(i))
Next
srd.close
I'm trying to pick up a combo box's selected index. This was working absolutely fine, then all of a sudden it started returning -1 no matter what item is selected
My code is:
Form Code
Private Sub Man_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Man.SelectedIndexChanged, Units.SelectedIndexChanged
'Set Transducer Type
Call References.LevListAdd()
End Sub
References Module LevListAdd Sub
Public Sub LevListAdd()
Form1.Lev.Items.Clear()
If Form1.Man.Text = "Pulsar" Then
With Form1.Lev.Items
.Add("Ultra Range")
.Add("IMP Range")
.Add("Twin Range")
End With
End If
End Sub
This fills the combo box lev fine when the Man combo box item "Pulsar" is selected. I then want my users to click a button to generate some labels and stuff. The code is as such:
Button Click Code
Private Sub Generate_Click(sender As Object, e As EventArgs) Handles Generate.Click
If CheckGenerate() = False Then Exit Sub
Dim X = CheckGenerationType(Man.SelectedIndex, Lev.SelectedIndex, Level.Checked, Volume.Checked, ListBox1.SelectedIndex,
Units.SelectedIndex)
Call ParamPage(X)
End Sub
CheckGenerate simply checks that all boxes have been filled in. I pass the informtion from the form to the following function:
Public Function CheckGenerationType(Man As Integer, Lev As Integer, Level As Boolean, Volume As Boolean, TankType As Integer,
MeasurementUnit As Integer) As String
Dim M As Integer
Dim L As Integer
Dim CT As Integer
Dim TT As Integer
Dim Ms As Integer
M = Man
L = Lev
TT = TankType
Ms = MeasurementUnit
If Level = True Then
CT = 0
ElseIf Volume = True Then
CT = 1
End If
CheckGenerationType = CStr(M) + "." + CStr(L) + "." + CStr(CT) + "." + CStr(TT) + "." + CStr(Ms)
End Function
When the lev.selectedindex parameter arrives at this function, it reads -1. Even if the user has selected any of the 3 items. Can anyone explain why this is happening?
I've just tried your code. I get the same result (-1 in lev.SelectedIndex) and this was because jumped using tab through the controls my when i'm hitting the Man or Units Combobox it runs the LevListAdd() and then clears the Lev-ComboBox because of Form1.Lev.Items.Clear().
You should think about your call Man_SelectedIndexChanged_1 or maybe just use something like this:
Public Sub LevListAdd()
If Form1.Man.Text = "Pulsar" Then
Form1.Lev.Items.Clear()
instead of
Public Sub LevListAdd()
Form1.Lev.Items.Clear()
If Form1.Man.Text = "Pulsar" Then
And you should separate the calls from the man and unit ComboBoxes.
Private Sub Unit_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Units.SelectedIndexChanged
' Do something
End Sub
Private Sub Man_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Man.SelectedIndexChanged
Form1.Lev.Items.Clear()
Select Case Form1.Man.Text
Case "Pulsar"
With Form1.Lev.Items
.Add("Ultra Range")
.Add("IMP Range")
.Add("Twin Range")
End With
Case "animals"
With Form1.Lev.Items
.Add("dogs")
.Add("cats")
.Add("birds")
End With
End Select
End Sub