none
searching Listview columns in detail mode

    Question

  • Hi

    I have a listview set to detail mode that displays media files breaking down all the info into separate columns, title, artist, file size etc.

     

    I would like to add dual column text search capabilities using incremental searching.

     

    The plan is to enter a title narrowing the listview display down to media files with the entered title.

     

    Then in the second search text box enter the artist and have the listview now display only media files that contain both the title entered in the first search box and the artist entered in the second, displaying all files that meet both search criteria.

     

    Thank you

     

    Mike44P

    Saturday, September 13, 2008 3:10 AM

Answers

  • Hi Mike44P

     

    I have written an example for you. In this example I use DataTable.Select() method to filter the records for me.

     

    First you can write a ListView with inherited from the System.Windows.Forms.ListView

    Code Snippet

    public class ListView : System.Windows.Forms.ListView

        {

            public ListView()

            {

            }

           

            public void SetDataSource(DataTable dataTable)

            {

                try

                {

                    this.Items.Clear();

     

                    for (int i = 0; i < dataTable.Rows.Count; i++)

                    {

                        System.Windows.Forms.ListViewItem listViewItem = new ListViewItem();

                        listViewItem.SubItems[0].Text = dataTable.Rows[i][0].ToString();

                        for (int j = 1; j < dataTable.Columns.Count; j++)

                        {

                            listViewItem.SubItems.Add(dataTable.Rows[i][j].ToString());

                        }

                        this.Items.Add(listViewItem);

                    }

                }

                catch (Exception exp)

                {

                    throw exp;

                }

            }

    }

     

     

    SetDataSource can simplify the process in loading the records to your ListView.

    Then in your form, you can add your song and artist information to the DataTable and use Select method to filter them.

    Code Snippet

    public partial class Form1 : Form

        {

            private DataTable dtSong = new DataTable();

     

            public Form1()

            {

                InitializeComponent();

     

                dtSong.Columns.Add("SongName", typeof(string));

                dtSong.Columns.Add("ArtistName", typeof(string));

     

                dtSong.Rows.Add("abcd", "abcdd");

                dtSong.Rows.Add("abecd", "4t4abcdd");

                dtSong.Rows.Add("abbdecd", "rtabcdd");

                dtSong.Rows.Add("abrecd", "rg");

                dtSong.Rows.Add("abcerd", "fgfabcdd");

                dtSong.Rows.Add("abeecdfd", "rtahrbcdd");

                dtSong.Rows.Add("abcaed", "nmmabcdd");

     

                this.listView1.SetDataSource(dtSong);

     

                this.txtSongName.TextChanged += new EventHandler(txtSongName_TextChanged);

                this.txtArtist.TextChanged += new EventHandler(txtArtist_TextChanged);

            }

     

            void txtArtist_TextChanged(object sender, EventArgs e)

            {

                string soneName = txtSongName.Text;

                string artistName = txtArtist.Text;

     

                DataTable dtNewSource = dtSong.Clone();

     

                DataRow[] dr = dtSong.Select("SongName LIKE \'%" + soneName + "%\' and ArtistName LIKE \'%" + artistName + "%\'");

                for (int i = 0; i < dr.Length; i++)

                {

                    dtNewSource.ImportRow(dr[i]);

                }

     

                this.listView1.SetDataSource(dtNewSource);

            }

     

            void txtSongName_TextChanged(object sender, EventArgs e)

            {

                string soneName = txtSongName.Text;

                string artistName = txtArtist.Text;

     

                DataTable dtNewSource = dtSong.Clone();

     

                DataRow[] dr = dtSong.Select("SongName LIKE \'%" + soneName + "%\' and ArtistName LIKE \'%" + artistName + "%\'");

                for (int i = 0; i < dr.Length; i++)

                {

                    dtNewSource.ImportRow(dr[i]);

                }

     

                this.listView1.SetDataSource(dtNewSource);

            }

    }

     

     

    The key point is to handle the TextBox.TextChanged event to do the filter. After filter the records, you will get a new DataTable, then you can reload the data to the ListView by using the SetDataSource method.

     

    Sincerely,

    Kira Qian

     

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Tuesday, September 16, 2008 9:05 AM
  • Hi Mike44P

     

    The main reason I choose to use a DataTable is because it has a Select method which will do the filter for me. It’s quite easy to do this by using a filter expression. And in my example, I create a new ListView which inherited from the System one is just to simplify the loading process (otherwise you will have to write the similary code each time when you do a filter). It’s hard for me to tell which way is the most efficient one.

     

    Sincerely,

    Kira Qian

     

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Wednesday, September 17, 2008 1:48 AM

All replies

  • Sounds like a good plan.  You forgot to ask a question.
    Saturday, September 13, 2008 7:52 PM
  • What can I say rough day.

     

    I have the search working for one column but can't seem to get it for the second.

     

    The first search narrows the list down to the selected title however the second search clears the screen as soon as the first text is entered into the search box.

     

    So the question how to do an incremental search on two columns Title and then once the list is narrowed artist?

     

    Mike44P

    Sunday, September 14, 2008 6:47 PM
  • Hi Mike44P

     

    I have written an example for you. In this example I use DataTable.Select() method to filter the records for me.

     

    First you can write a ListView with inherited from the System.Windows.Forms.ListView

    Code Snippet

    public class ListView : System.Windows.Forms.ListView

        {

            public ListView()

            {

            }

           

            public void SetDataSource(DataTable dataTable)

            {

                try

                {

                    this.Items.Clear();

     

                    for (int i = 0; i < dataTable.Rows.Count; i++)

                    {

                        System.Windows.Forms.ListViewItem listViewItem = new ListViewItem();

                        listViewItem.SubItems[0].Text = dataTable.Rows[i][0].ToString();

                        for (int j = 1; j < dataTable.Columns.Count; j++)

                        {

                            listViewItem.SubItems.Add(dataTable.Rows[i][j].ToString());

                        }

                        this.Items.Add(listViewItem);

                    }

                }

                catch (Exception exp)

                {

                    throw exp;

                }

            }

    }

     

     

    SetDataSource can simplify the process in loading the records to your ListView.

    Then in your form, you can add your song and artist information to the DataTable and use Select method to filter them.

    Code Snippet

    public partial class Form1 : Form

        {

            private DataTable dtSong = new DataTable();

     

            public Form1()

            {

                InitializeComponent();

     

                dtSong.Columns.Add("SongName", typeof(string));

                dtSong.Columns.Add("ArtistName", typeof(string));

     

                dtSong.Rows.Add("abcd", "abcdd");

                dtSong.Rows.Add("abecd", "4t4abcdd");

                dtSong.Rows.Add("abbdecd", "rtabcdd");

                dtSong.Rows.Add("abrecd", "rg");

                dtSong.Rows.Add("abcerd", "fgfabcdd");

                dtSong.Rows.Add("abeecdfd", "rtahrbcdd");

                dtSong.Rows.Add("abcaed", "nmmabcdd");

     

                this.listView1.SetDataSource(dtSong);

     

                this.txtSongName.TextChanged += new EventHandler(txtSongName_TextChanged);

                this.txtArtist.TextChanged += new EventHandler(txtArtist_TextChanged);

            }

     

            void txtArtist_TextChanged(object sender, EventArgs e)

            {

                string soneName = txtSongName.Text;

                string artistName = txtArtist.Text;

     

                DataTable dtNewSource = dtSong.Clone();

     

                DataRow[] dr = dtSong.Select("SongName LIKE \'%" + soneName + "%\' and ArtistName LIKE \'%" + artistName + "%\'");

                for (int i = 0; i < dr.Length; i++)

                {

                    dtNewSource.ImportRow(dr[i]);

                }

     

                this.listView1.SetDataSource(dtNewSource);

            }

     

            void txtSongName_TextChanged(object sender, EventArgs e)

            {

                string soneName = txtSongName.Text;

                string artistName = txtArtist.Text;

     

                DataTable dtNewSource = dtSong.Clone();

     

                DataRow[] dr = dtSong.Select("SongName LIKE \'%" + soneName + "%\' and ArtistName LIKE \'%" + artistName + "%\'");

                for (int i = 0; i < dr.Length; i++)

                {

                    dtNewSource.ImportRow(dr[i]);

                }

     

                this.listView1.SetDataSource(dtNewSource);

            }

    }

     

     

    The key point is to handle the TextBox.TextChanged event to do the filter. After filter the records, you will get a new DataTable, then you can reload the data to the ListView by using the SetDataSource method.

     

    Sincerely,

    Kira Qian

     

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Tuesday, September 16, 2008 9:05 AM
  • Kira

    Is there an advantage to using the dataset over just the listview directly?

     

    I was trying to use something like this:

     

    foreach (ListViewItem item2 in mediaLibrayListView.Items)

    {

    if (searchColumn2.ToLower().StartsWith(fileSearch2Tbx.ToString().ToLower()))

    {

    mediaLibrayListView.Items.Clear();

    mediaLibrayListView.Items.Add(item2);

    mediaFilesCount = mediaLibrayListView.Items.Count;

    }

    }

     

    The above is called via the text changed event as you mentioned.

     

    Speed is a serious consideration for me as the records will be around 50,000 files with subs and tags when fully populated.

     

    The above isn't fully working yet but I'm close, the first search box populates the listview with the applicable data however the second isn't quite up to speed, I'm not sure if I'm accessing the new list properly.

     

    Mike44P

    Tuesday, September 16, 2008 6:19 PM
  • Hi Mike44P

     

    The main reason I choose to use a DataTable is because it has a Select method which will do the filter for me. It’s quite easy to do this by using a filter expression. And in my example, I create a new ListView which inherited from the System one is just to simplify the loading process (otherwise you will have to write the similary code each time when you do a filter). It’s hard for me to tell which way is the most efficient one.

     

    Sincerely,

    Kira Qian

     

    Windows Forms General FAQs
    Windows Forms Data Controls and Databinding FAQs

    Wednesday, September 17, 2008 1:48 AM