2011-09-30 60 views
5

我有一個.NET 3.5 WinForm具有一個ListView與在詳細模式下設置的視圖。它用作長期後臺任務中狀態項目的可滾動列表。我最近添加了最近的ListViewItem(狀態條目)。爲了確保可以看到,我確保在添加後新項目的可見性。這一切都很好;列表視圖會自動滾動到底部以顯示最近的項目。ListView滾動控件 - 滾動到底部,如果用戶不滾動?

private void AddListItem(DateTime timestamp, string message, int index) 
{ 
    var listItem = new ListViewItem(timestamp.ToString()); 
    listItem.SubItems.Add(message); 
    statusList.Items.Insert(index, listItem); 
    statusList.Items[statusList.Items.Count - 1].EnsureVisible(); 
} 

問題是,如果用戶正在滾動上來看看舊郵件,ListView控件將向下滾動,使新項目可見,因爲它的用武之地。有沒有辦法來控制這種行爲,以檢查是否用戶正在與滾動條交互(具體來說,如果他們按住滾動條上的鼠標按鈕)?檢測卷軸是否始終位於底部也是可以接受的。如果它不在底部,那麼我不能確保最新項目的可見性。喜歡的東西:

private void AddListItem(DateTime timestamp, string message, int index) 
{ 
    var listItem = new ListViewItem(timestamp.ToString()); 
    listItem.SubItems.Add(message); 
    statusList.Items.Insert(index, listItem); 
    if (!statusList.IsScrollbarUserControlled) 
    { 
     statusList.Items[statusList.Items.Count - 1].EnsureVisible(); 
    } 
} 

什麼奇怪的是,當用戶按下到位滾動條「手柄」,手柄不動(這意味着該視圖實際上沒有被滾下來編程),但在事實上是。

更新:是否有可能檢測到滾動條的位置,即如果我在底部或不是?

回答

2

與SysInternals的ProcMon比較。添加一個標記爲「自動滾動」的複選框,以便用戶可以關閉它。

+0

不知道爲什麼這是-1'd。雖然這並沒有回答這個問題,但你提供了一個非常合理的替代方案 –

+0

@Stealth - 一些馬鞋系統地降低了我的答案。不知道爲什麼,不要擔心。感謝您的投票。 –

+0

這裏的兩個答案看起來都是正確的,但我最終會和你的建議一致,因爲我認爲它滿足用戶需求的更多,並且對它的功能不會感到驚訝。按照您的建議,我使用了處理器監視器,並且它對UX用戶體驗非常有用。 –

4

兩個步驟來解決這個問題:

  1. 的的WinForms ListView控件沒有一個滾動的事件。我們需要定義一個。
  2. 確定ListView何時處於空閒狀態,並僅在空閒一段時間後才調用EnsureVisible。

對於第一個問題,繼承的ListView一個新的類,覆蓋Windows消息泵,並且當用戶滾動它引發一個事件:

public class MyListView : ListView 
{ 
    public event EventHandler<EventArgs> Scrolled; 

    protected override void WndProc(ref Message m) 
    { 
     base.WndProc(ref m); 

     const int wm_vscroll = 0x115; 
     if (m.Msg == wm_vscroll && Scrolled != null) 
     { 
      Scrolled(this, new EventArgs()); 
     } 
    } 
} 

現在我們知道了用戶滾動當列表視圖。您的下一個問題是確定列表視圖是否空閒;也就是說,如果用戶沒有在一段時間內滾動它。

有多種方法可以做到這一點。爲此,我只是使用時間戳來指示最後一次滾動時間:

private DateTime lastScrollTime; 

... 

listView.Scrolled += delegate { lastScrollTime = DateTime.Now }; 

... 

private void AddListItem(DateTime timestamp, string message, int index) 
{ 
    var listItem = new ListViewItem(timestamp.ToString()); 
    listItem.SubItems.Add(message); 
    statusList.Items.Insert(index, listItem); 

    // Scroll down only if the list view is idle. 
    var idleTime = TimeSpan.FromSeconds(5); 
    var isListViewIdle = DateTime.Now.Subtract(this.lastScrollTime) > idleTime; 
    if (isListViewIdle) 
    { 
     statusList.Items[statusList.Items.Count - 1].EnsureVisible(); 
    } 
} 
+0

這是多少性能影響?這是你以前用過的東西嗎? –

+0

您不會看到性能下降。 –

+0

我很好奇這個0x115常量來自何處。 –