2

In my C# program I have a windows form (Winforms) containing a datagridview. The last column of this datagridview is a datagridviewcomboboxcolumn, and each comboboxcell (in each row) has its own datasource.

As there can be a lot of rows, I want to make a binding to populate the datagridview quickly. I already tried to bind the first columns then populate the datasources of the comboboxes afterwards (in the RowsAdded event), but it takes too much time.

My class Data is as follows :

public class Data
    {
        public string _aaa { get; private set; }

        public string _bbb { get; private set; }

        public string _ccc { get; private set; }

        public List<Room> _rooms_list { get; private set; }
...
}

And the Room class contains the following members :

public ElementId Id { get; }
public virtual string Name { get; set; }

When the datasource of the datagridview is bound to a list of Data objects, I want the corresponding comboboxcell to be filled with the corresponding list of Room objects, with Name as DisplayMember and Id as ValueMember.

I searched on the web but didn't find the answer if it's possible or not.

Thanks a lot for your help.

Edit

More info : I want to let the user select the desired Room among a list of detected/found Rooms, so that's why I chose comboboxes. The results of my calculation already are shown as strings in two of the (bound) string columns.

I also want to make the whole thing sortable, so I use a SortableBindingList to bind the DGV with the list of Data objects : mainDataGridView.DataSource = new SortableBindingList<Data>(_data);

M.V.
  • 177
  • 9
  • winforms of wpf? – Mong Zhu Jun 20 '17 at 08:06
  • Could you post some code of XAML or how you create your datagridview? – Keyur PATEL Jun 20 '17 at 08:14
  • You stated in a comment that… _”Each comboboxcell contains between 1 and 4 room items. But there can be many rows.”_... If this is the case, then, the posted class `Data` not only appears to be missing a `Room` value variable, but it seems awkward for the `Data` object to contain MULTIPLE `Room` values attached to that object. Since these MULTIPLE `Room` values are used for a `ComboBox` cell in the grid, it would appear only ONE (1) value would be needed for that `Data` object for each row.???? – JohnG Jun 20 '17 at 11:27
  • Example 1) If the combo box list has “Room1”, Room2” and “Room3”… where would the `Data` object keep what the user selected? If the combo box contains the values above… where in the `Data` object are you putting this value to show what `Room` the user selected? – JohnG Jun 20 '17 at 11:27
  • Example 2) Each row may have different values in the combo boxes, however, after the grid is filled, each rows combo box cell would display only ONE (1) of the values in the combo box. Given this, it would appear the `Data` class is missing this selected `Room` value for that `Data` object. Also as stated above, it seems awkward to have EACH `Data` object contain values that it will NEVER use… i.e. the values in its `List _rooms_list` that were NOT selected by the user. – JohnG Jun 20 '17 at 11:28
  • I am curious as to what determines what values should be in the combo boxes. I am guessing there may be a better way to do this without having to keep multiple `Room` values in each `Data` object when it appears only one (1) is needed. – JohnG Jun 20 '17 at 11:28
  • @JohnG You are right on many points. I made this Data class to represent the results of my program calculation. The results : strings and a list of Room objects (this class is not mine, I work with another API). I want the user to be able to choose one Room among the proposed ones. So I thought about comboboxes. By default I want to set the selected Room in the combobox to be the first of the list. – M.V. Jun 20 '17 at 11:50
  • Your comment… _”By default I want to set the selected Room in the combobox to be the first of the list.”_ … this is not a problem, but this still does not explain WHAT the combo box should initially contain? From your question, it appears there may be different values in each combo box…. What determines what values should be in the combo box? – JohnG Jun 20 '17 at 11:58
  • The values in the combobox should be the items of `_rooms_list`, with the first one selected. As I said in my initial post : "I want the corresponding comboboxcell to be filled with the corresponding list of Room objects, with Name as DisplayMember and Id as ValueMember." – M.V. Jun 20 '17 at 12:37
  • I've [done this before](https://stackoverflow.com/a/36289642/3773066) with a nested list of strings, but the concept is the same. – OhBeWise Jun 21 '17 at 14:07

1 Answers1

0

If you have many rooms in your list, it will be slow to create a new combo-box for each cell as you're already experiencing. I recommend creating one combo-box in code and then adding it to each cell.

Edit: If you're only using the grid for display, you can enhance the performance by simply displaying the rooms as text instead of combo-boxes. You can then denote the selected room by changing the font style (e.g. bold) or color, or by adding some symbol (e.g. asterisk) or word (e.g. [selected]). Separate each room with a new line. Here is an example function, but I don't know how your rooms are selected, so let's assume that you have a bool Selected { get; set; } in your Room class:

string ListRooms(List<Room> rooms){
    string result = "";
    foreach(Room r in rooms){
        result += r.Selected ? "* " : "";
        result += r.Name + "\r\n";
    }
    return result;
}

Now in the OnRowsAdded event, you can call this function and display the result in a simple text cell.

Edit 2: If you're allowing the users to select a room from the list of available rooms, and this list is different from one row to another, then combo-boxes are what we usually use for that purpose. However, if you have many rows then it takes longer to load like you're experiencing.

In that case, you're best bet is to not load the combo-boxes at the beginning. Leave them empty and when the user clicks on a combo-box to select a room, use Ajax to fetch the list of rooms for that row from the server and populate the combo-box using JavaScript. This solution will perform well, but the page may become a little heavy if the user has to select a room for all rows. I believe that all modern browsers will still be capable of handling it smoothly, but it might become and issue if your users use your web application on a mobile device.

Alternatively, you can use popups instead of combo-boxes. Replace the combo-boxes with buttons or links. They can read something like "Select a Room". When the user clicks on the button/link, use Ajax to load a popup with a list of available rooms for that row. The user selects a room from the list and clicks the button to close the popup then you display the select room using JavaScript either on the button/link that's used to open the popup, or in a separate column for the selected rooms which can be initially blank. This solution is easier to implement (you can use jQuery or Bootstrap), more flexible (you can display whatever you want on the popup), and performs perfectly regardless of the number of rows.

Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
  • Each comboboxcell contains between 1 and 4 room items. But there can be many rows. – M.V. Jun 20 '17 at 09:18
  • You mean the values in the combos are not the same? Is it not like a list of options to choose from? It seems from your comment like it is the list of selected values. If so, where are these values coming from? – Racil Hilan Jun 20 '17 at 09:29
  • No, the values are Room instances. I don't know in advance which Rooms will be associated to each row. This DGV is to show results. – M.V. Jun 20 '17 at 09:31
  • Oh, I see. You should mention this in your question. I thought the grid was for editing. Since it is for display only, why are you using combobox? You can simply Show the list of rooms as text. You can denote the selected room by changing the font style (e.g. bold) or color, or by adding some symbol (e.g. asterisk) or word (e.g. [selected]). Separate each room with a new line. I will edit my answer. – Racil Hilan Jun 20 '17 at 17:09
  • Sorry, I was not clear enough, the grid is to show results AND let the user select the desired Room for each row. Perhaps there is a better way to do this, without comboboxes... – M.V. Jun 21 '17 at 07:08
  • Alright, now it is clear. So the list of rooms is different from one row to another, and the user can select a room from the list for each row. Yes, combo-boxes are what we usually use for that purpose. See my second update for solutions. – Racil Hilan Jun 21 '17 at 12:53
  • Thanks for your proposal, but I really need to have a default (selected) Room value in the combobox, so that if the user clicks OK, the next action will perform something with the default Rooms. – M.V. Jun 21 '17 at 12:58
  • That's fine. You can do that with both approaches that I mentioned, but in this case the second approach becomes even better. With the first approach, you can load only the default room in each combo-box, and then load the rest when you click. With the second approach, you can display the default room (either on the button/link or in the separate column), while the popup functionality stays the same. – Racil Hilan Jun 21 '17 at 13:34
  • And in all cases, if you need the room ID for further processing, then you can save it in a hidden field attached to each row. – Racil Hilan Jun 21 '17 at 13:35
  • Does loading the default room only instead of the 1-to-4 proposals will save some time ? Not sure because what costs time is looping through each row (to set each Datasource). – M.V. Jun 21 '17 at 13:53
  • It saves lots of time, especially in the second approach (the popups). You will not set datasrource initially. Manually add the default room to the combo-box in first approach, or display its name and save its ID in second approach (which is exactly the same as displaying your other columns, just an additional column for default room). – Racil Hilan Jun 21 '17 at 15:00
  • I am doing what you say on the 2nd approach. I use a DataGridViewButtonColumn, and set each button's text to the default room name initially. That works fine and loads fast. Now I have to figure out what to show when the user click on the button to select another Room. What would you advise ? A new form containing a set of radiobuttons ? I am not working on a website but on a specific desktop application plugin, and I must use C# (and winforms). – M.V. Jun 21 '17 at 15:49
  • Oh, I see. Desktop application is even easier as you don't have to use JavaScript or frameworks for popups. Yes, you display a new form popup. It's up to you what to use on the form, radio buttons are fine, but you can also use a simple list box. – Racil Hilan Jun 21 '17 at 15:57
  • I managed to solve all of this thanks to your help, using buttons and a new selection form if the user wants to choose another Room. – M.V. Jun 22 '17 at 11:57