Click here to Skip to main content
6,291,722 members and growing! (13,621 online)
Email Password   helpLost your password?
Desktop Development » List Controls » ListView controls     Intermediate License: The BSD License

Scrolling to a group with a ListView

By Lord Zoltar

Add the functionality to scroll to a group in a ListView
C# (C# 1.0, C# 2.0, C# 3.0), Windows, .NET, WinForms, Dev
Posted:4 Jul 2008
Views:10,394
Bookmarked:18 times
Unedited contribution
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
1 vote for this article.
Popularity: 0.00 Rating: 4.00 out of 5

1

2

3
1 vote, 100.0%
4

5

Introduction

I had some data that I needed to display in a listview. The data was represented by images, and sorted into groups. Since there could be dozens (hundreds?) of images, I thought it would be useful to be able to jump to any group using buttons (1 button per group). Unfortunately, scrolling to a group is not something that the .NET ListView control supports out of the box.

listViewScroll_screenshot.png
Above is a screenshot of 4 buttons that scroll the listview to 4 groups.

Background

The first time I tried to implement scroll-to-a-group, I used the EnsureVisible method on the first list item in a group. This works, but it's not great. The problem is that the control will scroll just enough to make the item visible, and that could mean making it visible at the top or bottom of the control. If you have many 16x16 icons, it takes several seconds to find the item that you just EnsureVisible'd. With EnsureVisible, nothing will happen if the item is already visible. Also, EnsureVisible can only be applied to ListViewItems, not to ListViewGroups (but Groups is what I wanted). The other method that was suggested to me was to use the TopItem method. This cannot be used if the ListView's view mode is LargeIcon or SmallIcon or Tile (I was using LargeIcon), so TopItem was out of the question.

Using the code

Usage is simple: Add the AdvancedListView class to your project. When you want to scroll to a group, pass the group's name or index to AdvancedListView.ScrollToGroup() and you will see your ListView scroll so that the group header is right at the top of the control.

myListView.ScrollToGroup(myListViewItem.Group.Name);
		

Points of Interest

The main trick to getting this to work was realizing that the .NET framework just couldn't scroll to a group. I needed to use the SendMessage function to send a LVM_SCROLL message to the ListView control. In discussion forums, it had often been suggested to use WM_VSCROLL, but this did NOT work. Using WM_VSCROLL, I was only able to move the scrollbar, but could not scroll the contents. The LVM_SCROLL message allows the listview contents to be scrolled as well.
This message takes two values, which are used to determine how much to scroll the listview by, relative to its CURRENT scroll position. The problem with this is that the position of the group is an absolute position, based on the position of the first item in the group:

myListViewGroup.Items[0].Position.Y - 30
to get the correct amount to scroll by, we need to first get the current scroll position, using the API function GetScrollInfo:
			int prevScrollPos = 0;
			SCROLLINFO currentInfo = new SCROLLINFO();
			currentInfo.cbSize = Marshal.SizeOf(currentInfo);
			currentInfo.fMask = (int)ScrollInfoMask.SIF_ALL;

			GetScrollInfo(this.Handle, (int)ScrollBarDirection.SB_VERT, ref currentInfo)
				prevScrollPos = currentInfo.nPos;

			//The LVM_SCROLL message will take a delta-x and delta-y which tell the list view how 
			//much to scroll, relative to the current scroll positions. We are given the scroll
			//position as an absolute position, so some adjustments are necessary:
			scrollPos -= prevScrollPos;

As it turns out, there are MANY ListView messages. You can see all of them here:
http://msdn.microsoft.com/en-us/library/cc656508(VS.85).aspx
I used a very simple structure for the one message that I needed:

		private enum ListViewMessages : int  
		{   
			LVM_FIRST = 0x1000,   
			LVM_SCROLL = (LVM_FIRST + 20)   
		}

Using this message to scroll can be done like this (although my code doesn't actually have a scrollAmtX because I was not interested in horizontal scrolling):
SendMessage(listViewHandle, (uint)ListViewMessages.LVM_SCROLL, (IntPtr)scrollAmtX, (IntPtr)scrollAmtY);

History

July 5 2008: Added a screenshot, added a bit more explanation.

License

This article, along with any associated source code and files, is licensed under The BSD License

About the Author

Lord Zoltar


Member

Occupation: Web Developer
Location: Canada Canada

Other popular List Controls articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 2 of 2 (Total in Forum: 2) (Refresh)FirstPrevNext
GeneralImages? PinmemberJaime Olivares5:23 5 Jul '08  
GeneralRe: Images? PinmemberThe_Mega_ZZTer6:16 5 Jul '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 4 Jul 2008
Editor:
Copyright 2008 by Lord Zoltar
Everything else Copyright © CodeProject, 1999-2009
Web20 | Advertise on the Code Project