Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm General / February 2006

Tip: Looking for answers? Try searching our database.

How to set ListView scroll info?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Michael J. Salamone - 26 Feb 2006 21:58 GMT
I have a listview whose contents are constantly being refreshed.  When a
refresh occurs, I delete all the items and add back.  I want to maintain the
scroll position before deleting all the items, and then want to restore it
once the items are added back.

I'm using P/Invoke Get/SetScrollInfo to get and restore the scroll
information.  GetScrollInfo is working fine -  it returns expected
information.  SetScrollInfo has no effect - the scroll positions are
unchanged (both horz and vert are 0).

I also tried Get/SetScrollPos - no luck there, either.

Is this the correct way to do this?  Anyone know what might be wrong?

Here's some of my code:

 private void RefreshList()
 {
  User32.SCROLLINFO hsi = User32.GetScrollInfo((uint)
MyListView.Handle.ToInt32(), Constants.SB_HORZ);
  User32.SCROLLINFO vsi = User32.GetScrollInfo((uint)
MyListView.Handle.ToInt32(), Constants.SB_VERT);

  MyListView.BeginUpdate();

  MyListView.Items.Clear();

  // Add new items here...

  User32.SetScrollInfo((uint)MyListView.Handle.ToInt32(),
Constants.SB_HORZ, false, hsi);
  User32.SetScrollInfo((uint)MyListView.Handle.ToInt32(),
Constants.SB_VERT, false, vsi);

  MyListView.EndUpdate();
 }

public class Constants
{
 public const int SB_HORZ = 0;
 public const int SB_VERT = 1;
 public const int SB_CTL = 2;
 public const int SB_BOTH = 4;

 public const int SIF_RANGE =  0x0001;
 public const int SIF_PAGE =  0x0002;
 public const int SIF_POS =  0x0004;
 public const int SIF_DISABLENOSCROLL = 0x0008;
 public const int SIF_TRACKPOS = 0x0010;
 public const int SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS |
SIF_TRACKPOS);
}

public class User32
{
 [StructLayout(LayoutKind.Sequential)]
 public struct SCROLLINFO
 {
  public UInt32 cbSize;
  public UInt32 fMask;
  public Int32 nMin;
  public Int32 nMax;
  public UInt32 nPage;
  public Int32 nPos;
  public Int32 nTrackPos;
 }

 [DllImport("user32.dll", EntryPoint = "GetScrollInfo", SetLastError =
true)]
 private static extern int GetScrollInfoWnd(uint hWnd, int nBar, ref
SCROLLINFO si);

 public static SCROLLINFO GetScrollInfo(uint hWnd, int nBar)
 {
  SCROLLINFO si = new SCROLLINFO();

  si.cbSize = (uint) System.Runtime.InteropServices.Marshal.SizeOf(si);
  si.fMask = Constants.SIF_ALL;

  // also tried si.fMask = Constants.SIF_PAGE | Constants.SIF_POS |
Constants.SIF_RANGE

  GetScrollInfoWnd(hWnd, nBar, ref si);       // returns correct data

  return si;
 }

 [DllImport("user32.dll", EntryPoint = "SetScrollInfo", SetLastError =
true)]
 private static extern int SetScrollInfoWnd(uint hWnd, int nBar, bool
bRedraw, ref SCROLLINFO si);

 public static int SetScrollInfo(uint hWnd, int nBar, bool bRedraw,
SCROLLINFO si)
 {
  int rc = SetScrollInfoWnd(hWnd, nBar, bRedraw, ref si);

  return rc;  // return is 0 - presumably previous scroll position
 }
}

Thanks

Signature

Michael Salamone [eMVP]
Entrek Software, Inc.
www.entrek.com

Nick Hounsome - 27 Feb 2006 07:10 GMT
>I have a listview whose contents are constantly being refreshed.  When a
>refresh occurs, I delete all the items and add back.  I want to maintain
>the scroll position before deleting all the items, and then want to restore
>it once the items are added back.

Why not just overwrite your existing items (and delete any excess). It would
probably be quicker and would avoid all scrolling problems and the use of
P/Invoke
Michael J. Salamone - 27 Feb 2006 07:29 GMT
Unless I can solve the scroll problem, that's probably what I'm going to do.
The code is a whole lot simpler to clear and add back.  And I don't know
about quicker (you have to search and update if found, and then search and
delete).  But, you're right, if I write a little more code, I don't have to
worry about scrolling *and* should have an additional benefit of not being
such a litterbug creating all that garbage when clearing the listview :)
Which in the end, would be faster on the garbage collection side (should be
fewer invocations).

I may have just talked myself into it, but still would like to know how to
restore the scroll position if anyone knows.

Signature

Michael Salamone [eMVP]
Entrek Software, Inc.
www.entrek.com

>>I have a listview whose contents are constantly being refreshed.  When a
>>refresh occurs, I delete all the items and add back.  I want to maintain
[quoted text clipped - 4 lines]
> would probably be quicker and would avoid all scrolling problems and the
> use of P/Invoke
Nick Hounsome - 27 Feb 2006 14:22 GMT
> Unless I can solve the scroll problem, that's probably what I'm going to
> do. The code is a whole lot simpler to clear and add back.  And I don't
> know about quicker (you have to search and update if found, and then
> search and delete).

You misunderstand - I am not suggesting that you match current items to new
items. The following works for intial fill AND updates:

AddExtraItems(Math.Max(newItems.Count-view.Items.Count,0));
DeleteExcessItems(Math.Max(view.Items.Count-newItems.Count,0));
for(int i = 0; i < newItems.Count; ++i)
   view.Items[i].Text = newItems[i].Text;

You only need searching if you want to maintain the proper selection not the
scroll position.

> But, you're right, if I write a little more code, I don't have to worry
> about scrolling *and* should have an additional benefit of not being such
[quoted text clipped - 13 lines]
>> would probably be quicker and would avoid all scrolling problems and the
>> use of P/Invoke
Jared - 28 Feb 2006 02:45 GMT
3 solutions for you, if you want to detect scroll there is a way to do that
as well

(
.Item(x).Selected=true
listview.select
)

listview.topitem=x

.Item(x).EnsureVisible = true

>I have a listview whose contents are constantly being refreshed.  When a
>refresh occurs, I delete all the items and add back.  I want to maintain
[quoted text clipped - 98 lines]
>
> Thanks
Michael J. Salamone - 28 Feb 2006 03:08 GMT
I had already tried that.  It's not working for me.  I can select the
previous item - that's fine.  Setting listviewitem.EnsureVisible doesn't
seem to do anything.  Maybe I have to do that after adding all the other
items.  That is, after calling EnsureVisible on the selected item, I add
more items to the listview.  Maybe doing that invalidates the
EnsureVisible()?

Anyway, even if it works, it doesn't necessarily restore the scroll position
to where it was before the update.  It would scroll so that the selected
item was either at the top or bottom of the client area.

Signature

Michael Salamone [eMVP]
Entrek Software, Inc.
www.entrek.com

>3 solutions for you, if you want to detect scroll there is a way to do that
>as well
[quoted text clipped - 110 lines]
>>
>> Thanks

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.