views:

20

answers:

1

I have a panel which contains a TableLayoutPanel which itself contains a number of ListViews and Labels.

What I'd like is for each list view to resize to fit all of it's contents in vertically (i.e. so that every row is visible). The TableLayoutPanel should handle any vertical scrolling but I can't work out how to get the ListView to resize itself depending on the number of rows.

Do I need to handle OnResize and manually resize or is there already something to handle this?

A: 

A similar question suggested using an ObjectList, but it looked like overkill for what I wanted. So instead, I made this simple overload (below) to resize based on the items in the list.

I've only tested this displaying in details mode on Windows Vista, but it's simple and seems to work well.

#pragma once

/// <summary> 
/// A ListView based control which adds a method to resize itself to show all
/// items inside it.
/// </summary>
public ref class ResizingListView :
public System::Windows::Forms::ListView
{
public:
    /// <summary>
    /// Constructs a ResizingListView
    /// </summary>
    ResizingListView(void);

    /// <summary>
    /// Works out the height of the header and all the items within the control
    /// and resizes itself so that all items are shown.
    /// </summary>
    void ResizeToItems(void)
    {
        // Work out the height of the header
        int headerHeight = 0;
        int itemsHeight = 0;
        if( this->Items->Count == 0 )
        {
            // If no items exist, add one so we can use it to work out
            this->Items->Add("");
            headerHeight = GetHeaderSize();
            this->Items->Clear();

            itemsHeight = 0;
        }
        else
        {
            headerHeight = GetHeaderSize();
            itemsHeight = this->Items->Count*this->Items[0]->Bounds.Height;
        }

        // Work out the overall height and resize to it
        System::Drawing::Size sz = this->Size;
        int borderSize = 0;
        if( this->BorderStyle != System::Windows::Forms::BorderStyle::None )
        {
            borderSize = 2;
        }
        sz.Height = headerHeight+itemsHeight+borderSize;
        this->Size = sz;
    }

protected:
    /// <summary>
    /// Grabs the top of the first item in the list to work out how tall the
    /// header is. Note: There _must_ at least one item in the list or an 
    /// exception will be thrown
    /// </summary>
    /// <returns>The height of the header</returns>
    int GetHeaderSize(void)
    {
        return Items[0]->Bounds.Top;
    }


};
Jon Cage