Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Simulate WPF ListView Column Width Set to *

0.00/5 (No votes)
29 May 2010 1  
One technique for having a column width that grows/shrinks with ListView width
I'm writing a WPF front-end to a new version of my CPAM library, and the application features a number of ListView controls. One of the things that the standard ListView DOES NOT do through simple property settings is all the programmer to set a column width of "*" (meaning consume all horizontal width not consumed by columns with a specified width).

In my case, I wanted the left-most column to be automatically sized, because all of the rest of the columns having a size specified. I was looking for a simple way to implement this, and came up with the following. Handle the SizeChanged event for the ListView, and in the event handler method, and implement code that looks something like this:

private void InnerListView_SizeChanged(object sender, SizeChangedEventArgs e)
{
    if (e.WidthChanged)
    {
        GridView view  = this.InnerListView.View as GridView;
        Decorator border = VisualTreeHelper.GetChild(this.InnerListView, 0) as Decorator;
        if (border != null)
        {
            ScrollViewer scroller = border.Child as ScrollViewer;
            if (scroller != null)
            {
                ItemsPresenter presenter = scroller.Content as ItemsPresenter;
                if (presenter != null)
                {
                    view.Columns[0].Width = presenter.ActualWidth;
                    for (int i = 1; i < view.Columns.Count; i++)
                    {
                        view.Columns[0].Width -= view.Columns[i].ActualWidth;
                    }
                }
            }
        }
    }
}


Because a ListView could have enough items to cause the vertical scrollbar to be displayed, we have to account for this in a non hard-wired manner. Essentially, you want to find the width of the "client rectangle" (to put it into a Windows API context), which excludes the vertical scrollbar's width. To accomplish this, we need to get to the ItemsPresenter control inside the ListView.

In a standard ListView, the Child is a Decorator, and the ScrollViewer is the Child of Decorator. Finally, the ItemsPresenter is the Content of the ScrollViewer, and guess what - ItemsPresenter.ActualWidth represents the width of your ListView content NOT INCLUDING the scrollbar's width. Will wonders never cease?

Once you get the width of your client area, you can loop through all of the columns and subtract their width to come up with a hard-wired width for your "*" column.

Notice - I realize there are probably more WPF-conformant techniques to accomplish this goal, but I am more interested in "getting the work done" than in strictly adhering to a programming paradigm. I also don't really care to work in XAML.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here