listview控件_自动调整.NET ListView控件的大小

这篇博客介绍了一种通过扩展方法动态调整.NET ListView控件大小的技术,以避免显示垂直滚动条。作者通过一系列步骤,包括初始化控件大小、在while循环中增长控件、调整滚动条等,实现控件的自动适配。此外,还提到了如何限制控件的宽度以防止过度增长,并提供了自动调整列宽的额外功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

listview控件

I was recently working on a project that uses a list view control. I had to dynamically add items based on a configuration file so I could not set the height of the list view at design time unless I wanted scroll bars. For my application, I wasn't expecting a large amount of items. Therefore, I wanted to always size the list view to just the right amount so that it would not show a vertical scroll bar. Unfortunately, there is no autosize property of the list view control. I was able to write a series of extension methods that let you auto size the list view control. This could be done by inheriting from the list view control instead. I chose the extension method model for this article so that you don't have to add a control to your tool box.

我最近正在研究一个使用列表视图控件的项目。 我必须根据配置文件动态添加项目,因此除非设计滚动条,否则在设计时无法设置列表视图的高度。 对于我的应用程序,我没想到会有很多东西。 因此,我想始终将列表视图的大小调整为适当的大小,以使其不会显示垂直滚动条。 不幸的是,列表视图控件没有autosize属性。 我能够编写一系列扩展方法,使您可以自动调整列表视图控件的大小。 这可以通过从列表视图控件继承来完成。 我为本文选择了扩展方法模型,因此您不必在控件框中添加控件。

For maximum control, I separated the height and width functionality and then included an all encompassing method that calls both. For added flexibility, I allow you to set the number of items you want to display. To autosize it fully, pass in the number of items that the list view control contains.

为了最大程度地控制,我分离了高度和宽度功能,然后包括了一个同时调用两者的包围方法。 为了增加灵活性,我允许您设置要显示的项目数。 若要完全自动调整大小,请传入列表视图控件包含的项目数。

1.创建扩展方法框架 (1. Create the Extension Method Framework)

using System;
using System.Windows.Forms;
namespace ListViewExtensionMethods
{
   public static class ListViewExtensions
   {
      public static void AutoSizeControlHeight ( this ListView lv, int maxItemsToShow, bool adjustForHorizontalScrollBar)
      {
      }
      public static void AutoSizeControlWidth ( this ListView lv, bool adjustForVerticalScrollBar )
      {
      }
      public static void AutoSizeControl ( this ListView lv, int maxItemsToShow, bool adjustForHorizontalScrollBar, bool adjustForVerticalScrollBar )
      {
      }
   }
}

As you can see, we've created 3 functions, one for each dimension and then one that brings it all together. We'll first work with the Height function

如您所见,我们创建了3个功能,每个功能一个,然后将所有功能都整合在一起。 我们将首先使用“高度”功能

Within the height method

内高法

2.声明我们的变量 (2. Declare our variables)

int positionBefore = 0;
int positionAfter = 0;

3.确保列表视图中有项目。 (3. Make sure that the list view has items.)

if (lv.Items.Count == 0)
    return;

4.如果需要,按比例缩小最大项目数 (4. Scale down the max # of items if needed)

Ensure the max number of items to show is not greater than the number of items in the control

确保要显示的最大项目数不大于控件中的项目数

if (maxItemsToShow > lv.Items.Count)
    maxItemsToShow = lv.Items.Count);

Now we are ready to start sizing the control dynamically.

现在,我们准备开始动态调整控件的大小。

5.初始化控件的大小 (5. Initialize the size of the control)

Set the size of the listview to 1 so that it can grow from there

将listview的大小设置为1,以便可以从那里扩大

lv.Height = 1;

6.在while循环中增加控件 (6. Grow the control in a while loop)

The concept for determining the height is fairly straightforward. We scroll the first item into view and then the nth item into view over and over again. As we do this, we grow the control by one pixel. While doing that, we record the nth items position when the first item is in view and then when the nth item is in view. Once those two numbers are the same, we have grown enough.

确定高度的概念非常简单。 我们一遍又一遍地滚动第一个项目进入视图,然后滚动第n个项目进入视图。 在执行此操作时,我们将控件增加了一个像素。 这样做时,我们记录了第一个项目在查看时的第n个项目的位置,然后在第n个项目在查看时的情况下,记录了第n个项目的位置。 一旦这两个数字相同,我们就足够成长。

We can wrap our growing functionality in a while loop. The while loop will run as long as the two positions are different. To get the loop to run once, we need to make sure the two numbers are different to start. This is ok because the values are immediately overwritten once in the loop. We also need to account for the maximum size property. If this has been set, we want to stop growing once that size has been reached so we don't end up in a never ending loop (the two positions might never be the same).

我们可以将不断增长的功能包装在while循环中。 只要两个位置不同,while循环就会运行。 要使循环运行一次,我们需要确保两个数字不同才能开始。 可以,因为循环中的值会立即被覆盖一次。 我们还需要考虑最大大小属性。 如果已设置,则我们希望在达到该大小后停止增长,因此我们不会陷入永无止境的循环中(这两个位置可能永远不会相同)。

positionBefore = -1;
while (positionBefore != positionAfter && (lv.MaximumSize.Height == 0 || lv.Height < lv.MaximumSize.Height))
{
}

Within the while loop:

在while循环中:

7.加强控制 (7. Grow the control)

We first want to grow the control by a pixel. Even though this will occur before any real testing is done, this is ok because we have set the size so small that it won't matter.

我们首先要将控件增加一个像素。 即使在进行任何实际测试之前就会发生这种情况,这也是可以的,因为我们将尺寸设置得很小,以至于没有关系。

lv.Height += 1;

8.确定之前的位置 (8. Determine the before position)

We then need to determine the Y coordinate of the nth ListViewItem when the first item is in view. To accomplish this, we can use the EnsureVisible method of the ListViewItem. If the list view happens to be scrolled, ensuring this item is visible will scroll the list view back to the very top. Then we need to record the position of the nth item for later comparison. This should go without saying, but since all the collections have a zero based index, we need to subtract one from the maxItemsToShow

然后,当第一个项目在视图中时,我们需要确定第n个ListViewItem的Y坐标。 为此,我们可以使用ListViewItem的GuaranteeVisible方法。 如果列表视图碰巧被滚动,确保此项目可见,将列表视图滚动回到最顶部。 然后,我们需要记录第n个项目的位置,以便以后进行比较。 这应该不用说,但是由于所有集合都具有从零开始的索引,因此我们需要从maxItemsToShow中减去一个

lv.Items[0].EnsureVisible();
positionBefore = lv.Items[maxItemsToShow - 1].Position.Y;

9.确定后位置 (9. Determine the after position)

Now we need to determine the position of the nth item after it has been scrolled into view.

现在,我们需要确定第n个项目滚动到视图后的位置。

lv.Items[maxItemsToShow - 1].EnsureVisible();
positionAfter = lv.Items[maxItemsToShow - 1].Position.Y;
while (positionBefore != positionAfter && (lv.MaximumSize.Height == 0 || lv.Height < lv.MaximumSize.Height))
   {
      lv.Height += 1;
      lv.Items[0].EnsureVisible();
      positionBefore = lv.Items[maxItemsToShow - 1].Position.Y;
      lv.Items[maxItemsToShow - 1].EnsureVisible();
      positionAfter = lv.Items[maxItemsToShow - 1].Position.Y;
   }

10.调整滚动条 (10. Adjust for the scrollbar)

Finally, we need to adjust for the width of the horizontal scroll bar. Otherwise the last item will be cut off.

最后,我们需要调整水平滚动条的宽度。 否则,最后一项将被截断。

if (adjustForHorizontalScrollBar)
    lv.Height += SystemInformation.HorizontalScrollBarHeight;

Within the width method

内宽法

We are now ready to resize the width of the control to match the content. This is much simpler.

现在,我们准备调整控件的宽度以匹配内容。 这要简单得多。

1.重置宽度 (1. Reset the width)

Reset the width of the list view to zero so we can grow it as needed.

将列表视图的宽度重置为零,以便我们可以根据需要增加它的宽度。

lv.Width = 0;

2.增长控制力 (2. Grow the control)

We can now loop through each column and add each column width to the control.

现在,我们可以遍历每列并将每列宽度添加到控件中。

for (int i = 0; i < lv.Columns.Count; i++)
    lv.Width += lv.Columns[i].Width;

3.调整滚动条 (3. Adjust for the scroll bar)

Finally, we need to adjust for the vertical scroll bar, otherwise we'll cut the last column off and the horizontal scroll bar will be visible

最后,我们需要调整垂直滚动条,否则我们将最后一列剪掉,水平滚动条将可见

if (adjustForVerticalScrollBar)
    lv.Width += SystemInformation.VerticalScrollBarWidth;

The last thing we need to do is call these two methods in the AutoSizeControl method so that it does both. You may see the attached code for that example.

我们需要做的最后一件事是在AutoSizeControl方法中调用这两个方法,以便它们都能做到。 您可能会看到该示例的附件代码。

Full Code

完整代码

using System;
using System.Windows.Forms;

namespace ListViewExtensionMethods
{
    public static class ListViewExtensions
    {
        public static void AutoSizeControlHeight ( this ListView lv, int maxItemsToShow, bool adjustForHorizontalScrollBar )
        {
            int positionBefore = 0;
            int positionAfter = 0;

            if (lv.Items.Count == 0)
                return;

            if (maxItemsToShow > lv.Items.Count)
                maxItemsToShow = lv.Items.Count;

            lv.Height = 50;

            while (positionBefore != positionAfter && (lv.MaximumSize.Height == 0 || lv.Height < lv.MaximumSize.Height))
            {
                lv.Height += 1;

                lv.Items[0].EnsureVisible();
                positionBefore = lv.Items[maxItemsToShow - 1].Position.Y;

                lv.Items[maxItemsToShow - 1].EnsureVisible();
                positionAfter = lv.Items[maxItemsToShow - 1].Position.Y;
            }

            if (adjustForHorizontalScrollBar)
                lv.Height += SystemInformation.HorizontalScrollBarHeight;
        }

        public static void AutoSizeControlWidth ( this ListView lv, bool adjustForVerticalScrollBar)
        {
            lv.Width = 0;
            for (int i = 0; i < lv.Columns.Count; i++)
                lv.Width += lv.Columns[i].Width;

            if (adjustForVerticalScrollBar)
                lv.Width += SystemInformation.VerticalScrollBarWidth;
        }

        public static void AutoSizeControlColumnWidth ( this ListView lv, bool adjustForVerticalScrollBar)
        {
            int resizeByContent = 0;
            int resizeByHeader = 0;

            for (int i = 0; i < lv.Columns.Count; i++)
            {
                lv.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
                resizeByContent = lv.Columns[i].Width;

                lv.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
                resizeByHeader = lv.Columns[i].Width;

                lv.Columns[i].Width = (resizeByHeader > resizeByContent) ? resizeByHeader : resizeByContent;
            }
        }

        public static void AutoSizeControl ( this ListView lv, int maxItemsToShow, bool adjustForHorizontalScrollBar, bool adjustForVerticalScrollBar )
        {
            lv.AutoSizeControlColumnWidth();
            lv.AutoSizeControlWidth(adjustForVerticalScrollBar);
            lv.AutoSizeControlHeight(maxItemsToShow,adjustForHorizontalScrollBar);
        }
    }
}

Placing limits on size

限制大小

There is the potential that if you have too many items, the control might grow too wide. The ListView provides us with a maximum size property. If you set this, then the control will only grow up to that point and not further. In the case of adjusting the height, we had to make sure we didn't get stuck in a never ending loop. The width however does not need such a check because it is only looping through the columns, which has a finite number of iterations. When attempting to grow past the maximum size, you will not see an error. Instead, the control will just set the dimension to the maximum size.

如果项目过多,则可能会导致控件范围扩大。 ListView为我们提供了最大尺寸属性。 如果您设置了此选项,则控件将仅增长到该点,而不会进一步增长。 在调整高度的情况下,我们必须确保我们不会陷入永无止境的循环中。 但是宽度不需要这样的检查,因为它只是循环遍历具有有限次数的迭代的列。 尝试超过最大大小时,您不会看到错误。 而是,控件将尺寸设置为最大尺寸。

Ending Note

尾注

I also like to auto adjust the actual column widths. That was outside of the scope of this article, but in the code I've included a function that does that as well. My AutoSizeControl also calls this function automatically but this is just my preference.

我还喜欢自动调整实际的列宽。 那超出了本文的范围,但是在代码中,我包含了一个可以做到这一点的函数。 我的AutoSizeControl也自动调用此函数,但这只是我的偏爱。

翻译自: https://www.experts-exchange.com/articles/1782/AutoSize-a-NET-ListView-Control.html

listview控件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值