C#:DataGridView右侧和滚动条的额外空间

时间:2017-10-16 19:04:56

标签: c# datagridview width

我有DataGridView控件,列数会根据用户每10分钟的输入而改变。 需要做的是:

  1. DataGridView需要显示没有水平滚动条的所有列,除非它影响任何单元格内容的可读性。如果它开始隐藏单元格内容,则需要出现水平滚动条。
  2. 无论当前显示的列数是多少,无论是否显示水平滚动条,都必须填写DataGridView数据的右侧,以便不会使用空间。
  3. 无论单元格内容的长度如何,所有列宽都必须相同。 (一个单元格可以有10到9999之间的整数)
  4. 所有这3个要求需要同时满足,但如果我试图满足一个要求,其他要求就会崩溃。我确信无论如何总会有至少16列。如果有更多列,则由用户决定。

    有人可以告诉我以下内容有什么问题吗?

    int countVisible = 0; //Count the number of columns displayed
    foreach(DataGridViewColumn col in myDGV.Columns)
        if(col.Visible) countVisible++;
    
    //By default, use Fill mode
    DataGridViewAutoSizeColumnMode mode = DataGridViewAutoSizeColumnMode.Fill;
    
    //I am trying to show up to 20 columns without a scrollbar
    //A horizontal scrollbar required for more than 20 columns
    //If there are more than 20 columns, use DisplayedCells mode
    if(countVisible > 20)
        mode = DataGridViewAutoSizeColumnMode.DisplayedCells;
    
    //Apply the mode to all columns
    for(int i = 0; i < myDGV.Columns.Count; i++)
        myDGV.Columns[i].AutoSizeMode = mode;  
    

    如果列数小于某个值,则此代码有效,但在大于特定值的情况下,它会缩小所有行中只有2位数字的列的宽度,并且违反了要求#3。通过缩小一些列宽,它会在右侧创建额外的空间,并且违反了#2的要求。

    我迷失了方向。有人可以帮忙吗?任何建议将不胜感激。

2 个答案:

答案 0 :(得分:2)

这些要求似乎对我来说有点模糊。一个问题是要求3 ......

” 3。无论单元格内容的长度如何,所有列宽度都必须相同。 (一个单元格可以有10到9999之间的整数)“ ...

如果所有列的宽度必须相同且至少ONE(1)单元格的值为“9999”,那么所有列都将是此宽度,无论它具有多少位数。

看起来似乎要求所有数据都显示在一个单元格中,此外...所有列都具有相同的宽度。这将需要遍历每个单元格并找到具有最大宽度的单元格以显示其所有数据,并使所有列的宽度与先前的要求保持一致。

关键是,要求所有列的大小相同并确保显示每个单元格的所有内容几乎没有问题......每列必须是最大值的宽度。任何其他情况都会破坏其中一项要求。

假设以上是正确的,另一个要求

” 2。无论当前显示的列数是多少,并且无论是否显示水平滚动条,都必须填充DataGridView数据的右侧,以便没有未使用的空间。“ ...

我相信你必须控制它。不幸的是,网格栏“填充”属性很乐意将一百列填入一个小空间。这表明您必须使网格显示宽度,计算有多少列,找到列的宽度并检查它是否适合网格显示。

这意味着列宽的MINIMUM值。如果每个列宽度设置为最小值并且所有列的总宽度大于网格宽度,那么显然您将需要一个水平滚动条。

鉴于此,找到所有列的总宽度非常容易。如果此值大于网格宽度,则水平滚动条将自动出现,除非您希望避免可能涉及调整网格大小的列的可能拆分,否则不需要执行任何其他操作。如果列的总宽度小于网格宽度...则只需将列设置为填充。以下是一个例子。

全局变量minWidth用于确保所有列都至少为此值。这是你可以通过其他方式获得的价值;在这种情况下,其目的是设置列最小宽度。

首先,检查宽度是否小于最小值,如果是,则将其设置为最小值。接下来,将每列宽度设置为给定值。最后检查所有列的总宽度是否大于网格宽度。如果列不适合网格宽度,则只需将网格设置为DisplayedCells,水平滚动条将弹出。如果列适合,则只需将网格AutoColumnSizeMode设置为Fill即可。希望这会有所帮助。

int minWidth = 40;

private int YourMethodToGetColumnWidth() {
  return myDGV.Width / myDGV.Columns.Count;
}

private void SetColumnWidths() {
  int columnWidth = YourMethodToGetColumnWidth();
  if (columnWidth < minWidth)
    columnWidth = minWidth;
  foreach (DataGridViewColumn col in myDGV.Columns)
    col.Width = columnWidth;
  int allColumnsWidth = columnWidth * myDGV.Columns.Count;
  if (allColumnsWidth > myDGV.Width) {
    myDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
  }
  else {
    myDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
  }
}

答案 1 :(得分:0)

我昨天读了你有趣的问题。考虑到这一点,在我看来,最好的解决方案是完全摆脱AutoSizeMode并为列的最小宽度创建一个变量ColMinWidth。然后获取DataGridView.Width并将其除以所需列数(略微调整,可能少2px)。如果列的计算宽度大于ColMinWidth,那么这将是列的宽度,否则使用ColMinWidth。 最后将宽度设置为所有列。

我认为这是最小的解决方案,与AutoSize不同,隐藏捕获,可靠。