dennismagno / metroframework-modern-ui

My humble attempt to bring the new Modern UI alias Metro UI of Windows 8 to .NET Windows Forms applications.
http://dennismagno.github.io/metroframework-modern-ui
Other
861 stars 1.08k forks source link

Exception InvalidOperationException in OnMouseWheel of MetroGrid with hidden rows #111

Closed OToussaint closed 4 years ago

OToussaint commented 4 years ago

Hello,

This code

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (this.RowCount > 1)
            {
                if (e.Delta > 0 && this.FirstDisplayedScrollingRowIndex > 0)
                {
                    this.FirstDisplayedScrollingRowIndex--;
                }
                else if (e.Delta < 0)
                {
                    this.FirstDisplayedScrollingRowIndex++;
                }
            }       
        }

is throwing "InvalidOperationException: FirstDisplayedScrollingRowIndex property cannot be set to an invisible row." when some rows of the MetroGrid are hidden.

Can you fix, please?

OToussaint commented 4 years ago

Duplicate of #81

OToussaint commented 4 years ago
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);

            int incrementBy=0; // Don't know yet the direction
            int firstDisplayedRowIndex = Math.Max(this.FirstDisplayedScrollingRowIndex + (e.Delta > 0 ? -1 : 1), 0); // Default next is current +/- 1

            if (this.RowCount > 1) // It is worthless to do all this if there is no row in the grid
            {
                if (e.Delta > 0 && this.FirstDisplayedScrollingRowIndex > 0) // Are we going up?
                {
                    incrementBy = -1;
                }
                else if (e.Delta < 0) // Or down?
                {
                    incrementBy = 1;
                }

                while (!this.Rows[firstDisplayedRowIndex].Visible) // Oops, row is invisible. Time to jump to a visible row.
                {
                    if (firstDisplayedRowIndex < 1) // Go to first displayable row
                    {
                        firstDisplayedRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); 
                    }
                    else if (firstDisplayedRowIndex > this.Rows.GetLastRow(DataGridViewElementStates.Visible)) // Go to last displayable row
                    {
                        firstDisplayedRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible);
                    }
                    else // Try next row, maybe it is visible?
                    {
                        firstDisplayedRowIndex += incrementBy;
                    }
                }

                // As we just found a visible candidate, move to it.
                this.FirstDisplayedScrollingRowIndex = firstDisplayedRowIndex;

            }
        }

Is a valid solution but maybe not suitable for the initial developer.

By the way, there is another _grid.FirstDisplayedScrollingRowIndex = 0; that should be replaced by _grid.FirstDisplayedScrollingRowIndex = _grid.Rows.GetFirstRow(DataGridViewElementStates.Visible); in the void _scrollbar_Scroll(object sender, System.Windows.Forms.ScrollEventArgs e)

tiok-cek1 commented 4 years ago
protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);

            int incrementBy=0; // Don't know yet the direction
            int firstDisplayedRowIndex = Math.Min(Math.Max(this.FirstDisplayedScrollingRowIndex + (e.Delta > 0 ? -1 : 1), 0), this.RowCount-1); // Default next is current +/- 1

I added Min function from your solution. That solved my problem. Thanks