How to execute advance Listview Search - c#

Using Windows forms, My 'listview' have multiple columns as shown in the picture.
I have been trying to make this txtbox_search to be advanced. When any character, word or number is inserted, i want Some columns of my listview to be traversed to look for the character, word, number and bring up data related to the input.
Like when i enter: txtbox_search.Text = "a"
It should travers column "Name" and fill Listview with data:
entire row that has a name which starts with "a" such as "Anwar"
entire row that has a name which starts with "a" such as "Anas"
so on with entire rows that has a name which starts with "A..."
when i enter: txtbox_search.Text = "1"
It should travers column "ID" and fill Listview with data:
entire row that has a ID which starts with "1" such as "1002"
entire row that has a ID which starts with "1" such as "1112"
so on with entire rows that has a ID which starts with "1..."
so far i have been trying this for 2 days and end up with this much:
private void textBox_DEC_Search_TextChanged(object sender, EventArgs e)
{
foreach(ListViewItem Items in listView_DEC_CustomerList.Items)
{
if(Items.Text == textBox_DEC_Search.Text)
{
listView_DEC_CustomerList.Items.Clear();
listView_DEC_CustomerList.Items.Add(Items);
}
}
if(textBox_DEC_Search.Text == "" || textBox_DEC_Search.Text == string.Empty)
{
CusList Cus = new CusList();
Cus.CustomersList(listView_DEC_CustomerList);
}
}
This code only travers first column and bring up data that matches the inserted ID, only if the Complete ID matches with txtbox_search.Text how can i make this possible? (i want it to be on client side, not from sql/database). Guides and sample code helps will be really appreciated. Thanks.

To distinguish between your 2 criteria you could use the following:
if (textBox_DEC_Search.Text.All(x => Char.IsNumber(x)))
{
Debug.WriteLine("Number");
// search through ID
}
else
{
Debug.WriteLine("Name");
// search through Name
}
It basically checks whether your input is solely numeric.
EDIT:
To check for similarity you cold use String.StartsWith of String.Contains to make the search a little more flexible
to look for the ID or NAME you need to access the subitems!
since ID is your first column check SubItems[0]
if(Items.SubItems[0].Text.StartsWith(textBox_DEC_Search.Text) ||
Items.SubItems[0]Text.Contains(textBox_DEC_Search.Text))
since NAME is your second column check SubItems[1]
if(Items.SubItems[1].Text.StartsWith(textBox_DEC_Search.Text) ||
Items.SubItems[1]Text.Contains(textBox_DEC_Search.Text))
One Problem is this line:
listView_DEC_CustomerList.Items.Clear();
because it will erase the first found result when the second is found.
So if you find 10 matches the previous 9 will be deleted!
I suggest to make first the entire search and then add the results if there are any:
private void textBox_DEC_Search_TextChanged(object sender, EventArgs e)
{
// index is 0 if numeric for ID or 1 if not for NAME
int ind = textBox_DEC_Search.Text.All(x => Char.IsNumber(x)) ? 0 : 1;
List<ListViewItem> matchlist = new List<ListViewItem>();
foreach(ListViewItem Items in listView_DEC_CustomerList.Items)
{
if(Items.SubItems[ind].Text.StartsWith(textBox_DEC_Search.Text) ||
Items.SubItems[ind]Text.Contains(textBox_DEC_Search.Text))
{
matchlist.Add(Items);
}
}
// if you have found something add the all results
if(matchlist.Any())
{
listView_DEC_CustomerList.Items.Clear();
listView_DEC_CustomerList.Items.AddRange(matchlist.ToArray());
}
}
Disclaimer: Although this solution should work I would vote to follow the advice of #RezaAghaei. It is less messy and confusing than directly manipulating the ListView

Instead of using == which looks for an exact match try one of the following (I am assuming 'Text' is the column name in the list containing the name - if not change it to Items.Name (for example)
if you want to search on 'starting with' then try
if (Items.Text.StartsWith(textBox_DEC_Search.Text.Trim())
if you want to search based on the fact that a part of the string should be looked up then try
if (Items.Text.Contains(textBox_DEC_Search.Text.Trim())
You can similarly do for any other column you would like to search on. if you want to make the search case insensitive then use .ToLower() on the string and the column name.

Related

Sequence contains no match element but Element is there

I have a simple search box and button that is bound to a command, the command fires fine and passes the textbox parameter but when it hits the SearchStock method it runs through the list and doesn't match the parameter even though the element is there? Don't understand why its not matching, possibly my poor LINQ skills
Search Stock method
private void SearchStock(object _ticker)
{
var stock = Stocks.SingleOrDefault(x => x.Ticker == _ticker.ToString());
_selectedstock = (Stock)stock;
}
When I step into it it is showing the element ticker, I noticed that there were spaces after the Ticker name so I changed the column to NVARCHAR but it still didn't work
Ok so you find why it is not working all alone. "FB " is not equal to "FB".
You have 2 options :
Try to fix the used stored database string format.
use var stock = Stocks.SingleOrDefault(x => x.Ticker.Trim() == _ticker.ToString()); to ignore space in code

How to get particular infomation stored in list

I am using a existing web service which does a postcode search its then stored In a list box the values: "ID", "Text", "Highlight", "Cursor", "Description", "Next". I need to try and access a particular string value which is the ID & Next param and use it for validation later on. When I click on the list box I want the particular data to be taken stored then access the two pieces of information I need. How do I access the information on a particular row of the list box and use that later on?
try
{
int myMaxResultValue = (int)nud_MaxResults.Value;
int myMaxSuggestValue = (int)nud_MaxSuggestions.Value;
findResults = objBvSoapClient.CapturePlus_Interactive_Find_v2_10("Dak4-KZ62-AAdd87-X55", txt_Search.Text, txt_LastId.Text, cb_SearchFor.Text, text_Country.Text, text_LanguagePreference.Text, myMaxResultValue, myMaxSuggestValue);
if (txt_Search.Text.Length <= 2)// if less than two letters are entered nothing is displayed on the list.
{
ls_Output.Items.Clear();// Clear LstBox
ls_Output.Items.Add(String.Format(allDetails, "ID", "Text", "Highlight", "Cursor", "Description", "Next"));
MessageBox.Show("Please enter more than 2 Chars!!");
}
else if (txt_Search.Text.Length >= 3)// if greater than or equal to 3 letters in the search box continue search.
{
// Get Results and store in given array.
foreach (var items in findResults)
{ //Loop through our collection of found results and change resulting value.
ls_Output.Items.Add(String.Format(allDetails, items.Id, items.Text.ToString(), items.Highlight, items.Cursor, items.Description, items.Next));
}
}
}
As a side note your string.Format missing the variables in the string. It should be more like this
int id = 30;
string text = "Hello";
string.Format("This is the ID {0}. Here is some text {1}.", id, text);
The output will be "This is the ID 30. Here is some text Hello.".
To answer your question, you'll have to parse it to pull out the parts you want. You could use regex.split to do this. For example, if it's delimited on space you could do something like this
string[] data = Regex.Split(operation, #"\s+");
Then you can access it like this
string required = data[3];

Searching a access database for a part of a word

I have an access database that contains columns such as Title, Director, And Year.
I have access database connected to the program. I am able to search the database and print out the title of the movie to a listBox only if the title contains the one word. For example, if I search for the movie "psycho" the movie will display in the listBox.
Now I'm wondering how I can search for a particular word like "the" and print all the movie titles with "the" in it to the listBox.
At that point, the text book I'm using fails to go into anything deeper.
Maybe I'm not using the right method for what I'm trying to do.
private void searchButton_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
string lowerCaseData = textBox1.Text.ToLower();
if (titleButton.Checked)
{
var query =
from m in this.moviesDataSet.Movies
where m.Title == lowerCaseData
select m;
foreach (var m in query)
{
listBox1.Items.Add(m.Title);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'moviesDataSet.Movies' table. You can move, or remove it, as needed.
this.moviesTableAdapter.Fill(this.moviesDataSet.Movies);
}
Instead of exact match check for Contains
Depending on the LINQ provider, Contains check should be translated to SQL LIKE statement which will be case insensitive, so your check should be:
where m.Title.Contains(lowerCaseData)
However for in-memory collections, Contains would perform a case sensitive match. In that case String.IndexOf can be used like:
where m.Title.IndexOf(lowerCaseData, StringComparison.OrdinalIgnoreCase) >= 0)
Your where query is doing an exact match. Use Contains instead
where m.Title.ToLower().Contains(lowerCaseData)

C# report edit column values

I'm generating a report based on a database table. In the table I have genders saved as either 0 or 1 (male/female). In the report I would like to show the string value rather than showing the numbers. I tried messing with the code, ie.
this.ItemsTableAdapter.Fill(this.InventoryDataSet.Items);
foreach (DataRow row in this.InventoryDataSet.Items.Rows)
{
if (row["gender"].ToString() == "0")
{
row["gender"] = "Male";
}
}
this.reportViewer1.RefreshReport();
However this breaks the report complelty (no data is shown). How can I achieve what I want?
[edit]
I came a little closer to the solution (I think) with this:
this.InventoryDataSet.Items.Columns.Add("genderVerbose", typeof(string));
foreach (DataRow row in this.InventoryDataSet.Items.Rows)
{
if (row["gender"].ToString() == "0")
{
row["genderVerbose"] = "Male";
}
}
However now I get this error when trying to use the field in the report:
Error 2 The Value expression for the text box ‘color’ refers to the
field ‘genderVerbose’. Report item expressions can only refer to
fields within the current dataset scope or, if inside an aggregate,
the specified dataset scope. Letters in the names of fields must use
the correct case.
How about assigning Enum values to the cells? Enum.ToString() by default gives the value name in code as the string. So with:
public enum Gender { Male, Female }
You can just shove those into DataGridView cells and it will show that way. You can test values by
if ((Gender)row["gender"].Value == Gender.Male)
{
// do things...
}
If you need this to be user-selectable, you can use the DataGridViewComboBoxCell.

Reduce the number of item in datagridview while user types in C#

I have datagrid view filled with values
I have to create a search in datagridview.
private void textBox_Search_TextChanged(object sender, EventArgs e)
{
String search = textBox_Search.Text.Trim();
if (!String.IsNullOrEmpty(search))
{
dataGridView_LicenseKey.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;
webservicelicencesBindingSource.Filter = string.Format("{0}= '{1}'", "nom_centre", search);
}
}
I use above code.
Explaination of above code : When i type first letter in the textbox ;the datagridview becomes empty unless i type the complete string which matches the value in datagridview.
What i want : when i press the letter in the text box , datagridview should reduce .
For example :
values in Datagrid view
1. ABCDE
2. ABEFG
3. erdzf
4. rezfj
5. Agfe
When I type "A" in text box
value in Data grid view
1. ABCDE
2. ABEFG
3. Agfe
When I type "AB" in text box
value in Data grid view
1. ABCDE
2. ABEFG
When I type "ABC" in text box
value in Data grid view
1. ABCDE
and so on.
Need help in this.
Thanks in Advance.
Your filter condition is wrong, it filters exact values only. It should look like this:
webservicelicencesBindingSource.Filter = string.Format("{0} LIKE '{1}%'", "nom_centre", search);
(Doesn't have to be uppercase)
EDIT:
To show all results again, you have to improve condition when the search term is empty, like this:
dataGridView_LicenseKey.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;
if (!String.IsNullOrEmpty(search))
{
webservicelicencesBindingSource.Filter = string.Format("{0}= '{1}'", "nom_centre", search);
}
I suppose that bad filtering that you mentioned in the comment could happen because the event is fired at EVERY text change. So if you have search term 'AB', deleting one character by time, it would first filter by 'A', and then would cancel another filter because the search string was empty. This scenario would give mentioned result.

Categories