2011-09-30 62 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常量来自何处。 –