Disable Items in ListView

B

Bob

Is there any practical way to disable items within a ListView control?
I'd like to be able to 'filter' the list incrementally without
actually removing anything (so I can remove the filter to get back to
the full list).

The ListView will have a large number of items, so it would be
time-consuming to clone them and create new ListViews, etc. Even as it
is, it takes a long while to just iterate thru the items.

Any ideas?
 
M

Marc Gravell

Well, in this case I expect that "VirtualMode" is the way to go; that
way you don't have to add anything in the first place. As for the
backing store (which you will need to wire to the list manually)... if
you are using DataTable, then you can filter with strings;
unfortunately for the class-based approach this isn't implemented in
BindingList<T> (I have written a bound, filtering BindingList<T>, but
I made it predicate-based, not string based). In reality, I suspect it
is easier to keep two lists - the full list and the predicate-filtered
list, and tie your "VirtualMode" ListView to the filtered list.

Search for "+VirtualMode + ListView" for examples of usage.

Marc
 
B

Bob

Is there any practical way to disable items within a ListView control?
I'd like to be able to 'filter' the list incrementally without
actually removing anything (so I can remove the filter to get back to
the full list).

The ListView will have a large number of items, so it would be
time-consuming to clone them and create new ListViews, etc. Even as it
is, it takes a long while to just iterate thru the items.

Any ideas?

Just to be clear, I need to make the item completely disappear from
the list. The objective is to shorten the very long list so it is
easier to scroll through in searching for certain items.
 
M

Marc Gravell

Here you go - a fully worked example that filters a million records
using different filters, pretty-much instantly.

I hope you'll forgive my using C# 3 here - it makes writing both forms
snippets and delegates so much easier (and this uses both quite a
lot)... but you'll need VS 2008 (Express will do) to see it working.

Marc

using System;
using System.Collections.Generic;
using System.Windows.Forms;

public class Entity
{
public int Value { get; set; }
public int Id { get; set; }
}

static class Program
{
[STAThread]
static void Main()
{
// create some dummy data
const int SIZE = 1000000;
List<Entity> list = new List<Entity>(SIZE);
Random rand = new Random();
for (int i = 0; i < SIZE; i++)
{
list.Add(new Entity { Id = i, Value = rand.Next() });
}
Application.EnableVisualStyles();

// create the UI
using(ListView lv = new ListView {
Dock = DockStyle.Fill,
VirtualMode = true,
View = View.Details,
Columns = {"Id", "Value"}})
using(Button bAll = new Button {
Dock = DockStyle.Bottom,
Text = "All"})
using (Button bEvenRows = new Button {
Dock = DockStyle.Bottom,
Text = "Even Rows" })
using (Button bDivValues = new Button {
Dock = DockStyle.Bottom,
Text = "Values div 7" })
using(Form form = new Form {
Text = "Virtual Demo",
Controls = {lv, bAll, bEvenRows, bDivValues}}) {

// create a place-holder for the filtered sublist
List<Entity> filtered = null;

// create a delegate we can use to change the filter
Action<Predicate<Entity>> changeFilter = where => {
filtered = list.FindAll(where);
lv.VirtualListSize = filtered.Count;
lv.Update();
};

// wire the virtual mode data retreival
lv.RetrieveVirtualItem += (o,e) => {
Entity item = filtered[e.ItemIndex];
e.Item = new ListViewItem(
new[] {
new ListViewItem.ListViewSubItem() {Text =
item.Id.ToString()},
new ListViewItem.ListViewSubItem() {Text =
item.Value.ToString()}
}, 0);
};

// wire the buttons to apply different filters
bAll.Click += (o, e) => changeFilter(x => true);
bEvenRows.Click += (o, e) => changeFilter(x => x.Id % 2 ==
0);
bDivValues.Click += (o, e) => changeFilter(x => x.Value %
7 == 0);

// wire the form to display everything initially
form.Load += (o,e) => bAll.PerformClick();

// show the form
Application.Run(form);
}
}
}
 
B

Bob

Well, in this case I expect that "VirtualMode" is the way to go; that
way you don't have to add anything in the first place. As for the
backing store (which you will need to wire to the list manually)... if
you are using DataTable, then you can filter with strings;
unfortunately for the class-based approach this isn't implemented in
BindingList<T> (I have written a bound, filtering BindingList<T>, but
I made it predicate-based, not string based). In reality, I suspect it
is easier to keep two lists - the full list and the predicate-filtered
list, and tie your "VirtualMode" ListView to the filtered list.

Search for "+VirtualMode + ListView" for examples of usage.

Marc

Very clever, Marc! I'll take it for a spin. Thanks.
 

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

Similar Threads


Top