在ObjectListView中保存和恢复选择
本文关键字:恢复 选择 保存 ObjectListView | 更新日期: 2023-09-27 18:15:51
谁能告诉我如何在ObjectListView中保持选择?
我有一个对象列表在我的控制,我从数据库接收。用户选择一个,然后点击"刷新"(以便再次从数据库检索所有项目)。选择是"跳跃",但我希望它保持在一个用户选择的对象。
我必须根据对象的唯一id来比较它们,这样从数据库中排序或新对象就不会影响用户的选择。
这是我的解决方案(基于Barry Guvenkaya的答案)。我假设
- 可以选择多个项目(通过鼠标或键盘)
- 对象ID不是存储在olvlisttitem的列中,而是存储在对象内部(列可以隐藏,其顺序可以不同)。
My Refresh()
function:
PushSelected();
objectListView.SetObjects(...);
PopSelected();
保存和恢复选择:
private List<Guid> selected; // Keeping the ID's of selected objects
public void PushSelected()
{
// Value of SelectedList can be get using
// objectListView.SelectedObjects
selected.Clear();
foreach (MyObject r in SelectedList)
selected.Add(r.id);
}
public void PopSelected()
{
D.DeselectAll();
if (selected.Count != 0)
for (int i = 0; i < objectListView.Items.Count; i ++)
{
OLVListItem item = (OLVListItem)objectListView.Items[i];
Guid g = ((MyObject)item.RowObject).id;
if (selected.Contains(g))
item.Selected = true;
}
}
当然,这个解的复杂度也是O(n),如果所有项都被选中,复杂度甚至是O(n*n)。
Issue:
一旦您清除对象并再次构建列表,无论您是否将其保存在变量中,所选项目都会消失。因为要保留这些信息,必须将所选项的变量声明为动态附加到OLV控制的变量。这就是为什么一旦列表被清除,变量将无法保留选中的项。
关于处理:我有一个解决这个问题的方法。大多数人可能会想到实现objectListViewUserList.SelectedItem
属性,但这种属性存在一些问题。这与某种原因不一致。为了解决这个问题,我将引入objectListViewUserList.MouseMoveHitTest
这个性质。这听起来像是一个测试变量,但它很有魅力。
假设:
另外,为了实现这个解决方案,假设第一列是ID列。
处理:
这是解决方法。在单击事件中将第一列的文本信息保存在公共字符串中。
private void objectListViewUserList_Click(object sender, EventArgs e)
{
if (objectListViewUserList.MouseMoveHitTest.Item != null)
selectedItemText = objectListViewUserList.MouseMoveHitTest.Item.Text;
else
selectedItemText = "";
}
在我的应用程序中,我用fillOnlineUsers
方法刷新OLV控件。这是任意的。它可以是任何方法。在我的应用程序中,此方法与计时器一起工作。每次刷新后,我通过搜索新列表中的ID来选择项目。
public void fillOnlineUsers()
{
objectListViewUserList.ClearObjects();
objectListViewUserList.AddObjects(onlineUsers);
objectListViewUserList.BuildList();
if (selectedItemText != "")
{
foreach (OLVListItem olvi in objectListViewUserList.Items)
if (olvi.Text == selectedItemText)
olvi.Selected = true;
}
}
这个解决方法的复杂度为0 (n)。这意味着如果您有数千条记录,则可能会减慢应用程序的速度。
如果你使用2.9.1版本的ObjectListView,只使用olv.SetObjects(YourDataObject)现有的选择将被保留,您不需要任何耗时的方法或变通方法来记住活动的选择。
如果可能的话,您的代码应该尝试维护Data中的原始对象,并在需要时更新这些对象。如果您清除所有对象并重新创建新对象,您将失去选择,并被迫采用其他方法来记住选择所以从其他帖子看来,你的记录有一个Guid,这是个好消息!如果你实现了GetHashCode
和Equals
,那么你可以通过传递旧列表olv.SelectedObjects.Cast<object>().ToList()
来清除列表并重新选择旧的选择。
public partial class Form1 : Form
{
private Guid _guid1;
private Guid _guid2;
class MyClass
{
public readonly Guid Guid;
public string Key;
public string Value;
public MyClass(Guid guid, string key, string value)
{
Key = key;
Guid = guid;
Value = value;
}
public override int GetHashCode()
{
return Guid.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is MyClass)
return this.Guid.Equals(((MyClass) obj).Guid);
return base.Equals(obj);
}
}
public Form1()
{
InitializeComponent();
olv.FullRowSelect = true;
olv.HideSelection = false;
_guid1 = Guid.Parse("026c90aa-7fb8-452d-b8bc-b42fd7bc0e7f");
_guid2 = Guid.Parse("85ea0ce0-da65-412f-8198-724c196342da");
olv.AddObjects(new []
{
//two objects that will be updated
new MyClass(_guid1,"go","nuts"),
new MyClass(_guid2,"lol","rly?"),
//one object that will disapear
new MyClass(Guid.NewGuid(),"bye","bye")
});
}
private void BtnRefreshObjects_Click(object sender, System.EventArgs e)
{
olv.BeginUpdate();
//remember the old objects
var oldSelection = olv.SelectedObjects.Cast<object>().ToList();
//swap them for the new objects
olv.ClearObjects();
olv.AddObjects(
new []
{
//This object stays the same
new MyClass(_guid1,"go","nuts"),
//This object changes fields (but is still the same record due to Guid)
new MyClass(_guid2,"omg2","omg3"),
//This is a new object
new MyClass(Guid.NewGuid(),"omg5","omg6")
});
//reset the old selection (even though they are stale objects the selection works because of Equality override)
olv.SelectedObjects = oldSelection;
olv.EndUpdate();
}
}