0

I have several DataGridViews which perform similar operations on different types of data. For one of these operations, I want to select a row in a DataGridView and move it up or down one index. These grids are data-bound to a BindingList<T> where T is the object type of interest for each DataGridView. Operations performed on the DataGridView should be reflected in the data-source.

The reorder operation is called from a click event, sent by a Button in a DataGridView. The Button object and functionality is shared between all grids and is added to a grid's control when the mouse hovers over said grid. The function call is as follows:

protected void UpButtonClick(object sender, EventArgs e)
{
    DataGridView parent = (sender as Button).Parent as DataGridView;

    /* Code to move row up */
}

If the following code is used to reorder the rows, a System.InvalidOperationException: 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.' occurs because each grid is data-bound.

DataGridViewRow row = parent.Rows[gridRow];
parent.Rows.RemoveAt(gridRow);
parent.Rows.Insert(gridRow - 1, row);

Trying to modify the data-source is problematic too, because the type of the elements is unknown. Casting to type BindingList<T> requires that T be specified. Similarly, BindingList's inheritance and implements all involve declaration of element type.

object row = (parent.DataSource as BindingList)[gridRow];
(parent.DataSource as BindingList).RemoveAt(gridRow);
(parent.DataSource as BindingList).Insert(gridRow - 1, row);

Furthermore, it seems like poor code to create a collection of types and index each grid to specify which type corresponds to which data-source. Since the operations in question are not dependent on element type, and furthermore, do not mix element types between grids, it should stand to reason that a generic data source should be able to be reordered without knowing additional details about the data source.

How can I programmatically reorder elements in a data-bound DataGridView or BindingList without explicitly knowing the data type of each element?

Groger
  • 532
  • 3
  • 15
  • Use a BindingSource. You can swap the internal `IList`'s items, it's already a `BindingList` (so you don't need to specify the Type of `T`). It doesn't work with a DataTable. – Jimi Feb 01 '21 at 15:37
  • Since I am manipulating the data-source itself, using `BindingSource` is not an option, as it does not automatically update controls when its source is changed. https://stackoverflow.com/a/4675939/12297767 – Groger Feb 01 '21 at 16:27
  • ??? Since when? Set the DataSource of a BindingSource to a `BindingList`, then use the BindingSource as the DataSource of your DataGridView or the DataBinding of other Controls (also, you should check what the BindingSource creates when you set its DataSource. But I've already mentioned that) -- After that: `var bs = ([Your DataGridView].DataSource as BindingSource); var obj4 = bs.List[4]; bs.List.RemoveAt(4); bs.Insert(3, obj4);`. If you store the BindingSource object, you don't need `var bs = ([Your DataGridView].DataSource as BindingSource)`, just use the stored B.S. object. – Jimi Feb 01 '21 at 16:36
  • Hmm...that seems to work, though it's feels like a roundabout way of doing it. @Jimi – Groger Feb 01 '21 at 16:37
  • 1
    No, that's not a *workaround*. That's a standard for databindings. Same thing the Visual Studio tools do when you create DataSource and DataBindings using the Designer. -- The BindingSource is the usual tool you use to bind different components that have different databindings to the same source if data. – Jimi Feb 01 '21 at 16:39

0 Answers0