0

I am using a multi-column listView control in Visual Studio 2013 and coding with C#. I want to do a search on multiple columns as if I were doing a database SELECT. For example, if the first three columns were NAME, AGE and CITY, I might want to search for an Item where NAME = "Fred", AGE >= 20 and CITY = "Chicago" and then select that Item.

  • What is the most efficient way to do this?
  • Can linq be used?
  • Is there another way short of traversing the entire collection of Items and testing each column value? Appreciate any assistance.
Mrinal Kamboj
  • 11,300
  • 5
  • 40
  • 74
Algodevguy
  • 31
  • 6
  • I just realized that listView only supports strings unlike datagrid so please frame any answers as if the selection criteria were all based on string type variables. Thanks again. – Algodevguy Jun 09 '15 at 08:14

2 Answers2

0

Yes, it can be done, you are using the multi-column listView control, which i assume would have a data source like datatable. Which would contains Columns / Rows which would be rendered in the control.

You can easily use Linq to achieve the result, something like:

dataTable.AsEnumerable
         .Where(x=>x["NAME"] == "Fred")
         .Where(x=>x["AGE"] >= 20)
         .Where(x=>x["CITY"] == "Chicago")

Here each x represents a Row, since you are enumeration a Row Collection of a DataTable. Final result will be of Type IEnumerable<DataRow>, which you need to use to create separate DataTable than can be bind to the control, I am not sure if you can bind the IEnumerable<DataRow>.

Also check the following links:

Linq : select value in a datatable column

LINQ query on a DataTable

Adding more details to help OP further, the class available is List, that you are binding to the control, this makes life even easier, since, it is an IEnumerable type, what you need to do it use this class in the Linq query above as follows:

IList<ListClass> lc = new List<ListClass>();

Now lc contains all data for control binding, what you need to do is

var Result = lc
             .Where(x=>x.Name == "Fred")
             .Where(x=>x.Age >= 20)
             .Where(x=>x.City == "Chicago").ToList();

Here Result will be of type List<ListClass>, which contains the filtered records, as per your requirement, which can be used for binding with the control.

Here x would be an object of ListClass in the Linq query, similarly you can dynamically supply values to the Linq query and keep getting the filtered subset. All the properties will be available in intellisense since we have strongly typed object. Hope this helps in further clarifying.

Community
  • 1
  • 1
Mrinal Kamboj
  • 11,300
  • 5
  • 40
  • 74
  • Thanks very much for that lightning-fast response! Apologies but I am rather new to C# and the .NET world. Could I trouble you to expand your example slightly so I could put it into my context. Given the declaration: public IList myList = new List(); How would I apply the expression you gave above to search this list. Thanks again – Algodevguy Jun 09 '15 at 08:40
  • What part are you not clear, so that I can help further and add more details – Mrinal Kamboj Jun 09 '15 at 08:42
  • Added more details at the bottom part – Mrinal Kamboj Jun 09 '15 at 08:49
  • Now, I am traversing the list by going: foreach(ListViewItem myItem in myList) { if ((myItem.SubItems[0].Text == "Fred") && ...... etc. then do something. How would I use your example instead of what I am doing now. Thanks. – Algodevguy Jun 09 '15 at 08:50
  • Use my code to create a sublist os main List, Linq query is a replacement of the Foreach loop. Here Result is of type List and its filtered, it can directly be supplied to the control – Mrinal Kamboj Jun 09 '15 at 08:51
  • Awesome! quick followups: 1) once I apply the results to the control, I assume it shows up in the view. How would I return the view to the full list? 2) If the search results in 1 item, I assume it is selected? If multiple items are in the results, is the top item selected? 3) If there are no results (lc == null)? – Algodevguy Jun 09 '15 at 09:08
  • Yes once you apply filtered result, then that would bind the control. Your full list remains in the object lc, filtered version is a new object, just bind the original object. Selection is a control property, you need to manage that via control, not the list collection. You need to do null check before binding. Binding with Null leaves control empty, this should be be bare minimum empty collection to show at least the headers – Mrinal Kamboj Jun 09 '15 at 09:15
  • Again, thanks very much for continuing to answer my questions. I will try what you said. Hope you don't mind if I have some followups later. – Algodevguy Jun 09 '15 at 09:47
  • @Algodevguy Since my answer has helped you, if you don't mind can you upvote it – Mrinal Kamboj Jun 09 '15 at 17:17
0

The type of ListView.Items is ListView.ListViewItemCollection, which implements IEnumerable, so surely LINQ can be used. You can do something like the following:

theListView.Items.Where(item =>
    item.Text == "Fred" &&
    Int32.Parse(item.SubItems[0].Text) >= 20 &&
    item.SubItems[1].Text == "Chicago")
ycsun
  • 1,825
  • 1
  • 13
  • 21