Try to read text , put on list , then compare on list and finally replace txt file - vb.net

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

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

Related

VB: Populate a textbox with popup from txt

I am creating a vb file, and I have a txt file with some that I want to populate a textbox.
What it is currently doing: It is choosing an option that i input in the textbox that I have created.
What I want it to do: Create a popup with every option from a textbox file, show it on screen, let me choose, and then populate another textbox with my choice.
Current code and screenshot:
Public Class Form1
Private Sub TextBox1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseClick
Dim f As New Form2
Try
f.Owner = Me
'
' Before showing the child form populate TextBoxes
'
f.TextBox1.Text = "1"
f.TextBox2.Text = "2"
f.TextBox3.Text = "3"
If f.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim Box = (From T In f.Controls.OfType(Of TextBox)()
Where Not String.IsNullOrWhiteSpace(T.Text)
Select T Order By T.Name).FirstOrDefault
If Box IsNot Nothing Then
Me.TextBox1.Text = Box.Text
End If
End If
Finally
f.Dispose()
End Try
End Sub
End Class
Form 2
Public Class Form2
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim Box = (From T In Controls.OfType(Of TextBox)()
Where Not String.IsNullOrWhiteSpace(T.Text)
Select T Order By T.Name).FirstOrDefault
If Box IsNot Nothing Then
CType(Me.Owner, Form1).TextBox1.Text = Box.Text
End If
CType(Me.Owner, Form1).ActiveControl = CType(Me.Owner, Form1).cmdClose
Close()
End Sub
End Class
Image:
edit: now i only need to make the checkbox into locked textboxes, one line from the text file each.

simple dialog like msgbox with custom buttons (vb)

I want to ask user for example "Do you want to go right or left?".
To have simple Code I use MSGBOX with a prompt like:
"Do you want to go right or left"
Press "YES for 'right' / NO for 'left'"
Then I process Yes/No/Cancel that was pressed. This works but is ugly and in some cases hard to understand.
Also in Addition in some cases I have more than 2 choices - but that is probable another question...
You can create one dynamically
Public Module CustomMessageBox
Private result As String
Public Function Show(options As IEnumerable(Of String), Optional message As String = "", Optional title As String = "") As String
result = "Cancel"
Dim myForm As New Form With {.Text = title}
Dim tlp As New TableLayoutPanel With {.ColumnCount = 1, .RowCount = 2}
Dim flp As New FlowLayoutPanel()
Dim l As New Label With {.Text = message}
myForm.Controls.Add(tlp)
tlp.Dock = DockStyle.Fill
tlp.Controls.Add(l)
l.Dock = DockStyle.Fill
tlp.Controls.Add(flp)
flp.Dock = DockStyle.Fill
For Each o In options
Dim b As New Button With {.Text = o}
flp.Controls.Add(b)
AddHandler b.Click,
Sub(sender As Object, e As EventArgs)
result = DirectCast(sender, Button).Text
myForm.Close()
End Sub
Next
myForm.FormBorderStyle = FormBorderStyle.FixedDialog
myForm.Height = 100
myForm.ShowDialog()
Return result
End Function
End Module
You see you have options as to what buttons are present, the message, and title.
Use it like this
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim result = CustomMessageBox.Show(
{"Right", "Left"},
"Do you want to go right or left?",
"Confirm Direction")
MessageBox.Show(result)
End Sub
End Class
In my example, the prompt is "Do you want to go right or left?" and the options are "Right" and "Left".
The string is returned as opposed to DialogResult because now your options are unlimited (!). Experiment with the size to your suiting.
You need to create your own "custom" msgbox form according to your needs, and its better to create a reusable control - pass your "question" string via the constructor of your custom control.
You need some "way" to get the user decision from out side your custom msgbox - one way is use DialogResult Enum for that.
Here is a basic example i just wrote to demonstrate that, please see the comments i have added inside the code.
create a new project with 2 forms, Form1 will be the main form that will call the custom msgbox and Form2 will be the custom msgbox:
Form1:
Form2:
Code for Form1:
Public Class Form1
Private Sub btnOpenCustomMsgbox_Click(sender As Object, e As EventArgs) Handles btnOpenCustomMsgbox.Click
Dim customMsgbox = New Form2("this is my custom msg, if you press yes i will do something if you press no i will do nothing")
If customMsgbox.ShowDialog() = DialogResult.Yes Then
' do something
MsgBox("I am doing some operation...")
Else
' do nothing (its DialogResult.no)
MsgBox("I am doing nothing...")
End If
End Sub
End Class
Code for Form2:
Public Class Form2
' field that will contain the messege
Private PromtMsg As String
Sub New(ByVal promtmsg As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
' set global field with the argument that was passed to the constructor
Me.PromtMsg = promtmsg
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' set the msg label
Me.lblPromtMsg.Text = Me.PromtMsg
End Sub
Private Sub btnCustomYes_Click(sender As Object, e As EventArgs) Handles btnCustomYes.Click
' user choosed yes - return DialogResult.Yes
Me.DialogResult = DialogResult.Yes
Me.Close()
End Sub
Private Sub btnCustomNo_Click(sender As Object, e As EventArgs) Handles btnCustomNo.Click
' user choosed no - DialogResult.no
Me.DialogResult = DialogResult.No
Me.Close()
End Sub
End Class
it can be much more sophisticated but if you explore that example i hope you will understand the general idea.

Custom Textbox Zoom - Return text to active datagridview cell?

I have 2 Datagridview controls in same form. Each Datagrid has some columns where user will write long texts, so I designed form with RichTextBox that opens when user double-clicks these columns to enlarge text-entry. Code works, but I want to use same form for both Datagrids, so I should somehow return text to active datagridview cell. Here is my code (for Datagridview1):
TextZoomForm:
Public Class TextZoomForm
Public OpenedForm1 As New Form1
Private Sub RichTextBox1_DoubleClick(sender As Object, e As EventArgs) Handles RichTextBox1.DoubleClick
OpenedForm1.DataGridView1.CurrentCell.Value = RichTextBox1.Text
OpenedForm1.Label24.Focus()
Me.Close()
End Sub
Private Sub TextZoom_Load(sender As Object, e As EventArgs) Handles Me.Load
RichTextBox1.Text = OpenedForm1.DataGridView1.CurrentCell.Value
End Sub
End Class
DataGridView1_CellMouseDoubleClick in Form1:
Private Sub DataGridView1_CellMouseDoubleClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDoubleClick
If e.ColumnIndex = 1 Then
Dim cp = Cursor.Position
cp.Y += CInt(Cursor.Size.Height * (-0.5))
cp.X += CInt(Cursor.Size.Width * 0.8)
Dim f As New TextZoomForm()
f.OpenedForm1 = Me
f.Show()
f.Location = New Point(cp)
End If
End Sub
Any ideas on how to return text to active datagridview cell?
Change your zoomed form so that it doesn't know where its data comes from. Instead the control using it will pass the data.
Public Class TextZoomForm
Public Property ZoomedText As String
Get
Return RichTextBox1.Text
End Get
Set(value As String)
RichTextBox1.Text = value
End Set
End Property
Private Sub RichTextBox1_DoubleClick(sender As Object, e As EventArgs) Handles RichTextBox1.DoubleClick
Me.Close()
End Sub
End Class
To call the form change your code to the following:
Private Sub DataGridView1_CellMouseDoubleClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDoubleClick
...
Dim f As New TextZoomForm()
f.ZoomedText = DataGridView1.CurrentCell.Value
f.ShowDialog()
'Great breakpoint location.
DataGridView1.CurrentCell.Value = f.ZoomedText
Label24.Focus()
....
End Sub
Using ShowDialog prevents the user from changing the current cell part way through your call.
If you need it modeless then you should:
store the cell that the user has selected
handle the FormClosing event.
Test the DialogResult to make sure the user pressed ok
write the data back to the stored cell.

How to return selected item on listbox on the second form to the main form in visual basic?

So basically you have a main form that shows only a label (lblTotalPrice) and a button that when you click it, it opens a second form that contains a listbox with different prices packages (lstPackages). How do do you select an item from lstPackages that is on the second form and return it to lblTotalPrice, which is located on the main form?
I attempted this code using a function (thought it would be useful for calculations), but it seems like it didn't work:
On my second form, I populated the lstPackages with it's name using parallel arrays:
Dim strPackages As String = {"Package 1", "Package 2", "Package 3", "Package 4", "Package 5"}
Dim decPrice As String = {100D, 200D, 300D, 400D, 500D}
Private Sub SecondForm_Activated(sender As Object, e As EventArgs) Handles MyBase.Activate
Dim frmMain as New
Dim i As Integer
For i = 0 To strPackages.Length - 1
lstPackages.Items.Add(strPackages(i))
Next
End Sub
After I tried to select a value on lstPackages, but I just was not too sure if I was using the right code to select the item and return it to the main form:
Function CalcPackage()
Dim decPackages As Decimal = 0D
If lstPackages.SelectedIndex = -1 Then
MessageBox.Show("Select a package")
Else
For i = 0 To lstPackages.SelectedItem - 1
decPackages = lstPackages.SelectedItem(i)
Next i
End If
Return decPackages
End Function
When I have selected the item in the lstPackages, I tried to send the selected item back to the main form, but ran into a problem here:
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnClose.Click
Dim frmMainForm As New MainForm
Dim decTotal As Decimal
decTotal = CalcPackage()
'I was stuck in this part and wasn't sure how to return it to lblTotalPrice (and also close the second form too)
frmMainForm.lblTotalPrice.Text = decTotal.ToString("c")
frmMainForm.Show()
Me.Close()
End Sub
So yea sorry if my code is weird, but I'm hoping to get help on how to return the value of the item to lblTotalPrice on the main form, thanks guys
Part of your problem is that you are newing up an instance of the main form in the button exit click event handler of the second form, as shown in this code posted:
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnClose.Click
Dim frmMainForm As New MainForm
Dim decTotal As Decimal
decTotal = CalcPackage()
'I was stuck in this part and wasn't sure how to return it to lblTotalPrice (and also close the second form too)
frmMainForm.lblTotalPrice.Text = decTotal.ToString("c")
frmMainForm.Show()
Me.Close()
End Sub
Instead pass an instance of the main form to the second form via its constructor, like this:
Public Class SecondForm Inherits Form
Dim theMainForm As MainForm
Public Sub New(mainForm As MainForm)
theMainForm = mainForm
End Sub
End Class
Now you can reference the lblTotalPrice in the MainForm class via the theMainForm variable, like this:
theMainForm.lblTotalPrice.Text = lstPackages.SelectedItem
The theMainForm.lblTotalPrice.Text should only be updated in response to an item being selected from lstPackages not when the second form is closed; so handle the updating of the main form's label in the SelectedIndexChanged event of lstPackages, like this:
Protected Sub lstPackages_IndexChanged(sender As Object, e As EventArgs)
Dim decTotal As Decimal
decTotal = CalcPackage()
theMainForm.lblTotalPrice.Text = decTotal.ToString("c")
End Sub
All the exit button click event handler should do is to show the main form and close the second form, like this:
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnClose.Click
theMainForm.Show()
Me.Close()
End Sub
Just display SecondForm with ShowDialog(), then retrieve the value with the reference to it that you already have:
Public Class MainForm
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim sf As New SecondForm
If sf.ShowDialog = Windows.Forms.DialogResult.OK Then
lblTotalPrice.Text = sf.TotalPrice
End If
End Sub
End Class
Over in SecondForm:
Public Class SecondForm
Private _TotalPrice As Decimal
Public ReadOnly Property TotalPrice As Decimal
Get
Return _TotalPrice
End Get
End Property
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnClose.Click
If lstPackages.SelectedIndex = -1 Then
MessageBox.Show("Select a package")
Else
_TotalPrice = lstPackages.SelectedItem(0)
Me.DialogResult = Windows.Forms.DialogResult.OK
End If
End Sub
End Class

Custom control mybase.OnTextChanged not firing

I have a custom text box control which validates input (striped out unwanted chars). This works fine apart from when I also want to do further processing on an implementation of the control.
Example I have 3 "specialTextbox"s on a form. sText1, sText2 and sText3. sText1 & sText2 work as as intended. However, I need to make changes on the forum when the value of sText3 is changed, so I have a handler in the form to handle the ctext changed event:
Private Sub sText3(sender As Object, e As EventArgs) Handles sText3.TextChanged
'do some stuff here
End Sub
However this routine appears to override the OnTextChanged method of the custom text box. I have tried includeing a call to MyBase.OnTextChanged, but this still doesn't cascade up and no matter what I do I can't seem to get the text box to do its validation duties.
Must be something really simple, but I'm stumped!
Here is a class which overrides textbox
Public Class restrictedTextBox
Inherits Windows.Forms.TextBox
Protected validChars As List(Of Char)
Public Sub New(ByVal _validChars As List(Of Char))
MyBase.New()
validChars = _validChars
End Sub
Public Sub setValidChars(ByVal chrz As List(Of Char))
validChars = chrz
End Sub
Protected Overrides Sub OnTextChanged(e As System.EventArgs)
MyBase.OnTextChanged(e)
Dim newValue As String = ""
For Each c As Char In Me.Text.ToCharArray
Dim valid As Boolean = False
For Each c2 As Char In validChars
If c = c2 Then valid = True
Next
If valid Then newValue &= c.ToString
Next
Me.Text = newValue
End Sub
End Class
Here is a form which has a a custom textbox
Public Class frmNewForm
Private Sub btnOK_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnOK.Click
MessageBox.Show("the text from the restricted text is: " & txtRestricted.Text)
End Sub
End Class
Here is a form with a custom text box, which implements the TextChanged event
Public Class frmNewForm2
Private Sub btnOK_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnOK.Click
MessageBox.Show("the text from the restricted text is: " & txtRestricted.Text)
End If
Private Sub txtRestricted_TextChanged(sender As Object, e As EventArgs) Handles txtRestricted.TextChanged
'now that I have implemented this method, the restrictedTextBox.OnTextChanged() doesn't fire - even if I call MyBase.OnTextChanged(e)
'just to be completely clear. the line of code below DOES get executed. But the code in restrictedTextBox.vb does NOT
lblAwesomeLabel.Text=txtRestricted.Text
End Sub
End Class
It fires, but probably not the way you are implementing it.
Your sample code does not have an empty constructor for the textbox, which means you are most likely not using the designer when you are adding the textbox to the form.
But your form shows it was created by the designer:
Private Sub txtRestricted_TextChanged(sender As Object, e As EventArgs) _
Handles txtRestricted.TextChanged
End Sub
That's not possible with your posted code. If you are creating "new" controls programmatically, then you need to wire up the events programmatically, too.
Drop the handler and just leave the stub:
Private Sub txtRestricted_TextChanged(sender As Object, e As EventArgs)
'yada-yada-yada
End Sub
then when you create a new textbox, wire it up:
txtRestricted = new restrictedTextBox(myCharsList)
AddHandler txtRestricted.TextChanged, AddressOf txtRestricted_TextChanged
Me.Controls.Add(txtRestricted)