我对WinForm上的DataGridView有一个奇怪的问题。我可以通过鼠标调整所有列的大小,但对于最右边我只能收缩而不是增加大小。
有谁知道如何解决这个问题?
答案 0 :(得分:2)
这是设计的。单击/按住鼠标按钮时,鼠标将被捕获,无法离开客户区,从而阻止调整大小。你必须推动它。
我尝试不要P / Invoke来释放捕获 看看这是否适合您(当然,如果设置了任何AutoSize模式,则不会发生任何事情)。
private bool IsLastColumn = false;
private bool IsMouseDown = false;
private int MouseLocationX = 0;
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
int _LastColumnIndex = dataGridView1.Columns.Count - 1;
//Check if the mousedown is contained in last column boundaries
//In the middle of it because clicking the divider of the row before
//the last may be seen as inside the last too.
Point _Location = new Point(e.X - (dataGridView1.Columns[_LastColumnIndex].Width / 2), e.Y);
if (dataGridView1.GetColumnDisplayRectangle(_LastColumnIndex, true).Contains(_Location))
{
//Store a positive checks and the current mouse position
this.IsLastColumn = true;
this.IsMouseDown = true;
this.MouseLocationX = e.Location.X;
}
}
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
//If it's the last column and the left mouse button is pressed...
if ((this.IsLastColumn == true) && (this.IsMouseDown == true) && (e.Button == System.Windows.Forms.MouseButtons.Left))
{
// Adding the width of the vertical scrollbar, if any.
int cursorXPosition = e.X;
if (dataGridView1.Controls.OfType<VScrollBar>().Where(s => s.Visible).Count() > 0)
{
cursorXPosition += SystemInformation.VerticalScrollBarWidth;
}
//... calculate the offset of the movement.
//You'll have to play with it a bit, though
int _ColumnWidth = dataGridView1.Columns[dataGridView1.Columns.Count - 1].Width;
int _ColumnWidthOffset = _ColumnWidth + (e.X - this.MouseLocationX) > 0 ? (e.X - this.MouseLocationX) : 1;
//If mouse pointer reaches the limit of the clientarea...
if ((_ColumnWidthOffset > -1) && (cursorXPosition >= dataGridView1.ClientSize.Width - 1))
{
//...resize the column and move the scrollbar offset
dataGridView1.HorizontalScrollingOffset = dataGridView1.ClientSize.Width + _ColumnWidth + _ColumnWidthOffset;
dataGridView1.Columns[dataGridView1.Columns.Count - 1].Width = _ColumnWidth + _ColumnWidthOffset;
}
}
}
private void dataGridView1_MouseUp(object sender, MouseEventArgs e)
{
this.IsMouseDown = false;
this.IsLastColumn = false;
}
答案 1 :(得分:0)
我也遇到了这个问题,发现.NET dgv无法处理此问题确实令人讨厌。我尝试了其他建议的解决方案,但是即使单击了最后一个col的调整大小区域,它也不会始终触发,即使您没有单击标题,它也会触发。
我想出了这种快捷方法,仅当您单击最后一列的标题时才调整大小。它使用CellMouseMove,因此您可以检查他们是否在标题上单击(RowIndex = -1),并且在他们单击最后一个列上的鼠标左键时仅会打扰(检查DisplayIndex是否为最右边的列,因为他们可能已经对列进行了重新排序。
它假定列标题右侧边缘的左右两侧有五个px的“缓冲区”,这是当您将鼠标悬停在col标题右侧时,出现“调整大小”光标的情况。我发现这是我的机器上的情况,但是在其他显示设置上缓冲区可能略有不同,因此您可能需要进行调整。我还将列宽一次增加了5像素,这比每次做到的要平滑。您也可以根据自己的喜好进行调整。
Private Sub dgvView_CellMouseMove(sender As Object, e As DataGridViewCellMouseEventArgs) Handles dgvView.CellMouseMove
If e.Button = MouseButtons.Left AndAlso e.RowIndex = -1 AndAlso dgvView.Columns(e.ColumnIndex).DisplayIndex = dgvView.ColumnCount - 1 Then
Dim iBuffer As Integer = 5, iIncrease As Integer = 5
Dim iCSWidth As Integer = dgvView.ClientSize.Width
Dim iMouseX As Integer = dgvView.GetColumnDisplayRectangle(e.ColumnIndex, True).X + e.X
If dgvView.Controls.OfType(Of VScrollBar)().First().Visible Then iCSWidth -= SystemInformation.VerticalScrollBarWidth
If iMouseX >= iCSWidth - iBuffer AndAlso iMouseX <= iCSWidth + iBuffer Then
dgvView.HorizontalScrollingOffset += iIncrease
dgvView.Columns(e.ColumnIndex).Width += iIncrease
End If
End If
End Sub
此方法的唯一缺点是,如果将最后一列移到右侧(不调整其大小),它仍然会触发。如果单击col的中间并开始向右移动,一旦到达边缘,它将认为您正在调整大小并开始调整大小。坦白说,我对此并不在意。如果他们将最右边的列移到右边并且已经到达屏幕的边缘,那么开始调整它的大小几乎是有意义的,但是我怀疑我是否还会遇到尝试这样做的用户。
我本可以避免这种行为,但是当他们第一次单击鼠标时(并设置一个布尔变量来存储它们),它需要向CellMouseDown和CellMouseUp添加更多代码以检查它们是否在“调整大小”范围内。 ,则每次移动鼠标时都要重新检查它们是否仍在调整大小范围内,然后在鼠标向上移动时将其关闭。问题是,有多种方法可以触发CellMouseUp事件(例如,在调整大小时点击esc或另一个获得焦点的窗口会绕过cellmouseup事件)。然后您的var保持为True,只需将鼠标移到最右边的列标题上,即可开始调整大小。
我应该注意,向右移动鼠标而不根本不上下移动鼠标不会触发dgv的CellMouseMove或MouseMove事件。这是因为鼠标实际上并没有“移动”(因为它已经到达dgv的边缘)。因此,如果您的用户非常缓慢地向右移动鼠标(根本不上下移动),则不会发生任何事情。大多数人在左右移动鼠标时会上下移动一点,所以这不是什么大问题。我什至没有去研究如何解决这个问题(如果可能的话,因为我的dgv延伸到了表格的最右边,所以Form_MouseMove事件可能不会触发)。
换句话说,我确定有一个更复杂的方法可以解决每个小问题,但是我决定不浪费时间,在各种事件中放置大量额外的代码,只是为了做到这一点。完善。上面的方法简单,简短,涵盖了99%的用例,并且可能永远不会让用户陷入循环。