C# ListView – MultiColumn Search/Filter

In this tutorial we will see how to search or filter a multicolumn ListView. We have a TextBox where the user enters the search term and we filter the data in our ListView taking into account all the columns and rows in the ListView.

Once the user has searched data, he can click on the ListView row to view the result in a messagebox.

Our programming language is C#.

Aims

Our aim is to Perform a multi-column, multi-parameter search filter of our C# windows forms listview.

We use a TextBox for the user to type the search query or term.

Let's start.

We are Building a Vibrant YouTube Community

We have a fast rising YouTube Channel of friends. So far we've accumulated more than 2.6 million agreggate views and more than 10,000 subscribers. Here's the Channel: ProgrammingWizards TV.

Please go ahead subscribe(free obviously) as well. If you have a question or a comment you can post there instead of in this site.People are suggesting us tutorials to do there so you can too.

Here's this tutorial in Video Format.

Program.cs

We normally prefer to code our C# Windows Forms applicatios from scratch, without designer. This is the best way for our people to understand, since we move line by line.

Add Using Statements

We will first specify three imports via the using directives. These are namespaces we are importing.

We need System.Windows.Forms and System.Drawing for construction of our user interface.

using System;
using System.Drawing;
using System.Windows.Forms;

Create our Namespace

This namespace will hold our C# classes. We will have several of them.

namespace ListViewSearchFilter
{...}

Create C# POCO Class

POCO stands for Plain Old CLR Object. CLR stands for Common Language Runtime.
This class is our data object. It basically represents a single Nebular object. We will be searching nebulas.

The Nebular will have a name, type and Spaceship properties. Users will be able to search our ListView by any of these parameters.

    class Nebular
    {
        public string Name { get; set; }
        public string Type { get; set; }
        public string Spaceship { get; set; }
    }

Create our Main Class

The main class is the class that has the main method. The main method is normally the entry point to all C# executable applications.

    static partial class Program
    {
        ...
    }

Add Class Data Members

These are static fields, that is fields belonging to the class as opposed to the instance of the class.
Our class is first and foremost a static class.

These field include:

  1. ListView - To render our nebulas in a multi-column list.
  2. TextBox - For searching the ListView.
  3. Form - Our windows form. To hold other components.
  4. Array Field - To hold our data.
  5. Boolean Field - To hold the selection state of a ListView item.
        private static ListView myListView;
        private static TextBox searchTxt;
        private static Form myForm;
        private static Nebular[] nebulae;
        private static bool selected;

Generate our Data Set

We use a simple array as our data source. This array will contain our Nebular objects.

        private static void populateData()
        {
            nebulae = new[]
            {
                new Nebular {Name="Horse Head",Type = "HII REGION",Spaceship= "James Web"},
                new Nebular {Name="Black Widow",Type="DARK NEBULAR",Spaceship= "Casini"},
                ......

Create ListViewItems

To populate our Windows Form ListView with data, we will loop through the array, instantiating the ListViewItem class, while passing in an array containing the properties of our Nebular.

This will ensure that we will be populating our multi-column listview with data.

        foreach (Nebular s in nebulae)
            {
                myListView.Items.Add(new ListViewItem(new[] { s.Name, s.Type,s.Spaceship }));
            }
        }

How to Search our C# ListView

We will first create a method that will take the query or searchTerm as a parameter. This searchTerm is our constraint, it is what the user will be typing in the TextBox.

        private static void searchData(string searchTerm)
        {
            ...

So first we clear the ListView using the Clear() method.

            myListView.Items.Clear();

Then loop through our data set:

            foreach (Nebular s in nebulae)
            {
                ...

We are searching using the Contains() method defined in the String class. First we convert our parameters, that is Name,Type and Spaceship properties to lower case.

Then we convert the searchTerm to lower case as well.

Then compare the two:

                if (s.Name.ToLower().Contains(searchTerm.ToLower()) || s.Type.ToLower().Contains(searchTerm.ToLower()) || s.Spaceship.ToLower().Contains(searchTerm.ToLower()))

If this evaluates to true, we add the Nebular with its properties to our ListView as a ListViewItem:

                {
                    myListView.Items.Add(new ListViewItem(new[] {s.Name, s.Type,s.Spaceship}));
                }

Register Event Handlers

These are the event handlers for:

  1. ListView :: ItemSelectionChanged - so that we get the selected ListView item.
  2. TextBox :: TextChanged - so that we can search in realtime as the user types.

Create the TextBox TextChanged Event Handler

As the user types data in the TextBox, the TextChanged event will be raised. We simple invoke the searchData() method, passing in the typed searchTerm.

        static void searchTxt_TextChanged(object sender, EventArgs e)
        {
            searchData(searchTxt.Text);
        }

Show Selected listView Item in MessageBox

If the user clicks or selects an item in our ListView, even after searching, we will get it and show it in a messagebox.

        static void myListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (e.IsSelected)
            {
                MessageBox.Show("NEBULAR : "+myListView.SelectedItems[0].SubItems[0].Text + "n" +
                    "TYPE : "+myListView.SelectedItems[0].SubItems[1].Text + "n" + 
                    "SPACESHIP : "+myListView.SelectedItems[0].SubItems[2].Text);
                selected = true;
            }
            else
            {
                selected = false;
            }
        }

Create our Windows Form Programmatically

We will first create a method to do so.

        private static void createForm(){ ...}

Inside the method we instantiate the Form, setting its properties:

            myForm = new Form
            {
                AutoScaleDimensions = new SizeF(6F, 13F),
                AutoScaleMode = AutoScaleMode.Font,
                Text = "C# ListView : Array - MultiColumn Search/Filter",
                ClientSize = new Size(520, 585),
                BackColor = Color.Salmon
            };

Here's the full source code.

Full Code

using System;
using System.Drawing;
using System.Windows.Forms;

namespace ListViewSearchFilter
{
    /*
     * POCO. Our data object
     */
    class Nebular
    {
        public string Name { get; set; }
        public string Type { get; set; }
        public string Spaceship { get; set; }
    }
    static partial class Program
    {
        /*
         * static fields
         */
        private static ListView myListView;
        private static TextBox searchTxt;
        private static Form myForm;
        private static Nebular[] nebulae;
        private static bool selected;

        /*
         * Generate data and populate our ListView.
         */
        private static void populateData()
        {
            nebulae = new[]
            {
                new Nebular {Name="Horse Head",Type = "HII REGION",Spaceship= "James Web"},
                new Nebular {Name="Black Widow",Type="DARK NEBULAR",Spaceship= "Casini"},
                new Nebular {Name="Ghost Head",Type="REFLECTION NEBULAR",Spaceship= "New Horizon"},
                new Nebular {Name="Witch Head",Type="PLANETRAY NEBULAR",Spaceship= "Star Dust"},
                new Nebular {Name="Cat's Eye",Type="SUPERNOVA REMNANT",Spaceship= "Juno"},
                new Nebular {Name="Elephant's Trunk",Type="REFLECTION NEBULAR",Spaceship= "Opportunity"},
                new Nebular {Name="Snake",Type="DARK NEBULAR",Spaceship= "Hubble"},
                new Nebular {Name="Butterfly",Type="HII REGION",Spaceship= "Endeavor"},
                new Nebular {Name="Ant",Type="HII REGION",Spaceship= "Apollo 15"},
                new Nebular {Name="Rosette",Type="REFLECTION NEBULAR",Spaceship= "Atlantis"},
                new Nebular {Name="Bernard 68",Type="SUPERNOVA REMNANT",Spaceship= "Columbia"},
                new Nebular {Name="Helix",Type="DARK NEBULAR",Spaceship= "Challenger"},
                new Nebular {Name="Pelican",Type="HII REGION",Spaceship= "Enterprise"},
                new Nebular {Name="Orion",Type="PLANETRAY NEBULAR",Spaceship= "Galileo"},
                new Nebular{Name="Eagle",Type="REFLECTION NEBULAR",Spaceship= "WMAP"},
                new Nebular {Name="Own",Type="PLANETRAY NEBULAR",Spaceship= "Swift"},
                new Nebular{Name="Ring",Type="REFLECTION NEBULAR",Spaceship= "Voyager B"},
                new Nebular{Name="Flame",Type="PLANETRAY NEBULAR",Spaceship= "Spitzer"},
                new Nebular{Name="Cone",Type="DARK NEBULAR",Spaceship= "Pioneer"},
                new Nebular{Name="Bumerang",Type="SUPERNOVA REMNANT",Spaceship= "Voyager A"},

            };
            //POPULATE SPACECRAFTS
            foreach (Nebular s in nebulae)
            {
                myListView.Items.Add(new ListViewItem(new[] { s.Name, s.Type,s.Spaceship }));
            }
        }
        /*
         * Search Data using Contains() method
         */
        private static void searchData(string searchTerm)
        {
            myListView.Items.Clear();
            foreach (Nebular s in nebulae)
            {
                if (s.Name.ToLower().Contains(searchTerm.ToLower()) || s.Type.ToLower().Contains(searchTerm.ToLower()) || s.Spaceship.ToLower().Contains(searchTerm.ToLower()))
                {
                    myListView.Items.Add(new ListViewItem(new[] {s.Name, s.Type,s.Spaceship}));
                }
            }
        }
        /*
         * Set up event handlers
         */
        private static void setUpEventHandlers()
        {
            myListView.ItemSelectionChanged += myListView_ItemSelectionChanged;
            searchTxt.TextChanged += searchTxt_TextChanged;
        }
        /*
         * TextChanged event of our TextBox
         */
        static void searchTxt_TextChanged(object sender, EventArgs e)
        {
            searchData(searchTxt.Text);
        }
        /*
         * When ListViewItem is selected show it in a messagebox
         */
        static void myListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (e.IsSelected)
            {
                MessageBox.Show("NEBULAR : "+myListView.SelectedItems[0].SubItems[0].Text + "n" +
                    "TYPE : "+myListView.SelectedItems[0].SubItems[1].Text + "n" + 
                    "SPACESHIP : "+myListView.SelectedItems[0].SubItems[2].Text);
                selected = true;
            }
            else
            {
                selected = false;
            }
        }

        /*
         * Create Form, set it's properties
         */
        private static void createForm()
        {
            myForm = new Form
            {
                AutoScaleDimensions = new SizeF(6F, 13F),
                AutoScaleMode = AutoScaleMode.Font,
                Text = "C# ListView : Array - MultiColumn Search/Filter",
                ClientSize = new Size(520, 585),
                BackColor = Color.Salmon
            };
            createComponents();
            populateData();
            setUpEventHandlers();
            Application.EnableVisualStyles();
            Application.Run(myForm);
        }
        /*
       * Main method
       */
        public static void Main()
        {
            createForm();
        }
    }
    /*
     * Our Partial Program class
     * Create WinForms components for us.
     * Exists in the same namespace.
     */
    static partial class Program
    {
        public static void createComponents()
        {
            /*
             * Create a Label,set its properties
             */
            Label searchLabel = new Label
            {
                Location = new Point(57, 106),
                Size = new Size(38, 19),
                Font = new Font("Segoe UI", 12F, FontStyle.Bold, GraphicsUnit.Pixel),
                Text = "Filter: "
            };
            /*
             * Create TextBoxes, set its properties
             */
            searchTxt = new TextBox
            {
                Location = new Point(146, 106),
                Size = new Size(173, 23),
                TabIndex = 0
            };
            /*
             * Create ListView, set its properties, add columns
             */
            myListView = new ListView { Location = new Point(57, 165), Size = new Size(400, 400), View = View.Details, FullRowSelect = true, Alignment = ListViewAlignment.SnapToGrid };
            myListView.Columns.Add("NEBULAR", 100);
            myListView.Columns.Add("CATEGORY", 150);
            myListView.Columns.Add("SPACESHIP", 150);
            /*
             * Add Components to Form
             */
            myForm.Controls.Add(searchLabel);
            myForm.Controls.Add(searchTxt);
            myForm.Controls.Add(myListView);
        }
    }
}

Result

C# ListView Search Filter
C# ListView Search Filter

Running The Code

We write our code from scratch because its the best way to learn, as opposed to using the designer.
So to run the above code:

  1. Create an console application.
  2. Copy paste the code above to the console application.
  3. Add System.Windows.Forms and System.Drawing references to your project. Well right click your project, the choose Add References, the search System.Windows.Forms and System.Drawing, check them and add them to the project.
  4. That's it.

Best Regards.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *