2017-10-16 93 views
1

我有一个DataGridView控件,列的数目根据用户每10分钟的输入而改变。 什么需要实现的是:C#:DataGridView在右侧和滚动条上的额外空间

  1. DataGridView需要显示所有列没有水平滚动条,除非它影响到的任何单元格内容的可读性。如果它开始隐藏单元格内容,则需要出现水平滚动条。
  2. 无论当前显示多少列,也无论是否显示水平滚动条,必须填写DataGridView数据的右侧,以便没有未使用的空间。
  3. 无论单元格内容的长度如何,所有列宽都需要相同。 (A细胞可以从10到9999的整数)

所有的这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条要求。

我很迷茫和卡住。有人可以帮忙吗?任何意见将不胜感激。

+0

没有经过测试,JohnG的解决方案对我来说看起来是正确的。如果你的需求被改变为在列上有不同的宽度,那么我建议看看我在这里提供的答案:[水平滚动条消失设置最后一个列大小填充](https:// stackoverflow。 com/a/27870091/3773066) – OhBeWise

回答

2

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

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

如果所有的列必须是相同的宽度并且至少有一个(1)单元格的值为”9999“,那么所有的列将是这个宽度,不管它有多少个数字。

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

问题的关键是,,要求所有列具有相同的大小,并确保显示的每一个细胞的所有内容都没有留下来的问题...每列将是最大值的宽度。任何其他情况都会破坏其中一项要求。

假设以上是正确的,其它要求

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

我很有信心你将不得不控制这一点。不幸的是,网格栏“填充”属性会很乐意将一百列放入一个小空间。这表明,你将获得显示宽度的网格,算多少列有,找到列的宽度和检查,看看它是否适合在网格显示。

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

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

全局变量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; 
    } 
} 
+0

谢谢!能够解决这个问题!你是个天才。 –

0

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

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