Efficient way of selecting an item in a Virtual ListView

D

Danny Tuppeny

Hi All,

I'm trying to find the best way to select an item in a ListView using the
Virtual mode. My "items" are business classes, and I have a reference to
once I want to select (passed from another dialog). One way is to spin
through the items and compare the .Tag property to my business object (code
below), however I fear the casts are probably costly (there could be a lot
of servers). I also thought about spinning through the servers list and
comparing directly, then using the index to set the selected item, however
to use foreach(), I don't have the index number, and I'm not sure of the
performance of a for(int i...) loop in comparison to a foreach. My code
currently works, but I'd like to make sure this is as fast as possible
(it'll be in many places, with very big lists soon!)

List<Server> servers = Server.GetAll();
listServers.VirtualListSize = servers.Count;
if (server != null)
{
foreach(ListViewItem lvi in listServers.Items)
{
if (server == (Server)lvi.Tag)
{
lvi.Selected = true;
break;
}
}
}
 
D

Danny Tuppeny

<snip>

I lied - my code doesn't currently works. listView.Items is empty in virtual
mode... So in addition to the mots efficient way, does anyone actually have
a way that works?

I've tried allsorts, including setting .Selected to true in the
RetrieveVirtualItem method, and still no joy :-(
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


Is the server variable a reference to an instance you know is in the list?
note I'm not refering to two object with EXACT the same values, but the same
reference.


If so, you do not need to cast , it will compare the reference and it will
be as fast as you can get :)


cheers,
 
D

Danny Tuppeny

Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

what is "virtual mode" ?

Virtual Mode is for when you already have your items in an array. Rather
than create loads of ListViewItems, you do:

list.VirtualMode = true;
list.VirtualListSize = 100;
list.RetrieveVirtualItem += new
System.Windows.Forms.RetrieveVirtualItemEventHandler(this.listServers_RetrieveVirtualItem);

and define an event handler:

private void listServers_RetrieveVirtualItem(object sender,
RetrieveVirtualItemEventArgs e)
{
NewsServer server = servers[e.ItemIndex];
e.Item = new ListViewItem(server.Username + " on " + server.Host
+ ":" + server.Port.ToString(), 0);
}

This way, only items that are seen in the list are created.

However, it seems to break SelectItems et al, so I can't find a way to
programatically select something when using virtual mode :-((
 
D

Danny Tuppeny

Jason Newell said:
He's using .NET Framework 2.0.

Trying!

Yeah, sorry, I forgot this is just a c# group! :)

Still, I've not come across a single way to programatically select an item
in a ListBox using VirtualMode... Is this not a fundamental requirement? :blush:(
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Well, I'm still using 1.1 at the office so I haven't play with something as
especific as this, I just checked the doc ( pretty scarse btw) and it seems
that you have to handle RetriveVirtualItem event, which apparently expect a
ListViewItem, so at the end you do create ListViewItems :)

Also it's stated in the doc that an exception is throw IF you set
VirtualMode=true AND Items has elements. so what you are seeing is
consistent with the doc.

My advice is to simply use the ListView as usual :)

cheers,
 
D

Danny Tuppeny

Ignacio Machin ( .NET/ C# MVP ) said:
Well, I'm still using 1.1 at the office so I haven't play with something
as especific as this, I just checked the doc ( pretty scarse btw) and it
seems that you have to handle RetriveVirtualItem event, which apparently
expect a ListViewItem, so at the end you do create ListViewItems :)

Yep, but you don't have to create 50,000 of them. You create the 6 or so the
user can see, and as they scroll you add more individually - performance on
a *massive* list is fantastic :D

Also it's stated in the doc that an exception is throw IF you set
VirtualMode=true AND Items has elements. so what you are seeing is
consistent with the doc.

Not quite, I was trying to read Items after setting virtual items. It turns
out, there was a bug in my original code, and you do actually get at times
via .Items (to read, not to set), like this:

listView1.Items[listView.SelectedIndices[0]].Selected = true;

or in full, my code is:

listServers.VirtualListSize = servers.Count;
if (selectedServer != null)
{
for(int i = 0; i < servers.Count; i++)
{
if (selectedServer == servers)
{
listServers.Items.Selected = true;
break;
}
}
}

And it works :))))
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


Danny Tuppeny said:
Yep, but you don't have to create 50,000 of them. You create the 6 or so
the user can see, and as they scroll you add more individually -
performance on a *massive* list is fantastic :D

Whoaa, I have never had such a huge amount of data in a listview, you are
right using the "regular" way is out of the question.

Also it's stated in the doc that an exception is throw IF you set
VirtualMode=true AND Items has elements. so what you are seeing is
consistent with the doc.

Not quite, I was trying to read Items after setting virtual items. It
turns out, there was a bug in my original code, and you do actually get at
times via .Items (to read, not to set), like this:

listView1.Items[listView.SelectedIndices[0]].Selected = true;

or in full, my code is:

listServers.VirtualListSize = servers.Count;
if (selectedServer != null)
{
for(int i = 0; i < servers.Count; i++)
{
if (selectedServer == servers)
{
listServers.Items.Selected = true;
break;
}
}
}

And it works :))))


Good to know :)

I was checking yesterday a Owned draw list control and it also may have
solved your problem, take a look at it in www.opennetcf.org the article is
interesting, the good thing about this approach is that you could do it
without creating any listviewitem .


cheers,
 
D

Danny Tuppeny

Ignacio Machin ( .NET/ C# MVP ) said:
Whoaa, I have never had such a huge amount of data in a listview, you are
right using the "regular" way is out of the question.

Nor me, it was an example! :)
I like it because it means you don't have to create ListViewItem's that'd
never be used, and it's scalable should you need it :)
You think you only need 6 items, but wait until your user gets hold of your
app, and finds a way to abuse some "new" functionality into it! ;o)))

I was checking yesterday a Owned draw list control and it also may have
solved your problem, take a look at it in www.opennetcf.org the article is
interesting, the good thing about this approach is that you could do it
without creating any listviewitem .

I don't think creating a few ListViewItems is a problem, and I'm a fan of
using the built in controls where I can - shipped apps will be smaller, and
I'm liking the look of ClickOnce :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top