0

I have a DataGridView control and a Panel control placed next to each other with the same height, and both of them have a vertical scrollbar scrollable to the same distance. What I want to achieve is, I control the scrollbar on the DataGridView and move the scrollbar of the Panel the same degree each time.

I found some examples where both controls are DataGridView's but in my case, one is a Panel. I tried the following:

//Inside a for loop
myDGV[i].Scroll += (sender, e) => {
    if(e.ScrollOrientation == ScrollOrientation.VerticalScroll)
    {
        int val = myDGV[i].FirstDisplayedScrollingRowIndex; //Error on this line
        myPanel[i].VerticalScroll.Value = val;
    }
};

but it gives an error:

IndexOutOfRangeException was unhandled.
Index was outside the bounds of the array.

I also found Using one scroll bar to control two DataGridView and tried the following:

//This is also inside a for loop
myDGV[i].Scroll += (sender, e) => {
    myPanel[i].VerticallScrollBar.Value = e.NewValue;
};

but it gave me the same error. I have 4 instances of each (DataGridView and Panel, and each i corresponds to each other's. Panel's are declared correctly, but I am not sure why I am getting this error.

Can anyone help please?

J.Doe
  • 329
  • 3
  • 14
  • You cannot use the variable i inside the delegate - by the time the event is raised it will not have the expected value. Put a break point on the error line & check for yourself. – PaulF Oct 16 '17 at 16:38

1 Answers1

1

You should be getting a warning in your code regarding "Access to modified closure" on your use of variable i inside the delegates.

What is happening is your delegate is using the local variable i, which will most likely have changed it's value before the event is raised (probably 1 more than your array length). Also, all events will be using exactly the same value of i.

The answer is to create a new integer variable INSIDE the for loop, initialised to the current value of i. Make sure you do not modify this integer after you have added the delegate. All data grid views will be using their own copies of the variable which will have the correct value.

Try something like the following as a solution :

for (int i = 0; i < myDGV.Length; i++)
{
    int ii = i;

    myDGV[i].Scroll += (sender, e) => {
        if(e.ScrollOrientation == ScrollOrientation.VerticalScroll)
        {
            int val = myDGV[ii].FirstDisplayedScrollingRowIndex;
            myPanel[ii].VerticalScroll.Value = val;
        }
    };
}
PaulF
  • 6,673
  • 2
  • 18
  • 29
  • Thank you for your answer. Right now, my event is inside a for loop, using the value of i. What you mean is create another for loop inside which I declare the event? – J.Doe Oct 16 '17 at 16:55
  • See my code - you need to create a new integer inside the for loop, not use another for loop. Note that i have called this integer ii & that is used inside the delegate. The delegate is effectively creating a reference to the integer you are using, if it's value changes it will not be using the value at creation of the delegate but the value at the time it is called. – PaulF Oct 16 '17 at 16:56
  • Thank you! It did stop the error from happening, and it does move the scrollbar on the `Panel` when I move the scrollbar on the `DataGridView`. – J.Doe Oct 16 '17 at 17:32