2009-03-09 41 views
10

Tôi đã có chế độ xem danh sách mà tôi đang điền với 8 cột dữ liệu người dùng. Người dùng có tùy chọn cho phép tự động làm mới, điều này làm cho ListView bị xóa và được tái hoạt động với dữ liệu mới nhất từ ​​cơ sở dữ liệu.WinForms ListView, Nhớ vị trí cuộn trên Tải lại

Vấn đề là khi các mục được xóa và được mở lại, vùng hiển thị sẽ nhảy trở lại đầu danh sách. Vì vậy, nếu tôi đang xem mục 1000 năm 2000, rất bất tiện khi quay lại mục đó.

Về cơ bản, những gì tôi hỏi là, làm cách nào để có được khoảng cách cuộn hiện tại (x và y) và sau đó khôi phục chúng?

Trả lời

4

Tôi đã có cùng một vấn đề với một thời gian trước và tôi đã kết thúc việc thực hiện một thuật toán để so sánh mô hình với danh sách, vì vậy tôi chỉ thêm/xóa các phần tử đã thay đổi. Bằng cách này, nếu không có thay đổi lớn, danh sách đã không chuyển sang đầu. Và điều chính tôi muốn đạt được là hiệu quả (để danh sách không chớp mắt).

+0

Đây là những gì tôi đã làm. Tôi đã thêm thẻ vào mục con đầu tiên và sau đó sử dụng thẻ đó để thực hiện so sánh và chỉ cập nhật khi được yêu cầu. – GenericTypeTea

1

Nhìn vào thuộc tính ListView.TopItem. Nó có một chỉ mục, nó sẽ chứa vị trí của nó trong danh sách. Tìm chỉ mục đó trong danh sách mới và đặt TopItem thành mục đó và nó sẽ tự động cuộn.

+0

ListView.TopItem dường như không hoạt động. Tôi nghĩ rằng nó có thể liên quan đến việc phân loại vì vậy tôi đã tắt nó, nhưng khi tôi đặt TopItem thành một mục và kiểm tra thuộc tính ngay lập tức sau đó nó không bị thay đổi (thay đổi đối với một mục khác, không phải là mục tôi đã chỉ định). Bạn còn ý kiến ​​nào không? – TheAgent

0

Thật không may, bạn sẽ cần phải sử dụng một số interop để cuộn đến vị trí chính xác trong ListView. Sử dụng hàm 01apiwinapi để lấy vị trí cuộn hiện tại và SendMessage để cuộn đến vị trí đó.

Có trong một bài viết về CodeProject có tên Scrolling to a group with a ListView có thể hướng dẫn bạn giải pháp.

12

Tôi chỉ muốn cung cấp một số thông tin cho những người tuyệt vọng cố gắng sử dụng các tài sản buggy ListView.TopItem:

  1. Bạn PHẢI thiết lập thuộc tính TopItem SAU gọi ListView.EndUpdate
  2. Các mặt hàng của ListView kiểm soát PHẢI có thuộc tính Văn bản của họ được đặt thành một số khác hơn String.Empty hoặc thuộc tính sẽ không hoạt động.
  3. Đặt ListView.TopItem ném ngoại lệ tham chiếu null không liên tục. Luôn luôn giữ dòng mã này bên trong khối try ... Catch.

Tất nhiên, điều này sẽ làm cho thanh cuộn của ListView nhảy về 0 và quay lại vị trí của mục trên cùng, điều này gây phiền toái. Vui lòng cập nhật câu hỏi này nếu bạn tìm thấy giải pháp cho vấn đề này.

+0

Tôi đã phát hiện ra rằng tôi nhận được lỗi off-by-one khi gán cho TopItem (tức là, nó cuộn đến mục trên đầu tôi yêu cầu) nhưng nếu tôi gọi nó hai lần thì nó hoạt động. Buggy, bạn nói không? :-) – RichieHindle

0

Tôi sắp xếp cùng một vấn đề. Tôi có một listView mà tôi cư trú mỗi 1/2 giây và khi tôi đặt TopItem thành một ListItem có chỉ mục> các mục hiển thị, sau đó danh sách nhảy lên giữa topItem và ngược lại 2 điểm.

Vì vậy, để khắc phục sự cố, tôi đã đặt TopIterm SAU cuộc gọi đến EndUpdate.

lvB.EndUpdate(); 
lvI.EndUpdate(); 
lvR.EndUpdate(); 

if (lstEntryInts.Items.Count > 0) 
    lstEntryInts.TopItem = lstEntryInts.Items[iTopVisIdx]; 
if (lstEntryBools.Items.Count > 0) 
    lstEntryBools.TopItem = lstEntryBools.Items[iTopVisIdx]; 
if (lstEntryReals.Items.Count > 0) 
    lstEntryReals.TopItem = lstEntryReals.Items[iTopVisIdx];​ 
0

Giải pháp của tôi để duy trì vị trí cuộn:

biến cấp Mẫu:

private static int scrollSpot = 0; 

Bên refresh listview (ví dụ Timer, nút) để lưu trữ tại chỗ hiện tại:

scrollSpot = this.listView1.TopItem.Index; 
refreshTheForm(); 

Làm mới bên trongPhương thức Form để hiển thị vị trí được lưu trữ (đặt ở cuối phương thức):

if (scrollSpot <= 1) 
{ 
    listView1.Items[scrollSpot].Selected = true; 
} 
else 
{ 
    listView1.Items[scrollSpot - 2].Selected = true; 
} 
listView1.TopItem = listView1.SelectedItems[0]; 
3

Thuộc tính TopItemIndex trên ListView là những gì bạn đang tìm kiếm, tuy nhiên nó có một số lỗi xác nhận cần được giải quyết trong bản phát hành VS2010 .. không chắc chắn (chưa kiểm tra).

Dù sao, cách giải quyết của tôi để làm việc này là để làm điều này:

listViewOutput.TopItemIndex = outputList.Count - 1; 
listViewOutput.TopItemIndex = myNewTopItemIndex; 

Đối với một số lý do đặt nó trực tiếp không cập nhật nó, nhưng đặt nó vào mục cuối cùng và sau đó một trong những Tôi muốn tác phẩm đáng tin cậy cho tôi.

6

tôi đã sử dụng sau thành công:

int topItemIndex = 0; 
try 
{ 
    topItemIndex = listView1.TopItem.Index; 
} 
catch (Exception ex) 
{ } 
listView1.BeginUpdate(); 
listView1.Items.Clear(); 
//CODE TO FILL LISTVIEW GOES HERE 
listView1.EndUpdate(); 
try 
{ 
    listView1.TopItem = listView1.Items[topItemIndex]; 
} 
catch (Exception ex) 
{ } 
0

Trong các thử nghiệm của tôi, bạn thậm chí không cần TopItem, mặc dù tôi đã sử dụng một int để lưu các mục đã chọn. Ngoài ra TopItem ném một ngoại lệ nếu bạn đang sử dụng View.Tile hoặc View.LargeIcon.

Mã này không di chuyển thanh cuộn:

listView1.BeginUpdate(); 
listView1.Items.Clear(); 

// loop through your add routine 
listView1.Items.Add(lvi); 

listView1.EndUpdate(); 
Các vấn đề liên quan