0

Trying to read a .txt file , put items to list, then on textbox change compare if the string exists in the list. Finally write the new list on the same .txt file.

Public Class Form1

Dim stockList As New List(Of String)
private sub
ListBox1.Items.AddRange(IO.File.ReadAllLines("C:\Users\path\file.txt"))
end sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles 
TextBox1.ReadOnlyChanged

    Dim text As String = TextBox1.Text
    If TextBox1.Text <> "TRAINING" Then
        For Each item As Object In ListBox1.Items
            If item.ToString = text Then
                MsgBox("This code has already been used.", 0, "cheat attempt violation") ' Else alert the user that item already exist
            Else
                ListBox1.Items.Add(TextBox1.Text)

            End If
        Next
    End If
    IO.File.WriteAllLines("C:\Users\path\file.txt", ListBox1.Items.Cast(Of String).ToArray)
End Sub

1 Answers1

0

Instead of using a UI control to store data, you should store the data in a variable. I'm not sure if you really need to show the data in a ListBox, so in the following example code I didn't.

If you use a List(Of String) instead of an array of strings, it is simpler to add another item before saving it.

The Contains method I used in the example can take a second parameter which does the comparison of the item - I guessed that you might want to ignore the case (e.g. "ABC" is the same as "aBc") so I used StringComparer.CurrentCultureIgnoreCase.

I suspect that you want to use the Control.Validating Event instead of the TextChanged event. When the data has been validated, the Control.Validated event handler is used to save it.

I put one TextBox and one Button on the form, so that the focus could change away from the TextBox, e.g. when pressing tab, to fire the validating event.

Imports System.IO

Public Class Form1

    Dim dataFile As String = "C:\temp\grains.txt"
    Dim alreadyUsed As List(Of String) = Nothing

    Sub LoadAlreadyUsed(filename As String)
        'TODO: Add exception checking, e.g., the file might not exist.
        alreadyUsed = File.ReadAllLines(filename).ToList()

    End Sub

    Sub SaveAlreadyUsed(filename As String)
        File.WriteAllLines(dataFile, alreadyUsed)

    End Sub

    Function CodeIsAlreadyUsed(newCode As String) As Boolean
        Return alreadyUsed.Contains(newCode, StringComparer.CurrentCultureIgnoreCase)
    End Function

    Private Sub TextBox1_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating
        ' Do nothing if the user has clicked the form close button
        ' See https://stackoverflow.com/questions/15920770/closing-the-c-sharp-windows-form-by-avoiding-textbox-validation
        If Me.ActiveControl.Equals(sender) Then
            Exit Sub
        End If

        Dim txt = DirectCast(sender, TextBox).Text

        If CodeIsAlreadyUsed(txt) Then
            MessageBox.Show("This code has already been used.", "Cheat attempt violation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            e.Cancel = True
        End If

    End Sub

    Private Sub TextBox1_Validated(sender As Object, e As EventArgs) Handles TextBox1.Validated
        ' The Validated event is raised before the FormClosing event.
        ' We do not want to save the data when the form is closing.
        If Me.ActiveControl.Equals(sender) Then
            Exit Sub
        End If

        Dim txt = DirectCast(sender, TextBox).Text
        alreadyUsed.Add(txt)
        SaveAlreadyUsed(dataFile)

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        LoadAlreadyUsed(dataFile)

    End Sub

End Class
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • @GiannisStefanidis I have updated the code to put the saving into the Validated event handler, which is where it should be. – Andrew Morton Sep 19 '20 at 08:12