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
im trying to get to change the visibility of different labels during runtime after a button click
Dim labelsEmpty As New ArrayList
Dim allTxt As New List(Of Control)
For Each txt As TextBox In FindControlRecursive(allTxt, Me, GetType(TextBox))
If txt.Text = "" Then
If txt.Name = "TextBox1" Then
Else
'Dim textBoxName = txt.Name.ToString.Remove("txt").ToLower
labelsEmpty.Add(txt.Name.ToString.Replace("txt", "lblMsg"))
End If
End If
Next
For Each label In labelsEmpty
Dim Label1 As New Label
Label1.Name = label
Label1.Text = "Insert a value"
Label1.Visible = True
Next
This is what i have, each textbox in my form has a label used to tell the user that there was some kind of error, in this case i need to get which textbox is left empty and set the visibility of its label to true (already hidden from form start), so what i do is i go through every textbox in my form to see which one the user left empty and then take their name (ex: txtAge) and replace txt with "lblMsg" and then insert them into an array.
Doing so i get an array with all the label names that should be set to visible = true
Now i need to set their visibility and text value, so what i did is i created a for each loop and getting every label in the array, but the code i used is not working, i already checked if there are items in the array and they are there, any help? Thanks.
My Form: https://i.stack.imgur.com/qrawz.png
In your final loop, you are creating new labels and never adding them to your form. If you already have existing labels on your form, you want to reference those:
For Each label In labelsEmpty
With Controls(label)
.Text = "Insert a value"
.Visible = True
End With
Next
Setting the Text property may be unnecessary if your labels already have the necessary text.
If you want to create new labels and then add them to your form, you need to add the control to the form after you have created it:
For Each label In labelsEmpty
Dim Label1 As New Label
With Label1
.Name = label
.Text = "Insert a value"
'.Top = 100
'.Left = 100
.Visible = True
End With
Controls.Add(Label1)
Next
If you do it this way, you will need some way to set the Top and Left properties so that the labels align correctly with your existing text boxes. There are several ways to do that but I'll leave that to you as I'm fairly sure that my first solution answers your question.
I have a DataGridViewComboBox in a DataGrid. One of the other columns allows multiple lines of text to be entered.
My problem is that the dropdown in the DataGridViewComboBox expands to fill the cell. I would like the dropdown to only be one line.
Here is an examples: http://imgur.com/qX4wsuk. In this example, the first column's dropdowns should only be one line, and not fill the whole cell.
You need to set the cell style's alignment and display style:
var datagrid = new DataGridView();
var combobox = new DataGridViewComboBoxColumn();
combobox.DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.TopLeft};
combobox.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox;
MSDN on DataGridViewContentAlignment
MSDN on DataGridViewComboBoxDisplayStyle
I'm fairly new to infragistics and i need help -
i need to add a checkbox to every cell in my grid while still displaying the cell value and allow user to check/uncheck the cell-
for ex - my grid has many columns - text, datetime, numbers etc
each cell will display the text/date/number and also have a checkbox for user to check/uncheck that field
IS THIS POSSIBLE?
One possible way is to add an editor in the grid cells. For example, you can add UltraTextEditor with StateEditorButton (on the left or right as is better for your solution) in each cell like this:
private void UltraGrid_InitializeRow(object sender, InitializeRowEventArgs e)
{
if (!e.ReInitialize)
{
foreach (UltraGridCell cell in e.Row.Cells)
{
StateEditorButton checkBox = new StateEditorButton();
UltraTextEditor textEditor = new UltraTextEditor();
textEditor.ButtonsRight.Add(checkBox);
cell.EditorComponent = textEditor;
cell.Column.ButtonDisplayStyle = ButtonDisplayStyle.Always;
}
}
}
Keep in mind this will add many editors to your grid - bad performance. Other possible solution is to add via Creation Filter the check boxes to your cells.
Either way the main question is - how you will save the checked state back to your data source? If you have a boolean column for each column you actually do not need to add any check boxes. So think how you will save this information.
I have a code similar to next to load a data from a SQL query.....
Dim myDataset as new dataset = myMethod(params) 'This is a methos that fills a common dataset.
With Me.myRadDataGrid
.AutoGenerateColumns = True
.ItemsSource = myDataset.Tables(0).Rows
End With
So far so good....but when I tried to remove a line the object items do not nothing; the line do not show any exception, but nothing happend...
Me.myRadDataGrid.Items.RemoveAt(myIndex) 'Nohitng happend
Me.myRadDataGrid.Items.Remove(Me.myRadDataGrid.SelectItem) 'Nothig happend
Me.myRadDataGrid.Items.Refresh()
Me.myRadDataGrid.Rebind()
At the end the dataset collection into a RadGridView has the same elements....do not remove any row.
Thanks to all....
You need to remove the item from the ItemsSource, not from the Items collection.
So remove the item from myDataset.Tables(0).Rows, and you'll probably need to refresh the grid manually since I'm fairly sure a DataTable will not automatically raise a change notification like an ObservableCollection does when an item gets removed.