Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

Auto Sizing WPF GridView Class

3.00/5 (2 votes)
7 Aug 2020CPOL3 min read 15.2K   738  
Implements automatic column width sizing based on item contents for ListViews using GridView
AutoSizingGridView is a class used with Microsoft WPF ListViews which automatically sizes GridViewColumns based on dynamic content. The basic GridView class already sizes itself automatically, but the sizing is done based on initial visible content. AutoSizingGridView extends this to react to new ListViewItems and, optionally, to changes in content for existing items. AutoSizingGridView manages column width, but uses the default GridView support for row height maintenance. You may find you need to tweak the code to support changes in non-text (e.g., image-based, or complex cells) data.

Image 1

AutoSizingGridView provides a convenient replacement for the default WPF GridView class, which implements automatic column width management, based on dynamic ListView content.

Introduction

WPF's ListView control is a useful tool for viewing a relatively small number of records of read-only fixed-format data. The default GridView class supplied with WPF automatically formats data into rows and columns, calculating the row height and column width based on the initial set of visible rows. This is sufficient for most cases, but can be limiting if the data is dynamic -- when new rows are added over time or the contents of visible records changes. The changed data values are displayed as truncated values when they don't fit into the existing column. The user can manually resize the columns to see the new data, but this may be inconvenient. Replacing the GridView class with AutoSizingGridView is an easy way to reduce the need for manually resizing ListView columns.

Using AutoSizingGridView

The AutoSizingGridView class is a drop-in replacement for WPF's GridView class. It's used as the View property of the ListView class:

XAML
<ListView x:Name="AutoSizedListView" SelectionMode="Extended"
          ItemsSource="{Binding RelativeSource=
                      {RelativeSource AncestorType=local:MainWindow}, Path=Items}">
    <ListView.View>
        <asgv:AutoSizingGridView x:Name="AutoSizedGridView" IsValueTrackingEnabled="True">
            <GridViewColumn Header="Name" 
            DisplayMemberBinding="{Binding Name, NotifyOnTargetUpdated=True}" />
            <GridViewColumn Header="Description" 
            DisplayMemberBinding="{Binding Description}" />
        </asgv:AutoSizingGridView>
    </ListView.View>
</ListView>

The only new property is the IsValueTrackingEnabled property, which determines if the <code>AutoSavingGridView will re-size when the contents of existing items is displayed (true). Setting the IsValueTrackingEnabled property to False inhibits value-change monitoring. Changed item values may still be displayed (as they usually are using GridView, if the source item implements INotifyPropertyChanged), but the value could be truncated. Change tracking is relatively expensive, so the property defaults to false.

Individual column widths can be set to be fixed, using XAML, programmatically, or manually by the user. AutoSavingGridView will not resize columns whose width has been set. Remaining columns will continue to be auto-sized.

Demonstration Application

A simple application is supplied to demonstrate how AutoSavingGridView and GridView react to changes in a ListView's items. You can use it to add items and change existing items, observing how they're displayed using both views.

Implementation

The AutoSizingGridView class is derived from the WPF GridView class. It overrides the GridView.PrepareItem method to receive notification when a new ListViewItem is ready to be displayed. An AutoSizingGridView instance can only be the member of one ListView's View property. Each ListView must have a dedicated AutoSavingGridView.

AutoSavingGridView will monitor column headers to ensure they fit, when the IsValueTrackingEnabled property is set to true. A change to a GridViewColumn's Header property may expand the column's width to ensure the header fits. Since the AutoSizingGridView instance doesn't become active until the first ListViewItem is prepared, changes to column widths are delayed until the first item is prepared.

AutoSavingGridView always checks new ListViewItems to ensure each cell's data can be displayed without truncation. Columns with fixed width are ignored. AutoSavingGridView does not shrink columns -- it only expands them when needed. Thus a column may become very wide to support a long data item, and will remain wide even when the item is removed or no longer visible. When the IsValueTrackingEnabled property is set to true, AutoSizingGridView also tries to track changes to individual cells in a row. If the column's DisplayMemberBinding has set NotifyOnTargetUpdated to true, the item's TargetUpdated event is hooked. Otherwise, the item's PropertyChanged event is used for tracking changes. This should be sufficient for simple text columns, but may not be sufficient for more complex or structured data.

History

  • 6th August, 2020: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)