How I can validate ten comboboxes for the same value? - wpf

I have 10 comboboxes with players. In each combobox must be selected one player. Now, I must validate their so, that only one unique player can be selected in combobox.
For example:
combobox1 - Anna
combobox2 - Anna (too)
But if Anna is selected I don't want choose she in another combobox. Or I can show error message on click button "Start Game", that Anna is selected in two comboboxes. The main thing it must be validate. I have only one Idea how I ca validate this and it's not the best way.
if cmbPlayer1.SelectedValue = cmbPlayer2.SelectedValue Or
cmbPlayer1.SelectedValue = cmbPlayer2.SelectedValue Or
...
cmbPlayer1.SelectedValue = cmbPlayer10.SelectedValue
and so for each of ten combobox.
How I can do it better?

Create List of all selected value of value.
List<Player> players=new List<Player>
palyers.add(cmbPlayer1.SelectedValue)
upto 10 Players.
Then check unique values
palyers.Distinct().Count()==10

How bout this
I tried with one combobox with bunch of names inside,and one listbox to show 10 players that have selected on the combobox. i make a condition like this :
If you select the same name it will shows an message "Multiple name detected". Else if you didn't do that you'll able to add another name to listbox.
So i make the "prevention" condition when selecting names,not when the button pressed.
Try to add a listbox and combobox,fill the listbox value with names. And make the name appear on listbox when you select it.
And code like this on the combobox
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
If Not ListBox1.Items.Contains(ComboBox1.Text) Then
ListBox1.Items.Add(ComboBox1.Text)
Else
MsgBox("Multiple name detected")
End If
End Sub
Hope this will help you,and sorry for my bad english.

Related

In VB.NET, is there a way to change DataGridView ComboBox drop downs of unchanged cells to a new list array while preserving changed cells?

I create DataGridView1 and populate it so that each cell is a ComboBox with data from ComboNames() which is as list of names from a text file. In the main form code I declare a global array called DropDownArray() which is a copy of ComboNames() so I can use it in other Subs. When I test/debug, the form loads and I can do anything in the form without error (there are a bunch of buttons and a separate ListBox). But as soon as I change a cell value in the grid it breaks. Error Message at the bottom after my code. Hopefully I am not trying to do something that cannot be done since I've put quite a lot of time into this project
Snippet of DataGridView Setup:
DataGridView1.ColumnCount = 12
DataGridView1.RowCount = 12
DataGridView1.RowHeadersWidth = 50
For row As Integer = 0 To 11
DataGridView1.Rows(row).HeaderCell.Value = (row + 1).ToString()
For col As Integer = 0 To 11
DataGridView1(col, row) = New DataGridViewComboBoxCell
Next
Next
Snippet of ComboBox Setup:
Dim combo As DataGridViewComboBoxCell
For row = 0 To DataGridView1.Rows.Count - 1
For col = 0 To DataGridView1.Columns.Count - 1
combo = DataGridView1(col, row)
combo.DataSource = ComboNames
Next
Next
Started = 1
My failed attempt to update unchanged cells to have a new ComboBox DataSource of UpdatedNamesList():
Private Sub DataGridView1_SelectionChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
Dim UpdatedNameList As New List(Of String)()
UpdatedNameList = DropDownArray '!!! DropDownArray() = ComboNames() !!!
If started = 1 Then
If DataGridView1.CurrentCell.Value.ToString.Length > 4 Then 'Shortest name is Brian
GridNames.Add(DataGridView1.CurrentCell.Value.ToString)
End If
Dim Difference As IEnumerable(Of String) = DropDownArray.Except(GridNames)
For x As Integer = 0 To DropDownArray.ToString.Length - 1
UpdatedNameList(x) = Difference(x)
Next
Dim combo As DataGridViewComboBoxCell
For row = 0 To DataGridView1.Rows.Count - 1
For col = 0 To DataGridView1.Columns.Count - 1
combo = DataGridView1(col, row)
If combo.Value.ToString.Length < 4 Then
combo.DataSource = UpdatedNameList
End If
Next
Next
End If
End Sub
I get a Break error with no reference to my code so I have no idea what I am messing up on. The error text reads:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
NameGrid.Form1.DataGridView1_SelectionChanged(Object, System.Windows.Forms.DataGridViewCellEventArgs) in Form1.vb
It will be difficult to proffer a good answer as I feel there may not be a good one. I do not want to dissuade you from what you are trying to do, however I hope I can give you a better idea of what is required to achieve what you ask. Basically this is a continuation of my comments (which you ignored) from your previous question… Initializing VB.NET DataGridView to have all Combo Boxes; Button to populate from Array
For starters, the way the code adds the combo boxes to the cells in the grid is …. just wrong. Please let me clarify…
The DataGridView has a column “TYPE” specifically for “combo boxes.” It is called a DataGridViewComboBoxColumn and it is what you should use. Instead, your code is adding DataGridViewTextBoxColumn’s to the grid and then places a DataGridViewComboBoxCell into each of the Text Box cells… ? … This may well work, however it only complicates things and “creates” more work for you. There is a better way.
Example, looking at the first snippet of code for the DataGridView setup…
DataGridView1.ColumnCount = 12
DataGridView1.RowCount = 12
DataGridView1.RowHeadersWidth = 50
For row As Integer = 0 To 11
DataGridView1.Rows(row).HeaderCell.Value = (row + 1).ToString()
For col As Integer = 0 To 11
DataGridView1(col, row) = New DataGridViewComboBoxCell
Next
Next
You should note the first line in this code…
DataGridView1.ColumnCount = 12
This is adding 12 “TEXT BOX” columns and you should be adding 12 “COMBO BOX” columns. If you use a DataGridViewComboBoxColumn instead of a DataGridViewTextBoxColumn, then you can remove the line of code in your loop that adds a DataGridViewComboBoxCell…
DataGridView1(col, row) = New DataGridViewComboBoxCell
The grid will “automatically” create a DataGridViewComboBoxCell for each cell in the combo box column. If a new row is added, it will automatically add the DataGridViewComboBoxCells. Therefore, to do this using a DataGridViewComboBoxColumn may look something like…
For index = 1 To 12
DataGridView1.Columns.Add(New DataGridViewComboBoxColumn())
Next
DataGridView1.RowCount = 12
DataGridView1.RowHeadersWidth = 50
For row As Integer = 0 To 11
DataGridView1.Rows(row).HeaderCell.Value = (row + 1).ToString()
Next
If you run the code above, you will note that each cell is “already” a DataGridViewComboBoxCell and there is no need for your code to add one. In addition, since your code is using a TextBoxColumn it may be one reason that the code fails on the line… combo = DataGridView1(col, row) ….
Next… In relation to the combo boxes having different values… you need to keep in mind that you are wanting to manage 12x12=144 combo boxes! If all 144 combo boxes list of items contained the same values then it is fairly straight forward and we could easily set each combo boxes data source to the same list of items. However, it would be easier to set each DataGridViewComboBoxColumn’s DataSource to the same list and each column will use this list for all the combo box cells in that column. Therefore you could change the code above that adds the combo box columns to…
For index = 1 To 12
Dim col = New DataGridViewComboBoxColumn()
col.DataSource = ComboNames
DataGridView1.Columns.Add(col)
Next
This will eliminate the need for the second code snippet ComboBox Setup
However, my understanding is you want… that if the user “selects” a particular item in one combo box, then, that selected item would NOT be available in any of the other combo boxes list of items.
This is certainly doable; however, it should be clear that… if each combo box had a different value selected… then technically… there would have to be 144 different data sources! Each individual combo boxes data source would have to be unique.
If we continue… let us take a closer look at what is involved when the user changes a combo box’s selected value. Initially, when the form loads, all the combo boxes are empty and each combo box uses the “same” data source.
Now the user changes the selected value in one of the “empty” combo boxes… Once the user selects a value, then one of the grid’s events fires to let us know which cell value changed. Let us say the user selected “Choice 1” in the combo box. Since ALL the combo boxes use the same data source and contain the same values, then we could simply “remove Choice 1” from that list of items.
HOWEVER, if we remove “Choice 1” item from the list… then the current combo box which HAS the value “Choice 1” selected will fail and you will get the grids DataError as “Choice 1” will not be in the combo boxes list of items. Therefore, we would need to add “Choice 1” ONLY to THAT combo boxes list of items. This makes THAT combo boxes data source UNIQUE and we can no longer use the same data source the other (non-selected) combo boxes use. Therefore let us assume that we create a unique list of items specifically for that combo box and continue.
Now the user selects a different combo box. We know that “Choice 1” will NOT be an item in the combo boxes list of items since we removed it from the list. Continuing, let us say the user selected “Choice 3” and the grids changed event fires and we proceeded as we did previously… we remove “Choice 3” from the list for all the combo boxes using the same data source and add “Choice 3” to the current combo boxes list of items. However…
We would ALSO need to remove “Choice 3” from ANY combo box that has already selected an item. We need to do this for each previously changed combo box since those combo boxes have their own UNIQUE list of items. Therefore, as the user changes more and more combo boxes, the code has to do more and more work.
Also note that the previous example “assumes” that when the user selects an item in the combo box, that the selected item in the combo box was originally “empty”… meaning nothing was previously selected. If the user selected a value for the combo box and sometime later “changed” that selected value to a different value… then… we would need to PUT BACK the previously selected value so the other combo boxes CAN select that value. This would include any previously changed combo box!
I hope you can see from the previous example, that it is NOT going to be trivial to manage 144 combo boxes in the manner you describe. Initially, when all the combo boxes are the same… it is trivial… however, as the user changes more and more combo boxes, it would not be surprising to possibly see a sluggish UI when combo box changes are made.
Please forgive my harangue and am only trying to help. It should be fairly clear that managing the combo boxes as you want will NOT be trivial especially using a DataGridViewComboBoxCell. I hope I cleared some things up.
And finally, I have to ask if you have seriously sat down and actually “used” your 12x12 grid of combo boxes… I ran a few tests and can only speak for myself… however… as a user… looking at 144 combo boxes was not pleasant. I am not sure what the overall goal is, however from a user perspective I would consider the 12x12 combo box grid a questionable UI choice. We already know it is NOT going to be trivial to implement and it is going to suck if you go to all the effort to make it work only to find the users hate it.
Main point being… it sounds like you may need to go back to the “data design” phase. What you want to do is not that unusual, however there are just too many combo boxes and too many items in each combo box… that is the “real” problem and it is a “data design” problem… not a UI problem. Good Luck.
I solved my problem. It's slow and very inefficient but that's for another question page. The issue I originally had was changing DataSource of "Unchanged" cells in a DataGridView while preserving ones that had been changed. Easy thing to do. But the issue in my code was a call to the following:
If DataGridView1.CurrentCell.Value.ToString.Length > 4 Then
On cells that had not been touched there is no length. If you try and call that on an "unchanged" cell, it will break but not reference any code. So instead I loop on each cell on CellValueChanged and do a Try Catch so if it fails I change the DataSource to the new array and if not, I just add the value to the running list of entries in the grid. It's slow (about 4 seconds between cell change and allowing me to change next cell) but works. I'm open to optimization, but again, the answer is "Do not try and get length of an unchanged cell".
Working Code to update unchanged cells to have a new ComboBox DataSource of UpdatedNamesList():
Private Sub DataGridView1_SelectionChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
Dim UpdatedNameList As List(Of String) = DropDownArray
Dim combo2 As DataGridViewComboBoxCell
If started = 1 Then
For row = 0 To DataGridView1.Rows.Count - 1
For col = 0 To DataGridView1.Columns.Count - 1
Try
If DataGridView1(col, row).Value.ToString.Length >= 4 Then
GridNames.Add(DataGridView1(col, row).Value.ToString)
End If
Catch
Dim Difference As IEnumerable(Of String) = DropDownArray.Except(GridNames)
For x As Integer = 0 To DropDownArray.ToString.Length - 1
UpdatedNameList(x) = Difference(x)
Next
combo2 = DataGridView1(col, row)
combo2.DataSource = UpdatedNameList
End Try
Next
Next
End If
End Sub

How to code "A2" to add to end of combobox in userform?

I have a userform that the user can input data regarding solar panels and it fills in sheet1. I am now trying to allow the user to input new data that will go to the end of the combobox in the userform. So for example, if they start using a new manufacterur, they can just type in the name of the manufacturer somewhere (right now in sheet 2) and I need to code it so it will end up at the end of the Manufacturer combobox in the userform. What is the most effective way to do this and how do I code it. The solution I'm looking for would be the user clicks on sheet 2, types in the new manufacturer, presses add, and it pops up at the end of the manufacturer combobox in the userform (userform1). Thanks.
sheet 1
userform

How to Populate Label with String Array on ComboBox Item Selection in VB.Net

I have an application in VB.Net where I'm trying to fill a label with some string data that I have in an array. I have a ComboBox which holds some states as the index collection/values. When I select a particular value in the combobox, I want to pull string data from the assigned array, and populate the label with it as a "clickable link a browser window. I'm lost on this, yet here is what I have in my code stub:
Private Sub cboSelectState_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboSelectState.SelectedIndexChanged
'Create a string array
Dim AlabamaCities() As String = {"http://www.rolltide.com/", "http://www.crimsontidehoops.com/", "http://centralalabamapride.org/"}
Dim strAlabama As String
'Populate label with the array data, on a particular value selection in combo box.
If cboSelectState.SelectedValue("Georgia") Then
strAlabama = CStr(AlabamaCities(3))
lblLinkOutput.Text = strAlabama
End If
End Sub
So when I pick Alabama in my combo box, I want the label to show:
http://www.rolltide.com
http://www.crimsontidehoops.com
http://centralalabamapride.org
The links will be clickable from the label and populate in the same tab whenever clicked. I haven't tried the clickable link part yet, and I will try once I get this down.
I know it's probably bad starting form out the gate. But I'm trying to get the form down to gain the knowledge and plan out a bigger project, and accomplish something better when I think of it. I appreciate your knowledge and assistance.
Firstly, it would make sense to use a Dictionary to store the data. The state names will be the keys and the values would be the arrays of URLs. You would then display the keys in the ComboBox and, when a selection is made, use the selected key to get the corresponding value from the Dictionary.
At that point, you won't be using a Label if you want clickable links. You should use a TableLayoutPanel as a container and then add one LinkLabel to the table for each URL in the array. You can then use a single handler for all the LinkClicked events.

Enter text from text box into combo box vb.net

I have two form, A and B.
On FORM A user will select a country code from combobox and it will then be saved to DB.
On FORM B a textbox shows the country code that was saved to the database earlier.
I want to change the country code in FORM B when edit is selected.
How to change:
1. the textbox will first be hidden
2. a combobox with all the country codes will be shown with selected value equals to the hidden textbox value.
I have tried putting the info into the combobox like the textboxes straight from the database when it is blank, e.g:
cbCountryCode.Text = CStr(dataTable.Rows(0).Item(2))
but this does not work. I also need to keep the country codes in the combobox as the user will need to change the country code if it's wrong. Is there a way of doing this? I have a work around where I don't let the user update the info if the combobox is blank, but I want the country code to be already there so that the user does not have to select a country code again if it is not wrong. Any help with this problem would be greatly appreciated.
EDIT:
datatable.Rows(0).Item(2)
holds a country code, for example, Ireland (+353), United Kingdom (+44) or U.S.A. (1).
This is the code I have for calling the information from the database:
sqlVisitorDetails = "SELECT * FROM visitorDetails WHERE idNumber=#idNumber"
sqlCon.Open()
sqlCmd = New SqlCommand(sqlVisitorDetails, sqlCon)
sqlCmd.Parameters.AddWithValue("#idNumber", txtIdNumber.Text)
dtVisitorDetails = loadDtVisitorDetails()
txtFirstName.Text = CStr(dtVisitorDetails.Rows(0).Item(1))
txtLastName.Text = CStr(dtVisitorDetails.Rows(0).Item(2))
txtContactNumber.Text = CStr(dtVisitorDetails.Rows(0).Item(3))
txtCountryCode.Text = CStr(dtVisitorDetails.Rows(0).Item(4))
txtAddress.Text = CStr(dtVisitorDetails.Rows(0).Item(5))
The country code (e.g. 'Ireland (+353)') is stored in dtVisitorDetails.Rows(0).Item(4) and this is put into the text box txtCountryCode.
When edit is clicked on the form, the text box txtCountryCode is hidden and the combobox cbCountryCode is visible (before edit is clicked txtCountryCode is shown and cbCountryCode is hidden). I then want the country code (in this case 'Ireland (+353)') to be shown in the cbCountryCode combo box. At the moment when the combobox is shown it is blank and the user has to choose a country code again, even if it's right. I hope this makes things clearer.
From the best i can understand from your question.
cbCountryCode.Text = CStr(dataTable.Rows(0).Item(2))
will not work if the DropDownStyle in the properties is set to DropDownList, change it to DropDown instead(if its not).
And to this:
I also need to keep the country codes in the combobox as the user will need to change the country code if it's wrong.
you have to bind the data to the ComboBox to make it work.
EDIT:
If possible, use ColumnName instead of Index for getting a data from datatable. Since you're selecting all record from your database, your may not know when then index would change(when a column is added or deleted from DB)
cbCountryCode.Text = CStr(dataTable.Rows(0).Item("CountryCodeColumn"))
How about that?
cbCountryCode.ClearSelection()
cbCountryCode.SelectedIndex = cbCountryCode.Items.IndexOf(cbCountryCode.Items.FindByText(datatable.Rows(0).Item(2).ToString))
Try this;
cbCountryCode.SelectedItem = CStr(dataTable.Rows(0).Item(2))
The .Text property is the currently selected text in the combo, not the currently selected item.
EDIT: (version 3!)
This definitely works! Create a new project, with a new WinForms project and Form1, etc. Add a button (btnTest) and a combobox (cboTest) and paste this code in;
Private Sub Form1_Load() Handles MyBase.Load
' Add some items
cboTest.Items.Add("U.S.A (+1)")
cboTest.Items.Add("Ireland (+353)")
cboTest.Items.Add("U.K. (+44)")
' Select the first item
cboTest.SelectedIndex = 0
End Sub
Private Sub btnTest_Click() Handles btnTest.Click
' Select the UK entry
cboTest.SelectedIndex = cboTest.FindString("U.K.")
End Sub
And I hate to have to say it, but it works like a charm! I've tested it with the combobox set to DropDown AND to DropDownList and the result is the same. Please check you have the right data going into and out of your routines from the dataTable/Row/Item you are using!!
Try simple:
comboBox.Items.Add("Item 1");

MS ACCESS 2007 restrict editing to form fields until combobox selection is made

How do i restrict the editing of form fields until a combobox selection is made? I am using MS Access 2007.
Thanks for your help.
On the form, you can start off with all the fields being locked (cannot edit) and disabled (cannot click on them) (you can find those in the property sheet of the form). Then on the On Change event of the combo box, in VBA, cycle through all the fields and enable them again.
This answer provides code for how to loop through controls on a form. In this example, you would set ctl.Enabled = True and ctl.Locked = False (where ctl is the control you are referencing)
A note, to make sure that the combo box is always changed, I usually put "Choose One..." as the first item of the list. And check it on form submission to make sure it's not still selected. That way, it forces the On Change event to fire where it wouldn't if someone used the first option of the list.
Hope that was at least enough to get you started...
EDIT: Additional info
In the table design, I put default value of "Choose 1" on the Combo Box and made it the first option. So when the form comes up, that's what you see.
You can set the Locked property of your memo and date fields to Yes (found in the property sheet under data or you can use the .Locked = True in VBA.
Then, in the on change event of the combo box, click the ... and use the code builder and put something like this:
Dim ctl As Control
If Me.Combo77.Value <> "Choose 1" Then
'Loop through all controls on form
For Each ctl In Me.Controls
'Only text boxes, not labels, or combo box ect.
If ctl.ControlType = acTextBox Then
'Unlock the field and allow editing
ctl.Locked = False
End If
Next
End If
I tried it out and it works on my little test database.
Here is the MSDN article on the control types: MSDN Control Types
To do it this way, I would recommend what I said above and put the first item of the Combo Box something they're not going to choose.

Resources