我有一个列表视图,我正在填充8列用户数据。用户可以选择启用自动刷新,这会导致清除ListView并使用数据库中的最新数据重新填充。

问题是当项目被清除并重新填充时,可见区域会跳回到列表顶部。因此,如果我正在查看2000年的第1000项,那么回到那个项目是非常不方便的。

基本上,我要问的是,如何获取当前滚动距离(x和y)然后恢复它们?

有帮助吗?

解决方案

前一段时间我遇到了同样的问题,最后我实现了一个算法来比较模型和列表,所以我只添加/删除了已更改的元素。这样,如果没有大的变化,列表就没有跳到开头。我想要实现的主要是效率(因此列表不会闪烁)。

其他提示

我只是想为那些拼命尝试使用有缺陷的ListView.TopItem属性的人提供一些信息:

  1. 您必须在调用ListView.EndUpdate
  2. 后设置TopItem属性
  3. ListView控件的项目必须将其Text属性设置为其他属性 比String.Empty,或该属性不起作用。
  4. 设置ListView.TopItem会间歇性地抛出空引用异常。始终将这行代码保留在Try ... Catch块中。
  5. 当然,这会导致ListView的滚动条跳转到0并返回到顶部项目的位置,这很烦人。如果您找到解决此问题的方法,请更新此问题。

我成功使用了以下内容:

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)
{ }

ListView上的TopItemIndex属性是您正在寻找的,但它有一些确认的错误应该在VS2010版本中解决..不确定(尚未检查)。

无论如何,我做这项工作的解决方法是:

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

由于某些原因,直接设置它不会更新它,但将其设置为最后一项,然后我想要的那个可靠地为我工作。

查看ListView.TopItem属性。它有一个索引,应该包含它在列表中的位置。在新列表中找到该索引,并将TopItem设置为该项,它应该自动滚动。

不幸的是,你需要使用一些互操作来滚动到ListView中的确切位置。使用 GetScrollInfo winapi函数获取现有滚动位置和 SendMessage 滚动到该位置。

CodeProject中有一篇名为滚动到具有ListView的组这可能会引导您找到解决方案。

我保持滚动位置的解决方案:

表单级变量:

private static int scrollSpot = 0;

内部列表视图刷新(即计时器,按钮)存储当前点:

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

在refreshTheForm方法中显示存储的点(放在方法的最后):

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

我遇到了同样的问题。我有一个listView,我每隔1/2秒填充一次,当我将TopItem设置为一个ListItem时,其索引&gt;可见项目,然后列表跳转topItem和后2个点。

因此,为了解决问题,我在调用EndUpdate之后设置了TopIterm。

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];​

在我的测试中,你甚至不需要TopItem,尽管我使用int来保存所选项目。如果您使用的是View.Tile或View.LargeIcon,TopItem也会引发异常。

此代码不会移动滚动条:

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

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

listView1.EndUpdate();
scroll top