wulfgarpro
wulfgarpro

Reputation: 6934

Filtering a ListBox

I have a ListBox named lsbEntities. I want to filter it's items based on some selected radio button.

The code below is kind of pseudo, is their a better approach?

private List<string> _listBoxItemsToFilter;
private Thread tFilterEntityList;

enum EntityType
{
    Vehicle,
    Facility
}

private void FilterEntityList(EntityType entityType)
{
    _listBoxItemsToFilter = new List<string>();
    Dictionary<string,string> entitiesAndClassTypes;
    List<string> listBoxItems = new List<string>();

    for(int i = 0; i < lsbEntities.Count; i++)
    {
        //object listItem = lsbEntities.Items[i];           
        listBoxItems.Add(lsbEntities[i].ToString());    
    }

    // get associated types
    entityClassTypes = _controlFacade.GetClassTypes(listBoxItems);

    foreach (KeyValuePair<string,string>
            entityAndClass in entitiesAndClassTypes)
    {
        classType = entityAndClass.Value;

        if(classType != entityType)
        {
                _listBoxItemsToFilter.Add(entityAndClass.Key);          
        }
    }

    RemoveFilterFromEntityListBox();
    AddFilterToEntityListBox();
}

private void AddFilterToEntityListBox()
{
    // DELEGATE NEEDED TO MODIFY LISTBOX FROM THREAD
    foreach(string listBoxItem in _listBoxItemsToFilter)
    {
        if(lsbEntities.Contains(listBoxItem)
        {
            // REMOVE WITH DELEGATE
        }
    }
}

private void RemoveFilterFromEntityListBox()
{
    // DELEGATE NEEDED TO MODIFY LISTBOX FROM THREAD
    if(_listBoxItemsToFilter != null)
    {
        foreach(string listBoxItem in _listBoxItemsToFilter)
        {
            if(!lsbEntities.Contains(listBoxItem)
            {
            // REMOVE WITH DELEGATE
            }
        }
    }
}

 // EXAMPLE CALL WHEN CLICKING RADIO-BUTTON
 private void rbVehicles_CheckedChanged(object sender, EventArgs e)
 {
     switch (rbVehicles.Checked)
     {
         case (true):
         {
             object entityType = (object)EntityType.Vehicle;
             tFilterEntityList = new Thread(FilterEntityList(entityType));
             tFilterEntityList.IsBackground = true;
             tFilterEntityList.Start(); 
             //FilterEntityList(EntityType.Vehicle);
             break;
         }
     }
 }

I have only included an example of selecting to filter everything but VehicleS. The same approach would be used for the Facility class, where the thread would be re-instantiated.

Upvotes: 4

Views: 2406

Answers (1)

Tergiver
Tergiver

Reputation: 14517

Here is a simple example showing one way to filter items in a ListBox. This could be improved by using a ListView or DataGridView in VirtualMode. It is very unclear to me what you are trying to do, so if this is not helpful I will remove it.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

public class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    List<Entity> items = new List<Entity>()
    {
        new Entity(EntityType.Vehicle, "Car"),
        new Entity(EntityType.Vehicle, "Aeroplane"),
        new Entity(EntityType.Vehicle, "Truck"),
        new Entity(EntityType.Vehicle, "Bus"),
        new Entity(EntityType.Facility, "Garage"),
        new Entity(EntityType.Facility, "House"),
        new Entity(EntityType.Facility, "Shack"),
    };

    ListBox listBox;
    ComboBox comboBox;

    public Form1()
    {
        Text = "Filtering Demo";
        ClientSize = new Size(500, 320);
        Controls.Add(listBox = new ListBox
        {
            Location = new Point(10, 10),
            Size = new Size(200, 300),
        });
        Controls.Add(comboBox = new ComboBox
        {
            Location = new Point(230, 10),
            DropDownStyle = ComboBoxStyle.DropDownList,
            Items = { "All", EntityType.Vehicle, EntityType.Facility },
            SelectedIndex = 0,
        });

        comboBox.SelectedIndexChanged += UpdateFilter;
        UpdateFilter(comboBox, EventArgs.Empty);
    }

    void UpdateFilter(object sender, EventArgs e)
    {
        var filtered = items.Where((i) => comboBox.SelectedItem is string || (EntityType)comboBox.SelectedItem == i.EntityType);
        listBox.DataSource = new BindingSource(filtered, "");
    }
}

enum EntityType { Vehicle, Facility, }

class Entity : INotifyPropertyChanged
{
    public string Name { get; private set; }
    public EntityType EntityType { get; private set; }
    public Entity(EntityType entityType, string name) { EntityType = entityType; Name = name; }
    public override string ToString() { return Name ?? String.Empty; }
    // Implementing INotifyPropertyChanged to eliminate (caught) BindingSource exceptions
    public event PropertyChangedEventHandler PropertyChanged;
}

Upvotes: 3

Related Questions