How to create something similar to google style currency converter with VB.NET - vb.net

Ok I have a bit of a weird question here. I have a program similar to a currency converter (it performs a mathematical function in order to produce a value to go in another textbox). What I want it to be able to do is identify the last textbox that you edited (there are 4) and then update the rest based on what you have inputted, the user then must be able to change a different textbox to change all of them.
If anyone can get me started on how to do it or even some sample code that would be much appreciated, thanks!
Sorry if I'm not making sense, just have a look at the google currency converter and think that with two more editable boxes.

This might be what you want if I understand you correctly.
In the form class, you have a variable called lastTextBoxChangedName which keeps track of which text box was the last to be edited.
Next there is an event handler which will fire when any of the four TextBoxes are changed. This merely updates lastTextBoxChangedName.
When you have finihed editing a textbox, and tab to the next one or click on something that causes a TextBox to lose input focus, the next event handler executes. This looks at lastTextBoxChangedName to see which was the last edited TextBox and you can insert your update code to replace the comments in the Select Case block.
Public Class Form1
Dim lastTextBoxChangedName As String
Private Sub TextBox_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged, TextBox2.TextChanged, TextBox3.TextChanged, TextBox4.TextChanged
lastTextBoxChangedName = sender.name
End Sub
Private Sub TextBox1_LostFocus(sender As Object, e As EventArgs) Handles TextBox1.LostFocus, TextBox2.LostFocus, TextBox3.LostFocus, TextBox4.LostFocus
updateTextBoxes()
End Sub
Private Sub updateTextBoxes()
Select Case lastTextBoxChangedName
Case "TextBox1"
'do updates appropriate to textbox1 changed
Case "TextBox2"
'do updates appropriate to textbox2 changed
Case "TextBox3"
'do updates appropriate to textbox3 changed
Case "TextBox4"
'do updates appropriate to textbox4 changed
End Select
End Sub
End Class
However, if you already have separate event handlers for each TextBox, don't add that first event handler for TextBox_TextChanged, just add the line ..
lastTextBoxChangedName = sender.name
into each handler.

Related

Event is triggered when I do not want it

I have a question about the behavior of the combobox, more precisely about the Selected-Index-Changed-Eventhandler.
In this test project, I click on the first entry in the Combobox. Correctly, “Something happening here” appears in the output window below. But if I click on the same entry again, the event will be triggered again. That is not supposed to happen. Is there a trick to prevent this from happening? I would only think of creating a variable (oldIndex) and comparing the current index with the old one.
Edit
Public NotInheritable Class FormMain
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ComboBox1.Items.AddRange({"1", "2", "3"})
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
If ComboBox1.SelectedIndex <> (-1) Then
Debug.WriteLine("Something hapening here")
Select Case ComboBox1.SelectedIndex
Case 0
TextBox1.Text = "1"
Case 1
TextBox1.Text = "2"
Case 2
TextBox1.Text = "3"
Case Else
Exit Select
End Select
End If
End Sub
End Class
The implementation of the SelectedIndex property actually prevents these spurious events already but it appears that selecting an item via the UI doesn't actually cause the SelectedIndex property to be set. What we can do is inherit the ComboBox class and track the SelectedIndex ourselves and then simply abort the SelectedIndexChanged event if the property value hasn't actually changed:
Public Class ComboBoxEx
Inherits ComboBox
Private _selectedIndex As Integer = Integer.MinValue
Protected Overrides Sub OnSelectedIndexChanged(e As EventArgs)
If _selectedIndex = SelectedIndex Then
'The selection hasn't actually changed.
Return
End If
_selectedIndex = SelectedIndex
MyBase.OnSelectedIndexChanged(e)
End Sub
End Class
If you add a new class to your project, add that code and then build, the new control will appear in your Toolbox. You can then add it to a form instead of a regular ComboBox. If you already have a form with a regular ComboBox on it then you can open the designer code file and change the type of the existing controls. Make sure you have a backup first, in case you make a mistake and kill your form.
There are a couple of points to note here. Firstly, the SelectionChangeCommitted event behaves the same way, so you probably ought to override the corresponding method too. If you're not using that event though, it's not too important. This code does take care of the SelectedValueChanged event though.
Secondly, I'm not sure whether there might be times when this code could cause issues, e.g. the actual item selection has changed but the SelectedIndex hasn't. Probably not an issue but something to consider.

VB.net, Being able to select text in a richtextbox without losing focus?

VB.net .. Currently I have two controls, one richtextbox and a textbox. The RTB is readonly, and also HideSelection is set to false.
The textbox is generic, it allows for input (to send data).
I want to be able to select things in the richtextbox without losing focus in the textbox. There is a client called 'mushclient' that does this, and it works pretty well. The text is still selected, but it doesn't lose the focus on the chatbar to type in.
I don't exactly know however how to prevent 'focus' though. At the moment it breaks flow when you are in game but want to copy something, you'll have to click the textbox again to start typing again. I understand I could setfocus after clicking the RTB, but this feels overall a bit odd. I was wondering if there is a more elegant solution.
Thanks!
This seems to work well for me. The TextBox does loose focus, but as soon as the Mouse_UP event fires, the selected text is copied to the clipboard and focus is sent back to the text box.
Public Class Form1
Dim LostFocusControl As Control
Private Sub RichTextBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles RichTextBox1.MouseUp
If RichTextBox1.SelectedText.Length > 0 Then
Clipboard.SetText(RichTextBox1.SelectedText)
End If
If Not IsNothing(LostFocusControl) Then
LostFocusControl.Focus()
End If
End Sub
Private Sub ControlLostFocus(sender As Object, e As EventArgs) Handles TextBox1.LostFocus
LostFocusControl = Sender
End Sub
End Class
The code is a bit longer than it could be, but this makes it easier if later on you want to change the control that focus is returned to. To change the control that you want to return focus to, just change the name of the control that the handler is subscribed to e.g
Change
Private Sub ControlLostFocus(sender As Object, e As EventArgs) Handles TextBox1.LostFocus
To
Private Sub ControlLostFocus(sender As Object, e As EventArgs) Handles Listbox1.LostFocus
or whatever the name of the control is that you want to return focus to.

How to Dynamically Update Label with TextBox As Input Changes

I have a spelling application that I am building in VB.Net, where I have a textbox receiving simple input (spelling words), and a label which will show the output. What I want to accomplish is when I enter something in the textbox, I can see it in my label - as I am typing into the textbox.
I will admit that I don't know what I'm doing, as I've never tried this before, so I don't know to begin in terms of setting up what I need to do. I know that I'll need some variable to hold my String input, and will probably need some type of loop, but beyond that, I am lost. The only other example is in C#, and doesn't help me any.
Can anyone give me a simple model to work off of, so I can put the approach into memory? For now, all I have is code stub from my TextChanged event handler:
Private Sub txtSpell_TextChanged(sender As Object, e As EventArgs) Handles txtSpell.TextChanged
'Set variables to hold values.
Dim someText As String
'Connect the label and textbox.
lblShowInput.Text = txtWordInput.Text
'Process loop to populate the label from textbox input.
for '(This is where I am lost on the approach)
End Sub
I know that I'll need some variable to hold my String input, and will
probably need some type of loop
I don't think you'll need a loop, or the variable to hold the value. You almost have it:
Private Sub txtSpell_TextChanged(sender As Object, e As EventArgs) Handles txtSpell.TextChanged
'Connect the label and textbox.
lblShowInput.Text = txtSpell.Text
End Sub
In the code you provided, you are referencing an object named txtWordInput inside your txtSpell text changed event handler. If you are entering the text in the txtWordInput input, you'll want to handle this in the txtWordInput textChanged event handler:
Private Sub txtWordInput_TextChanged(sender As Object, e As EventArgs) Handles txtWordInput.TextChanged
'Connect the label and textbox.
lblShowInput.Text = txtWordInput.Text
End Sub
Follow-up:
The TextChanged event is the correct event for this.
In your code, you are assigning lblShowInput.Text to txtWordInput.Text, but in the txtSpell TextChanged event handler.
You want to be in the TextChanged event handler for whatever TextBox you would like to use to update the label, as the text is changing.
To give a better example, I have created a simple Winforms VB application that has only a textbox named InputTextBox and a label named Output Label.
The Form:
The Code:
Public Class Form1
Private Sub InputTextBox_TextChanged(sender As System.Object, e As System.EventArgs) Handles InputTextBox.TextChanged
OutputLabel.Text = InputTextBox.Text
End Sub
End Class
Explanation:
InputTextBox_TextChanged is the method name generated by Visual Studio for our event handler
Handles InputTextBox.TextChanged ties the method to an actual event it is handling.
When the InputTextBox text property is changed (typically by user input), whatever we have in our InputTextBox_TextChanged Sub will execute. In this case, I am assigning the Text of OutputLabel to the Text of the InputTextBox
Output:
Resources:
I've uploaded this simple demo to GitHub if you'd like a closer look.
Take a look at the TextChanged documentation

One column in a vb.net Datagridview should not allow paste of non-integers

I have a datagridview and one of the columns is a Quantity column that should only allow integers. No negative symbols or decimal points. I have prevented the user from typing in any characters but they can paste them in. I could stop this in validation but I would ideally like to not even show characters that are pasted in. How would I detect and remove pasted in letters and in what event?
Ideally I would also like for only the paste to not work, so if the field already had a 2 in it and they pasted "test" then the 2 would remain, although that isn't as important.
Here's one approach:
'Set a flag to show when the form has finished initialising
Dim initialising As Boolean = True
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Form is initialised so set boolean to false
initialising = False
End Sub
Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
'Only process once the form is initialised as values don't exist yet!
If Not initialising Then
If Not IsNothing(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value) Then
'If the clipboard contains text
If Clipboard.ContainsText Then
' Check to see if the value of the cell matches whats in the clipboard
If CStr(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value) = Clipboard.GetText Then
'You know its been pasted
If Not IsNumeric(CStr(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)) Then
'This value should be rejected
Else
'This value is allowed
End If
End If
End If
End If
End If
End Sub
See my commentated code for an explanation.
I'm not sure you will want to do it on this event as it doesn't fire the event until the user leaves the cell. Hopefully however my approach of checking the value against what is in the clipboard might help you to identify if its a pasted value.
You'd have to implement a validating method and call it in some of the DataGridView's events (I'm thinking KeyDown/Keypress and MouseClick).
I think it's bad practice, because you'll be struggling to find more ways in which the user can trick your application; most apps nowadays let the user input whatever they want, but keep the user from completing her task until she has sanitized her input. Most also give clear on-screen instructions on how to do so.
Something like this
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
End Sub

Edit Update DatagridView VB.Net (No Database)

Good day everyone.
I need your help in this project I am into (a Visual Basic program with no database.) It just contains a Datagridview, a Textbox, and three buttons (an "Add" Button, a "Edit" and an "Update" Button).
1 . Is there any way (like using "for loop") to automatically assign DataGridView1.Item("item location") to the one edited and be updated?
2 . Or is it possible to just click an item in the Datagridview then it will be edited at that without passing it to a Textbox, and to be updated at that.
The DataGridViewCellEventArgs variable (e in the method stub the designer will generate for you) of the double click event of the cell has RowIndex and ColumnIndex properties which refer to the position of the cell you clicked.
Save those (in a class variable possibly or a local one if that's all you need) and then refer to them when you update the cell in your DataGridView, possibly like this MyDataGridView.Item(e.ColumnIndex, e.RowIndex) or MyDataGridView.Rows(e.RowIndex).Cells(e.ColumnIndex) where e is the variable from the double click event handler.
For you cell double click event you could have something like this:
Private Sub DataGridView1_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick
Using myEditor As New frmCellEditor(Me.DataGridView1.Item(e.ColumnIndex, e.RowIndex).Value)
If myEditor.ShowDialog() = DialogResult.OK Then
Me.DataGridView1.Item(e.ColumnIndex, e.RowIndex).Value = myEditor.NewCellValue
End If
End Using
End Sub
This will call a new instance of your editor and get a value from you. For the purpose of this demo I have made a form like this:
Public Class frmCellEditor
Public NewCellValue As Integer
Public Sub New(ByVal CurrentCellValue As Object)
InitializeComponent()
Me.TextBox1.Text = CStr(CurrentCellValue)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.NewCellValue = CInt(Me.TextBox1.Text)
Me.DialogResult = DialogResult.OK
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Call Me.Close()
End Sub
End Class
Which just has two buttons (Button1 = OK, Button2 = Cancel). When you click OK, it just returns the value 1 which then gets set as the value of the cell.
This is a VERY simplistic example, but it should provide you the basics of what you are trying to do.
UPDATE:
I updated the code for the editor interface so it will include handling for passing the value back and forth from the form with your datagridview.
In your project, make a new form called frmCellEditor. This forms has to have two buttons and a textbox (Make sure that the programmatic names match!). Replace the code with the code listed above. You will have to add Imports System.Windows.Forms above the class as well.
Amend the event handler for the cell double click event of your datagrid to pass the cell value when frmCellEditor is constructed (the line going ... New frmCellEditor(...).
How many columns does your DataGridView has?
Based on how you populate your DataGridView, I'll assume only 1.
Declare this on top of your form
Dim i as Integer
On your btnUpdate_Click Event (Just combine your Edit and Update button into One)
SELECT CASE btnUpdate.Text
Case "Update"
With DataGridView1
'Check if there is a selected row
If .SelectedRows.Count = 0 Then
Msgbox "No Row Selected for Update"
Exit Sub
End If
i = .CurrentRow.Index 'Remember the Row Position
Textbox1.Text = .item(0 ,i).value 'Pass the Value to the textbox
.Enabled = False 'Disable DataGridView to prevent users from clicking other row while updating.
btnUpdate.Text = "Save"
End With
Case Else 'Save
DatagridView1.Item(0,i).Value = Textbox1.Text
btnUpdate.Text = "Update"
END SELECT
Thanks for those who contributed to finding answers for this thread. I have not used your solutions for now (maybe some other time). After some research, I've found an answer for problem 2 (more user friendly at that):
2 . Or is it possible to just click an item in the Datagridview then
it will be edited at that without passing it to a Textbox, and to be
updated at that.
Here's what i did:
in Private Sub Form1_Load, just add:
yourDataGridView.EditMode = DataGridViewEditMode.EditOnEnter
in Private Sub yourDataGridView_(whatever event here: DoubleCellClick, CellContentClick, etc.) add:
DataGridView1(e.ColumnIndex, e.RowIndex).[ReadOnly] = False
DataGridView1.BeginEdit(False)