VB.NET Check for keydown on dragdrop - vb.net

I've tried searching quite a bit for this answer but haven't been able to find a good solution.
I have a datagridview on my form where users can drag and drop files onto the grid and certain columns are filled in. This works fine.
I want to be able to check if a user has a certain key pressed at the time the file is dropped. If so, I want to use that to add specific data to one of the columns in the datagrid.
Is this possible?
EDIT:
I have used keydown outside of dragdrop before but it seems that I'm missing something. The code I have is below. No matter what I do, I never get "T is pressed" but I always get "T is not pressed".
Private Sub frmReader_DragDrop(sender As Object, e As DragEventArgs) Handles Me.DragDrop
Dim files As String() = CType(e.Data.GetData(DataFormats.FileDrop), String())
If Keyboard.IsKeyDown(Keys.T) Then
MsgBox("T is pressed.")
' Put certain info into the datagridview
Else
MsgBox("T is not pressed.")
' Put other data into the datagridview
End If
End Sub

God, embarassing... I changed "Keys.T" to "Key.T" and it's working fine. Sorry for the bother.

Related

How can I filter a ListView using TextBox and ComboBox?

Private Sub ComboBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox2.SelectedIndexChanged
ListView2.Items.Clear()
Dim curSelectionCombobox As String = ComboBox2.SelectedItem.ToString()
ListView2.Items.Add(listitm)
End Sub
Well basically this is what ive come up with the filtering thing in combobox which is obviously wont work
and in the combobox and button i didnt get to try coding those but im quite sure it wont work either im new in this language and im struggling to catch up giving the fact that this pandemic really gets me more and more stupider as the day passed by
Well my main problem is that the filtering in the groupBox_bookShelf is when i choose a genre in the combobox the static listview will filter leaving only the exact items its genre selected in the combobox
the second is the combobox and button im aiming to link the action of both property when filing in the groupBox_bookInformation then once the filter button is clicked i want to filter the lower listview leaving only the selected genre and its items
Here is the sample form ive been working on.
enter image description here
I am guessing that what is selected in the combo box is a value that appears in some of your list view items.
Start by calling .BeginUpdate() This will prevent the user interface from repainting on each update which would really slow things down.
I loop through the items and test one of the sub items to see if it matches the combo selection. If it does not match is is removed.
Be sure to call .EndUpdate or the changes will not show up.
Private Sub ComboBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox2.SelectedIndexChanged
Dim curSelectionCombobox As String = ComboBox2.SelectedItem.ToString()
ListView2.BeginUpdate()
For Each lvi As ListViewItem In ListView2.Items
If lvi.SubItems(6).Text <> curSelectionCombobox Then
lvi.Remove()
End If
Next
ListView2.EndUpdate()
End Sub

Needing Assistance with vb.NET Application

I don't normally post on forums because I try to find information for myself, and ask as an absolute last resort. I've tried scouring the net for answers, but I'm only receiving about half of the answer I'm looking for.
I'm currently building an application that deals with state law. There's one combo box and one text box. One for the offense title, and one for the numerical code for that particular code section. So say if I select "Kidnapping", it prepopulates the text box below it with "11-5-77", for example.
The method I've been using for, oh, about the last hour now, is:
If AWOffenseTitle.Text = "Kidnapping" Then
AWCN.Text = "11-5-77"
ElseIf AWOffenseTitle.Text = "False Imprisonment" Then
AWCN.Text = "11-5-78"
With AWOffenseTitle being the combo box name, and AWCN being the text box name. While this has proved to work perfectly well so far, I'm sure you can imagine with hundreds of offense titles, this is going to take a ridiculously long time. Well, I finally found a spreadsheet with offense titles and their respective title codes. What I'm looking to do is create two text files within a folder in the local directory "Offenses". One with a vertical list of offenses, and one with a vertical list of offense code numbers that populate the same lines in each. What I'm looking to do is populate the combo box with the contents of text file one (which I can do already), but then selecting an offense title will read the second text file and display it's proper title code. That's what has me at a loss. I'm relatively well-versed with vb.NET, but I'm not an expert by any means.
I'm hoping someone here will be able to provide a code example and explain it to me line-by-line so I can gain a better understanding. I want to get more proficient with VB although it's not so popular anymore. I've been using VB since 6.0, but not on a regular basis. More on a sporadic project kind of basis.
I really appreciate any assistance anyone might be able to provide, and if you need more information, I'd be glad to answer any questions. I tried to be as thorough as I could.
Thank you in advance!
First, you need to retrieve your data. I demonstrated using an Sql Server database containing a table named Offenses with columns named OffenseTitle and OffenseCode. You will have to change this code to match your situation.
Private Function GetOffenseData() As DataTable
Dim dt As New DataTable
Using cn As New SqlConnection("Your connection string"),
cmd As New SqlCommand("Select OffenseTitle, OffenseCode From Offenses;")
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
As the Form loads, set the properties of the ComboBox. DisplayMember matches the name of the title column and ValueMember is the name of the code column.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = GetOffenseData()
ComboBox1.DisplayMember = "OffenseTitle"
ComboBox1.ValueMember = "OffenseCode"
ComboBox1.DataSource = dt
End Sub
Then when the selected item in the combo changes, just set the .Text property of TextBox to the SelectedValue in the combo and your code appears.
Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
TextBox1.Text = ComboBox1.SelectedValue.ToString
End Sub
There are other ways to do this if your data source is other than a database. Please advise if you need additional help.
In addition to HardCode's comment and Mary's detailed answer, I can only add an answer that's somewhere in between them.
It might be the case, that the information is not taken from a database, but from another source, like a text/data file or a web service. So it might be useful to create an abstraction for the data source you actually use.
First, I create a class or struct that will hold the data for each combo box item.
Class Offense
Public ReadOnly Property Title As String
Public ReadOnly Property Code As String
Public Sub New(title As String, code As String)
Me.Title = title
Me.Code = code
End Sub
End Class
Next, you need a method that retrieves a list of offenses that you can bind to your combo box. It's entirely up to you how you fill/fetch the offenses list. I have simply hard coded your two values here.
Private Function GetOffenseData() As List(Of Offense)
Dim offenses As New List(Of Offense)
offenses.Add(New Offense("Kidnapping", "11-5-77"))
offenses.Add(New Offense("False Imprisonment", "11-5-78"))
Return offenses
End Function
At a certain moment (probably in your form's Load event handler), you need to initialize your combo box. Just like Mary did, I use data binding.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AWOffenseTitle.DropDownStyle = ComboBoxStyle.DropDownList
AWCN.ReadOnly = True
AWOffenseTitle.DisplayMember = NameOf(Offense.Title)
AWOffenseTitle.ValueMember = NameOf(Offense.Code)
AWOffenseTitle.DataSource = GetOffenseData()
End Sub
Note that I use the NameOf operator to get the desired property names of the Offense class. If you ever decide to rename the properties of your Offense class, you will be able to easily detect where they are used, since the compiler will complain if your code still uses the wrong property names somewhere.
Finally, the app needs to react to combo box value changes, so that the text box will show the corresponding offense code. Mary used an event handler for the SelectionChangeCommitted event, but I use a handler for the SelectedIndexChanged event instead:
Private Sub AWOffenseTitle_SelectedIndexChanged(sender As Object, e As EventArgs) Handles AWOffenseTitle.SelectedIndexChanged
AWCN.Text = AWOffenseTitle.SelectedValue
End Sub
(Up to now, I was not aware of the SelectionChangeCommitted event of the ComboBox control. I will need to look into this event to see if it is actually a better choice for this scenario, but I found that the SelectedIndexChanged event does the job just fine, so for now I sticked with that event, since I am more familiar with it.)

How to update a group of combo boxes using Loops

I have a form with combo boxes (cmbPort#) to select up to 8 serial ports. I want to first clear the item list for each, populate them with currently available system ports, and then add the option "Off" to each list. Finally, to set each combo box according to defaults saved in string spName(). I created a GroupBox (gBox1) and dragged each cmbPort onto it but I'm not sure how to reference the controls on it. I'm using VB 2015.
Can you help with VB.NET code to use loops ("For Each" or similar) to do this more efficiently?
Private Sub frmProp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
cmbPort1.Items.Clear()
...
cmbPort8.Items.Clear()
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbPort1.Items.Add(sp)
...
cmbPort8.Items.Add(sp)
Next
cmbPort1.Items.Add("Off")
...
cmbPort8.Items.Add("Off")
cmbPort1.Text = spName(1)
...
cmbPort8.Text = spName(8)
End Sub
Loops are an incredibly useful tool to master. I pitched here some code so you can get the idea, but I was working out of IDE so you might have to apply some fixes to this code to make it work as you want it to.
The main idea is that you shouldn't have to write a line more than once. If you multiply the same operation on several lines of code, you create potential problems for the future. Loops and subs are really helpful to prevent this kind of issues.
Private Sub frmProp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'This is for later
Dim cmbIndex As Integer = 1
'You basically do the same operations for every Combobox in your list, son only one loop needed
For Each cmbPort As ComboBox In {cmbPort1, cmbPort2, cmbPort3 [...] cmbPort8} 'this is a way to declare an array
'Clear
cmbPort.Items.Clear()
'Add SerialPortNames
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbPort.Items.Add(sp)
Next
'Add "Off"
cmbPort.Items.Add("Off")
'This last one is a little bit trickier because you want to match numbers
'This is the place where you get errors when something doesn't go as planned
'If you need to keep it inside the loop here's a way to achieve that, but honestly I would't do that
'Instead I would suggest that you take this part out of the loop and do it manually
If spName(cmbIndex) IsNot Nothing Then cmbPort.Text = spName(cmbIndex)
cmbIndex += 1
Next
End Sub
You shouldn't consider efficiency into this equation, as this operation will not be called all the time, only on load. I mean: you should always do things in the best way you can, but optimization is sometimes the enemy of good, readable code.

getchanges doesn't return the changes half the time

I'm using an Xceed grid bound with a DataSet/DataTable. The thing is, I need to know if changes were made before loading new datas in the grid and therefore, losing changes if I don't save them then.
But neither the DataSet nor DataTable's function getChanges([DataRowState])
return the right thing :S
I've found that sometimes dataColumnChangeEvent is called, but NOT dataRowChangeEvent, these are the times where the changes are not saved into the getChanges() function.
This happens when I click out of the grid while in an editing cell instead of selecting an other of the grid's cell by any way.
Also, I've looked and the rowState is to Unchanged, even if the data do is changed :S
Any ideas?
Great! I've finnaly found a solution.
Even if the dataRowChangeEvent doesn't seem to be called (I'll explain latter)
If the only code in the rowChangeEvent is the code below it works :
Private Sub RowChanged(ByVal sender As Object, ByVal e As DataColumnChangeEventArgs)
If e.Row.RowState = DataRowState.Unchanged Then
e.Row.AcceptChanges()
e.Row.SetModified()
End If
End Sub
We check the rowState because we can only setModified() a row wit the Unchanged state.
We do AcceptChanges() because doing only setModified() removes the changes on the edited cell.
We do SetModified(0 because if not AcceptChanges() leaves the RowState to Unchanged and therefor it doesn't get in the table's getChanges.
EDIT : This brings an other problem, the dataAdapter uses the datarow's original and current Value to do update, delete and insert,
doing "acceptChanges" set OriginalValue to the current Value so delete and Update doesn't work anymore :(
--More--
When I said it doesn't seem to get in the event, it's because the code below :
Private Sub RowChanged(ByVal sender As Object, ByVal e As DataColumnChangeEventArgs)
If e.Row.RowState = DataRowState.Unchanged Then
e.Row.AcceptChanges()
e.Row.SetModified()
End If
MessageBox.Show("hasError=" & IIf(e.Row.HasErrors, "true ", "false ") & _
"; action=" & e.ProposedValue)
End Sub
neither Shows the message Box nor get the changes in the dataTable's getChanges()...
Also, having only
MessageBox.Show("Changing")
instead of the previons messageBox, Do show the messageBox, and Do get the changes right, BUT it then kindof breaks the event so it doesn't go further in the newProjectSelected => no new project is loaded, but it only needs a "re-clic".
So, I've explained how it behaves.
But it's soo strange, I'de appreciate if someone would explaine shuch behaviour.

Vb.net + AutoComplete in textboxes

So I was reading a bit on AutoComplete of textboxes in VB.NET, but I can't really understand where these are stored? Is it a fully built in feature, or do I have to write some code for it to work? I've found the AutoCompleteMode and AutoCompleteSource properties of textboxes. But I want to append whatever I've written in the textbox to the autocomplete source. Do I connect the source to My.Settings or something? Wouldn't I have to use an array as well? Any help would be appreciated :)
You would have to add new entries to your auto-complete data source manually... which makes sense, when you think about it: How is Windows Forms supposed to know when a new entry should be added to the list of suggestions and when the text entered is only something temporary?
You could add new values e.g. when validation of the input field happens, or when the user presses an OK / Apply button, or whatever fits your need best. But you will have to do this yourself.
The properties you've already discovered are the right ones.
Dim suggestions As New List(Of String)
suggestions.Add("Abba")
suggestions.Add("Nirvana")
suggestions.Add("Rolling Stones")
...
textBox.AutoCompleteSource = suggestions
You can bind AutoCompleteSource to almost anything; this is very similar to data-binding. One thing to keep in mind is that if you're adding new entries to the auto-complete data source, the UI control might not immediately notice if your data source doesn't implement the INotifyCollectionChanged interface.
first create the list to use as the custom source.
Dim MySource As New AutoCompleteStringCollection()
and then set the property of the textbox
With MyTextbox
.AutoCompleteCustomSource = MySource
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.AutoCompleteSource = AutoCompleteSource.CustomSource
End With
put this code in eventlistener you use for validating the input field, e.g. btnOK.Click
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
MySource.Add(txtinput.text)
End Sub