Click here to Skip to main content
12,303,940 members (72,001 online)
Click here to Skip to main content
Add your own
alternative version

Stats

259.6K views
3K downloads
113 bookmarked
Posted

ListViewFilter Control for .NET

, 28 Apr 2003
Rate this:
Please Sign up or sign in to vote.
An enhanced ListView with sorting/shading and a filterbar to filter items.
<!-- Download Links --> <!-- Article image -->

Sample Image - ListViewFilter.gif

<!-- Add the rest of your HTML here -->

Introduction

This control is another extension to the now standard and widely used ListView control. I have included some of the more common features: shaded columns, column sorting (with data type), but the real addition is the FILTERBAR features of the header. This implementation eliminates all of the work of dealing with the filter messages and item filtering by incorporating it into the control. This could have been implemented as delegates, but we create controls to do the work for us, don't we? I would like to thank Carlos H. Perez since a lot of the implementation came from examples he set with his ListViewEx control.

Background

The HeaderControl FILTERBAR feature has been around since IE5.0 was released but it is not at all widely implemented even in controls like Windows Explorer! It can be a very useful addition to detailed ListView controls but the code involved in using one has always limited the availability of it. You have to trap WM_NOTIFY messages from the header control, change the header control style, and manually update the ListView items. This implementation attempts to remove those hard parts and make ListView filtering easier. I have applications currently bound that use this feature and the customer feedback has been great. Many have asked why Microsoft doesn't do this too.

This implementation has been tested only on XP and 2000. It all depends upon the comctl32.dll that is available on the platform. The Up/Down arrows for sort direction in the column header are only supported in version 6.0 and above, and you HAVE to supply a manifest file, or dynamically attach the .DLL and theme, in order for that to be implemented. Others may want to add a CUSTOMDRAW feature to the header control or ImageList for non-XP platforms to see the Up/Down arrows.

ListViewFilter Control Features

As with any .NET custom control you must make the .DLL available for use in the designer through the toolbox customization feature. Since this is as pure an implementation of a ListView as possible, all existing and new features work in DesignMode (except item filtering, but that's execution only). The Browsable properties are:

  • Filtered - bool, turn on/off the filterbar
  • IgnoreCase - bool, ignore character case when filtering strings
  • Shaded - bool, color the background of the sorted column differently
  • ShadeColor - Color, the color to use for the shaded column
  • SortColumn - int, the column to sort
  • SortOrder - bool, true for ascending
Non-Browsable properties:
  • Header - ListViewFilterHeader, readonly access to access column properties (see description of ListViewFilterHeader for column specific properties)
  • SortType - LVFDataType enum, current sort column data type for comparison (String, Number, Date)
As with all implementations of a FILTERBAR, a lot of functionality is hidden from the casual user. It takes a little explanation and practice before they become comfortable with it. I hid a ContextMenu attached to the filter button that pops up to allow changes to the alignment, data style, and other features. I guess hiding things in the user interface is too easy to ignore doing it!

The most hidden feature is the content of the filter text field. You are not limited to just entering ABC... or numbers or dates, you may preceed the actual string with a comparison type. By default comparison is equal to (=) if nothing is supplied. You may also use less then (<), less than or equal to (<=), greater than (>), greater than or equal to (>=) or not (!) comparison types. I will probably add ContextMenu items to add/change the filter text comparison type at some time when I am more comfortable working with the MenuItem event (there should be a better way to check which MenuItem is the sender instead of if then else logic).

Most of this control isn't difficult code, just implementation of features that have not really been exploited. Once you trap the correct messages (override WndProc) and crack the message headers this is simply a matter of having the right algorithm. Note, I'm not saying all of the implementation is correct, only that it works. I truly believe there are many other and better ways to do this, hopefully others can use this as an example for what not to do!

Since the ListViewItemCollection MUST contain all the visible Items we have to deal with taking Items out and putting them back into that collection to filter the list. Previous implementations in other languages allowed me to use OWNERDATA style ListView controls and private containers for the items. That may still be possible in .NET but would require that all filtering and item additions/removals be done through delegates. The simplest way is to let the ListViewItemCollection think it contains all the Items in the ListView.

The primary function for for filterig items is FilterUpdate() which does all the work when a filter content has changed. FilterBuild() helps by creating LVFFilter entries that describe all active column filters, FilterCheck() is the helper to perform an item/filter comparison for FilterUpdate(). FilterUpdate() has three functions:

  • Loop through all collection Items removing filter failures to a holding array
  • Loop through all previous filtered items returning now viable items to the collection
  • Add the holding array items from step 1 to the updated filtered items array
If no filters are applied all items in the current filtered array are returned to the ListViewItemCollection and the filtered Items array cleared. Before re-enabling update, a Sort is done to finish the process.

The trickiest piece of code was reading and writing the FILTERBAR content. This is done via messages to the header control (WM_GETITEMA/WM_SETITEMA) and the HDITEM structure. What is tricky is that for access to the filters you have to reference a HDTEXTFILTER structure from the HDITEM structure. Doing that involved marshaling the memory for the HDTEXTFILTER prior to passing the reference to the HDITEM structure in the message.

// structures used (see Win32 documentation)
HDTEXTFILTER hdTextfilter = new HDTEXTFILTER();
HDITEM       hdItem       = new HDITEM();

// get the current text content of a <code>column</code> filter.
// this is tricky since it involves marshalling pointers
// to structures that are used as a reference in another
// structure.  first initialize the receiving HDTEXTFILTER
hdTextfilter.pszText    = new string( new char[ 64 ]);
hdTextfilter.cchTextMax = hdTextfilter.pszText.Length;

// set the HDITEM up to request the current filter content
// NOTE: the HDI_FILTER flag in the mask means that the
// pvFilter points to a HDTEXTFILTER structure...
hdItem.mask = W32_HDI.HDI_FILTER;
hdItem.type = (uint)W32_HDFT.HDFT_ISSTRING;

// marshall memory big enough to contain a HDTEXTFILTER
hdITEM.pvFilter = Marshal.AllocCoTaskMem(
  Marshal.SizeOf( hdTextfilter ) );

// now copy the HDTEXTFILTER structure to the marshalled memory
Marshal.StructureToPtr( hdTextfilter, hdItem.pvFilter, false );

// retrieve the header filter string as non-wide string
SendMessage( col_hdrctl.Handle, W32_HDM.HDM_GETITEMA, <code>column</code>
NOTE: None of this works without all the standard Win32 constants (#define) that are freely available to C++ programmers. I know that there are a number of 'libraries' built (re: UtilityLibrary) but since I only needed a subset (and some of the flags weren't in UtilityLibrary) I simplified this by creating all the needed enumerations and structures as W32_xxx values. See the Win32Enum.cs, Win32Msgs.cs, and Win32Struct.cs files included in the source.

ListViewFilterHeader Control Features

Since the Header is available as a execution mode readonly property by ListViewFilter, it publishes a number of properties of it's own for use in manipulating the filters directly from code. Again my implementation may be called into question, but I wanted to access each property as an array. I could have made a Columns[] class with it's own properties to do that, but I didn't. Some of these properties are accesible through the Columns of the ListView itself but I implemented them as Header properties especially for the ContextMenu so that it did not have to know about the ListView.Columns, just the Header. The ContextMenu appears when you click one of the column filter buttons. The available properties are:

  • Alignment - HorizontalAlignment, column data format, Left, Right, Center
  • DataType - LVFDataType enum, String, Number, Date format for comparison
  • Filter - string, get/set the content of the filter
  • Names - string, get/set the column header name
  • SizeInfo - Size, readonly Width and Left in a (misused) Size structure
Properties promoted by ListViewFilter itself
  • Filtered - bool, turn on/off the filterbar
  • SortColumn - int, the column to sort
  • SortOrder - bool, true for ascending
The big thing about the ListViewFilterHeader control is that it is an encapsulation of the System.Windows.Forms.NativeWindow control and deals directly with the Handle of the HeaderControl itself. The ListViewFilter is responsible for the creation and destruction of this object. When the ListViewFilter.Handle changes this object is recreated and the new Handle attached in the constructor.

The primary purpose of this class is to set the header style, set the up/down sorted column arrow (this could be changed to an image index), and to promote access to the filter text, data type, and other properties of a column as needed. Any feature wanted for a header control accessible via SendMessage could be added to this class and publised as properties just like these.

Caveats

Marshalling memory for structures isn't really that hard, it was just difficult to find the right documentation on how and when to do so. Creating the enumerations for all the needed Win32 definitions is time consuming and prone to error (I really want to see .NET implement that somehow). You may notice that some of the messages are the A version not W because string just is easier with non-unicode text.

There will be problems with this control on some machines; you have the source, make it work for you. I have been developing controls for many years now (mostly in Borland C++ Builder) and this is my first submission to any board or group (maybe I have been selfish). So, take it easy on me this time I've only been coding C# for two weeks now.

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

Share

About the Author

Tom Mulligan
Web Developer
United States United States
S/W developer since 1977.

You may also be interested in...

Comments and Discussions

 
Questionfilter "like" Pin
Member 354512129-Sep-11 23:20
memberMember 354512129-Sep-11 23:20 
GeneralSorting with ShowGroups = true [modified] Pin
ibazar198310-Apr-11 23:11
memberibazar198310-Apr-11 23:11 
General64-bit compatibility fix Pin
joshua704489-Apr-11 5:52
memberjoshua704489-Apr-11 5:52 
GeneralRe: 64-bit compatibility fix Pin
sonia$cool17-Oct-11 20:32
membersonia$cool17-Oct-11 20:32 
QuestionLicensing question Pin
Michellle3-May-10 16:31
memberMichellle3-May-10 16:31 
GeneralWill this work with Virtualmode Pin
sunnypandya8-Jan-10 5:09
membersunnypandya8-Jan-10 5:09 
GeneralNatural Sort Pin
Bjoern M.8-Aug-09 13:30
memberBjoern M.8-Aug-09 13:30 
GeneralAdding groups to the list Pin
edaniel198415-Jul-09 6:49
memberedaniel198415-Jul-09 6:49 
GeneralThis one works in all environments Pin
bill700217-Apr-09 13:57
memberbill700217-Apr-09 13:57 
AnswerSignificantly adding speed when resetting filters in large lists Pin
CyberCo12-Nov-08 4:11
memberCyberCo12-Nov-08 4:11 
Generalno drag and drop and weird behavior Pin
NETtune18-Mar-08 3:48
memberNETtune18-Mar-08 3:48 
GeneralVista & Visual Studio 2008 Pin
Eiredrake1-Feb-08 3:34
memberEiredrake1-Feb-08 3:34 
QuestionScroll bar problem Pin
iskra_em26-Oct-07 2:40
memberiskra_em26-Oct-07 2:40 
GeneralSorting booster! Pin
Brosten2-Oct-07 0:50
memberBrosten2-Oct-07 0:50 
GeneralFilterproblem in Vista Pin
termos24-Sep-07 22:13
membertermos24-Sep-07 22:13 
GeneralRe: Filterproblem in Vista Pin
termos25-Sep-07 2:15
membertermos25-Sep-07 2:15 
GeneralNot solved! Pin
Brosten18-Oct-07 5:53
memberBrosten18-Oct-07 5:53 
GeneralRe: Not solved! Pin
Brosten18-Oct-07 11:48
memberBrosten18-Oct-07 11:48 
GeneralRe: Filterproblem in Vista Pin
Alexander Oleshov14-May-10 2:04
memberAlexander Oleshov14-May-10 2:04 
GeneralRandomly getting a bold font Pin
Brosten2-Sep-07 23:06
memberBrosten2-Sep-07 23:06 
GeneralRe: Randomly getting a bold font Pin
Eiredrake1-Feb-08 3:36
memberEiredrake1-Feb-08 3:36 
QuestionChange the filter default text Pin
VirusX5-Jun-07 5:16
memberVirusX5-Jun-07 5:16 
GeneralRe: Change the filter default text Pin
deloford27-Feb-08 10:00
memberdeloford27-Feb-08 10:00 
GeneralFocus on textbox Pin
dgortemaker24-May-07 1:13
memberdgortemaker24-May-07 1:13 
GeneralSetting SortColumn in constructor Pin
Member #36504727-Mar-07 7:05
memberMember #36504727-Mar-07 7:05 
GeneralColumn shadowing in VB Pin
Graznok27-Jul-06 7:10
memberGraznok27-Jul-06 7:10 
GeneralRe: Column shadowing in VB Pin
Graznok29-Jul-06 3:25
memberGraznok29-Jul-06 3:25 
GeneralTested on Vista Pin
Kel_20-Jul-06 13:15
memberKel_20-Jul-06 13:15 
GeneralRe: Tested on Vista Pin
ubik703-Jan-07 0:17
memberubik703-Jan-07 0:17 
GeneralIt seems does not work under Windows 2003 Server Pin
Ariete_ge27-Feb-06 5:45
memberAriete_ge27-Feb-06 5:45 
GeneralRe: It seems does not work under Windows 2003 Server Pin
cadessi10-Mar-06 5:21
membercadessi10-Mar-06 5:21 
GeneralRe: It seems does not work under Windows 2003 Server Pin
gwain1313-Feb-07 2:18
membergwain1313-Feb-07 2:18 
AnswerRe: It seems does not work under Windows 2003 Server Pin
rptx3229-Jun-09 7:25
memberrptx3229-Jun-09 7:25 
GeneralRe: It seems does not work under Windows 2003 Server Pin
D. de Kerf13-Apr-10 1:13
memberD. de Kerf13-Apr-10 1:13 
GeneralRe: It seems does not work under Windows 2003 Server Pin
D. de Kerf13-Apr-10 3:28
memberD. de Kerf13-Apr-10 3:28 
GeneralColumn Ordering Pin
freshthinking17-Jun-05 10:43
memberfreshthinking17-Jun-05 10:43 
GeneralFlicker Issues Pin
kettch15-Apr-05 15:18
memberkettch15-Apr-05 15:18 
QuestionDemo from same version as posted code? Pin
Tom Wanger10-Mar-05 5:27
sussTom Wanger10-Mar-05 5:27 
AnswerRe: Demo from same version as posted code? Pin
T Wanger10-Mar-05 6:43
memberT Wanger10-Mar-05 6:43 
QuestionWhat about wildcard placeholders? Pin
CrazyDevil6-Jan-05 1:51
memberCrazyDevil6-Jan-05 1:51 
AnswerRe: What about wildcard placeholders? Pin
Tom Mulligan7-Jan-05 12:49
memberTom Mulligan7-Jan-05 12:49 
GeneralRe: What about wildcard placeholders? Pin
CrazyDevil8-Jan-05 21:50
memberCrazyDevil8-Jan-05 21:50 
GeneralSpeed issue with a large number of items Pin
TimothyP4-Oct-04 20:35
memberTimothyP4-Oct-04 20:35 
GeneralRe: Speed issue with a large number of items Pin
TimothyP5-Oct-04 12:07
memberTimothyP5-Oct-04 12:07 
GeneralRe: Speed issue ... solved Pin
TimothyP6-Oct-04 10:52
memberTimothyP6-Oct-04 10:52 
GeneralRe: Speed issue with a large number of items Pin
outlanderza21-Oct-04 3:51
memberoutlanderza21-Oct-04 3:51 
GeneralRe: Speed issue with a large number of items Pin
ANIL KUMAR SHARMA (INDIA)17-Jun-06 2:18
memberANIL KUMAR SHARMA (INDIA)17-Jun-06 2:18 
GeneralRe: Speed issue with a large number of items Pin
Andreas Brosten22-Mar-07 0:40
memberAndreas Brosten22-Mar-07 0:40 
Questiongood work... what about DataGrid? Pin
Paolo Pagano14-Sep-04 0:37
memberPaolo Pagano14-Sep-04 0:37 
QuestionDefault filter text? Pin
jason0000@yahoo.com21-Aug-04 18:44
memberjason0000@yahoo.com21-Aug-04 18:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160530.1 | Last Updated 29 Apr 2003
Article Copyright 2003 by Tom Mulligan
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid