0

I have two forms, in one I fill DataGridView with some rows, each row has two comboboxes.

I am able to get both value and formatted value from these cells, however when I try to copy all of this data into the next DataGridView that is in different form, I am unable to tell him which item from the ComboBox should be marked as selected.

When I was looking around I found these lines of code (unfortunately they were from 6+ years ago)

dataGridView.Rows[index].Cells[3].Value = ImageFormat.Items[1];

(dataGridView.Rows[index].Cells[3] as DataGridViewComboBoxCell).Value = ImageFormat.Items[0];

DataGridViewComboBoxCell comboboxFormat = (DataGridViewComboBoxCell)(dataGridView.Rows[index].Cells[3]);

comboboxFormat.Value = ImageFormat.Items[0];

(dataGridView.Rows[index].Cells[3] as DataGridViewComboBoxCell).Value = (dataGridView.Rows[index].Cells[3] as DataGridViewComboBoxCell).Items[0];

Unfortunately none of these worked and most if not all threw "DataGridViewComboBoxCell value is not valid" exception

Maybe it's worth to mention that the possible items are binded from database like so:

string stm = "SELECT * FROM colours";
            using var cmd = new SQLiteCommand(stm, MainWin.con);
            SQLiteDataAdapter rdr = new SQLiteDataAdapter(cmd);
            DataTable dataTableColour = new DataTable();
            rdr.Fill(dataTableColour);

            stm = "SELECT * FROM formats";
            using var cmdd = new SQLiteCommand(stm, MainWin.con);
            SQLiteDataAdapter reader = new SQLiteDataAdapter(cmdd);
            DataTable dataTableFormat = new DataTable();
            reader.Fill(dataTableFormat);

            ImageFormat.ValueMember = "id";
            ImageFormat.DisplayMember = "name";
            ImageFormat.DataSource = dataTableFormat;

            ColourImage.ValueMember = "id";
            ColourImage.DisplayMember = "name";
            ColourImage.DataSource = dataTableColour;
benhorgen
  • 1,928
  • 1
  • 33
  • 38
  • If your DataGridViewComboBoxColumns are correctly initialized (I assume `ImageFormat` and `ColourImage` are DataGridViewComboBoxCells), there's nothing you have to do: each ComboBoxCell sets the value to the underlying data source of your DataGridView. So, you just pass the DataSource to another Control (setting a Filter to the DefaultView or linked BindingSource, eventually). Or a selection of DataRow references. – Jimi Jul 15 '21 at 14:24
  • ImageFormat and ColourImage are DataGridViewComboBoxColumns (or headers i guess). When I tried to see what's in the DataSource of the DGV it was null. The second DGV has it's ComboBox columns set the same way (from database) which might be redundant or straight wrong. When you get the Value of ComboBoxCell it gives you index, so I was trying to set this index into the second DGV – Беллик Николаи Jul 16 '21 at 07:29

1 Answers1

0

Your datagridview should be bound to some datatable (let's say ImageFiles). Set ColourImage/ImageFormat combo's .DataPropertyName property to be the name of the column in the [ImageFiles] datatable that the combo should edit. Don't try to interact with the DGVCombo directly; just interact with the datatable to which the grid is bound

enter image description here

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • See also https://stackoverflow.com/questions/68346589/c-sharp-winforms-datagridview-manipulating-data-by-user-input-and-programmatica/68388489#68388489 – Caius Jard Jul 15 '21 at 13:47
  • Whole dgv is not bound, just the two combobox columns, but the datatable doesn't exist outside the function where I pull the data from database, right? Or is there a way to access it elsewhere? Also I need to basically copy the values of each cell into other dgv and .DataPropertyName is only for header? – Беллик Николаи Jul 16 '21 at 07:15
  • I did now, and I found out that I can't use Data source in my project because it's in .NET Core not Framework and it's not supported yet – Беллик Николаи Jul 16 '21 at 07:49
  • That appears not to be true: https://i.stack.imgur.com/S9fPL.png – Caius Jard Jul 16 '21 at 10:27
  • But you have created it manually, in your other post, you are talking about designer way, and if I open Data Sources (as i am going by your walkthrough) it says "this window is not supported for selected project. For steps to enable data binding, please visit: https://aka.ms/WinForms/DataBinding" – Беллик Николаи Jul 16 '21 at 10:31
  • DataSources window might not be enabled for .net core but all it does is add some lines to designer file. i.e. it writes code for you, but you can still write same code "manually" or even in other ways by clicking around the designer. One moment, and i'll demonstrate – Caius Jard Jul 16 '21 at 10:34
  • Hmm. I was going to demonstrate it visually, but I forgot what an intensely irritating worse-than-beta grade experience it is trying to do WinForms in netcore; it worked on my first run through but it now [crashes persistently](https://i.stack.imgur.com/9EkoH.gif), every time I try to set a datagridview's DataSource property using the propertygrid. I'm putting some advice for doing it code-wise. One moment – Caius Jard Jul 16 '21 at 11:01
  • Just forget it, it's not worth it, I will work it around with regular comboboxes and buttons and solve it somehow differently. Thank you very much for your help – Беллик Николаи Jul 16 '21 at 11:06
  • The windows forms designer is not magical; all it does (when it's not crashing) is write code for you in the .Designer.cs file. There is nothing that stops you writing the same code yourself in any other file. You've made your dataset; just wire it up in code (or switch to a .net framework proejct and use the designer, because it actually works, and copy the generated code into your netcore project). It looks like that: https://i.stack.imgur.com/71JJX.gif – Caius Jard Jul 16 '21 at 11:30
  • ps; one wouldn't really ever have a textbox column and a combo column bound to the same underlying datatable column, in the same grid. It looks "glitchy" because you need to switch row to commit the value chosen in the combo into the underlying row so that it then shows in the textbox and vice versa. Ordinarily you;d just have the combo, and the data is committed on leaving the row – Caius Jard Jul 16 '21 at 11:32
  • Code and explanation: https://i.stack.imgur.com/FD53Y.png – Caius Jard Jul 16 '21 at 11:37
  • I know that you can write the same stuff in designer in other files, i do sometimes have to do that. I chose Core because I think it should have longer support than Framework (But what do I know) so I'd prefer not going back to it. And I did get to the point you showed in the gif, problem was when I wanted to copy these rows into second dgv and have the comboboxes matching selected items. As to the p.s. I don't have any other columns bound, only the two combos, each to it's own datatable – Беллик Николаи Jul 16 '21 at 11:42
  • But there's the core problem - youre not using the DataGridView in the right way; youre putting data into it directly and then asking "how do i get this data into another grid" - if you put your datainto a data container and bound the grid to it you could bind any number of grids to it.. – Caius Jard Jul 16 '21 at 11:43
  • So I should bind all columns to something? And if I change the data in grid, or add a new row it will get updated in the bound container? Can I bind dgv to a list? Because I have a list of structures I work with. Also I am not sure how to bind the combobox. – Беллик Николаи Jul 16 '21 at 11:50
  • Yes, you put your data in something (datatable, bindinglist..) that you can pass around. See here I have a Form1 and then 4 Form2 and they all update automatically as I change Form1. Form2 doesnt even have a combo, but they are updating as I'm changing the combo in Form1: https://i.stack.imgur.com/vtpj0.gif - yes, you bind all columns - here DGV is binding and creating columns auto for me because autogeneratecolumns is TRUE, but also I add another column of my own (the combo) and bind it. Code and explanation for that was above https://i.stack.imgur.com/FD53Y.png – Caius Jard Jul 16 '21 at 11:59
  • Would you show me how you made the dataset? Also you connected the combo with textbox I need them separate – Беллик Николаи Jul 16 '21 at 12:16
  • I put a demo project in the answer - the icon of a zip file; save it to your desktop, rename it as .zip and open it - it's the code I used in the animgif above – Caius Jard Jul 16 '21 at 12:18
  • The combo is connected to the textbox in the Age column , it is not connected to the textbox in the Name column. If I had put 10 columns in the datatable, the grid would have made 10 columns. I would have then added an 11th. If I had removed the Age column from the grid it would have left behind just a combo for setting the age – Caius Jard Jul 16 '21 at 12:20
  • If i download the "picture" I get corrupted zip. And my question regarding combobox was your got affected by textbox (and vice versa) which I don't want. Also you don't have the combobox in the second dgv? – Беллик Николаи Jul 16 '21 at 12:27
  • I just downloaded and tested it with winrar - it worked fine - windows explorer can't handle it. Try a better zip program? – Caius Jard Jul 16 '21 at 12:33
  • The Age text box column and the combo box column are binded to the SAME THING (they both bind to the Age column of Person datatable), so of course they affect each other. If you don't want it, then don't bind to the same thing.. I'm sure in your real app you will not have Age as a combo, it was just to demonstrate it. DGV auto generated the Age column because there is an Age column in Person. I never removed it, I just added another thing also binded to Age, to show you how the column says "adult" in the combo but it sets `1` into the Person table – Caius Jard Jul 16 '21 at 12:36
  • I know I don't have a combo in the second DGV on Form2.. because I never added one! The code for form 2 and the code for form 1 are separate object, in separate files, and are nothing to do with each other. Form 2 doesn't have any code that adds a combo. Both forms have a datagridview called `dataGridView1` but that is absolutely meaningless and nothing to do with why they share data; that is just a variable name - they share data because they both have a .DataSource that points to the same person datatable (because it was passed into form2's constructor)] – Caius Jard Jul 16 '21 at 12:37
  • Okay, I think I am following for now. If I understood correctly the combobox needs to have separate data table? – Беллик Николаи Jul 16 '21 at 12:41
  • Also something I don't really know what to do with, you bind the source to dgv and then to the combobox you create, but I already have these combos in the dgv, so I can't just give it a datasource can i? – Беллик Николаи Jul 16 '21 at 13:04
  • Okay I have tried it out, and found out that i can't do that, because the datatable creates new headers (so in my case I had all of them twice) So I think i pretty much answered all of my questions – Беллик Николаи Jul 16 '21 at 13:10
  • The datatable doesn't create new headers, the grid creates the headers. The grid will have as many columns as you add into it, plus as many headers it created itself because AutoGenerateColumns was true. If you don't want the grid to auto create columns, set that property to false. You can also independently create your own columns – Caius Jard Jul 16 '21 at 13:35
  • The combo has a separate datatable to drive its item list. It then pushes the data the user chooses (from that table) into the main table. The grid is bound to the main table. The combo is bound to the small "list values" table, and vitally the DataProeprtyName on the combo specifies what column in the main (Person) the combo shall edit using the value it ifinds in its own list (DispVal) – Caius Jard Jul 16 '21 at 13:38
  • Pay careful attention to the code: there is one DataSet, but it contains two separate DataTables - Person and DispVal. Grid is bound to Person. Combo is bound to DispVal. Combo uses the Val column (in DispVal) to edit the Age column (in Person) – Caius Jard Jul 16 '21 at 13:39