Ok... so I have got a working procedure to search a ListView. This procedure
works successfully however, it only searches 1 of 5 columns. My desire is to
get the procedure to search the first 2 columns which are forename and surname. I found a line of code which is suppose to do it but after compilation, it produces an error. Below is an excerpt of my code. and the line I am trying to use.
Thanks in advance for all the help and advice
private void button3_Click(object sender, EventArgs e)
{
string s = " Search Via Forename";
int result = 0;
int count = 0;
result = string.Compare(textBox1.Text, s);
if ((result == 0) || (String.IsNullOrEmpty(textBox1.Text)))
{
MessageBox.Show("Please input forename...");
return;
}
foreach(ListViewItem.ListViewSubItem subItem in item.SubItems)
{
if (item.Text.ToLower().StartsWith(textBox1.Text.ToLower()))
{
count++;
statusBar1.Panels[2].Text = "Found: " + count.ToString();
}
else
{
listView1.Items.Remove(item);
}
}
button1.Text = "Clear";
textBox1.Visible = false;
button3.Visible = false;
button2.Visible = false;
}
This happens because you are referencing an undeclared variables called item that was never declared or instanciated.
When looping through the list items, you need to use:
foreach(ListViewItem item in listView1.Items)
This will iterate the ListView's Items with a variable called item that will hold the current item on each iteration.
Try this code:
private void button3_Click(object sender, EventArgs e)
{
string s = " Search Via Forename";
int result = 0;
int count = 0;
result = string.Compare(textBox1.Text, s);
if ((result == 0) || (String.IsNullOrEmpty(textBox1.Text)))
{
MessageBox.Show("Please input forename...");
return;
}
foreach(ListViewItem item in listView1.Items)
{
if (item.Text.ToLower().StartsWith(textBox1.Text.ToLower()))
{
count++;
statusBar1.Panels[2].Text = "Found: " + count.ToString();
}
else
{
listView1.Items.Remove(item);
}
}
button1.Text = "Clear";
textBox1.Visible = button3.Visible = button2.Visible = false;
}
Related
I am trying to implement a multiple items select in multiple listboxes. Is this possible?
Requirements:
When user selects an item in ListBox1 - items in ListBox2 and ListBox3 should be selected.
When user deselects and item in ListBox1 - Items in ListBox2 and ListBox2 should be deselected.
I am able to achieve this on LB1.
Same behavior 1 and 2 should repeat for ListBox2 and ListBox3.
I am having difficulty here.
I have the code below - but of course it runs into stackoverflow exception. What am I missing?
private void listBox_1_SelectedIndexChanged_(object sender, EventArgs e)
{
int userSelectedIndex = listBox_1.Items.Count;
if (listBox_1.SelectedIndices.Count > 0)
{
for (int count = 0; count < listBox_1.Items.Count; count++)
{
// Determine if the item is selected.
if (listBox_1.GetSelected(count) == true)
{
if (count <= listBox_2.Items.Count)
listBox_2.SetSelected(count, true);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, true);
}
else if (listBox_1.GetSelected(count) == false)
{
// Select all items that are not selected.
if (count <= listBox_2.Items.Count)
listBox_2.SetSelected(count, false);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, false);
}
}
}
}
private void listBox_2_SelectedIndexChanged(object sender, EventArgs e)
{
int userSelectedIndex = listBox_2.Items.Count;
if (listBox_2.SelectedIndices.Count > 0)
{
for (int count = 0; count < listBox_2.Items.Count; count++)
{
// Determine if the item is selected.
if (listBox_2.GetSelected(count) == true)
{
if (count <= listBox_1.Items.Count)
listBox_1.SetSelected(count, true);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, true);
}
else if (listBox_2.GetSelected(count) == false)
{
// Select all items that are not selected.
if (count <= listBox_1.Items.Count)
listBox_1.SetSelected(count, false);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, false);
}
}
}
}
This field is used to avoid Stack Overflow Exceptions.
private bool _isUpdating;
I am also using the SelectedValueChanged event instead of SelectedIndexChanged but it should still work, here is the 3 different checkboxes (this could be improved by refactoring how it handles which listbox to update)
private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
if (this._isUpdating)
{
//// Prevent Stack Overflow by exiting out
return;
}
var selectedIndexes = this.listBox1.SelectedIndices;
this._isUpdating = true;
this.listBox2.SelectedItems.Clear();
this.listBox3.SelectedItems.Clear();
foreach (int index in selectedIndexes)
{
//// Listbox2
var foundItem = this.listBox2.Items[index];
this.listBox2.SelectedItems.Add(foundItem);
//// Listbox3
var foundItem2 = this.listBox3.Items[index];
this.listBox3.SelectedItems.Add(foundItem2);
}
this._isUpdating = false;
}
private void listBox2_SelectedValueChanged(object sender, EventArgs e)
{
if (this._isUpdating)
{
//// Prevent Stack Overflow by exiting out
return;
}
var selectedIndexes = this.listBox2.SelectedIndices;
this._isUpdating = true;
this.listBox1.SelectedItems.Clear();
this.listBox3.SelectedItems.Clear();
foreach (int index in selectedIndexes)
{
//// Listbox1
var foundItem = this.listBox1.Items[index];
this.listBox1.SelectedItems.Add(foundItem);
//// Listbox3
var foundItem2 = this.listBox3.Items[index];
this.listBox3.SelectedItems.Add(foundItem2);
}
this._isUpdating = false;
}
private void listBox3_SelectedValueChanged(object sender, EventArgs e)
{
if (this._isUpdating)
{
//// Prevent Stack Overflow by exiting out
return;
}
var selectedIndexes = this.listBox3.SelectedIndices;
this._isUpdating = true;
this.listBox1.SelectedItems.Clear();
this.listBox2.SelectedItems.Clear();
foreach (int index in selectedIndexes)
{
//// Listbox1
var foundItem = this.listBox1.Items[index];
this.listBox1.SelectedItems.Add(foundItem);
//// Listbox2
var foundItem2 = this.listBox2.Items[index];
this.listBox2.SelectedItems.Add(foundItem2);
}
this._isUpdating = false;
}
Which as stated previously, avoids the Stack Overflow Exception and ensures that selecting / deselecting an item in the Listbox at a given index will also select the item at the other listboxes index.
When search button is pressed, im trying to count how many results have the same 'username' and then sum their 'earned' (earned is a decimal)
private void button5_Click(object sender, EventArgs e)
{
string searchValue = textBox5.Text;
int rowIndex = 1;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
bool valueResult = true;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[1].Value.ToString().Equals(searchValue))
{
rowIndex = row.Index;
dataGridView1.Rows[1].Selected = true;
rowIndex++;
valueResult = false;
var count = this.dataGridView1.Rows.Cast<DataGridViewRow>()
.Count(roww => row.Cells[1].Value.ToString() == searchValue);
this.textBox6.Text = count.ToString();
}
}
if (valueResult != false)
{
MessageBox.Show("Record is not avalable for this Name: " + textBox5.Text, "Not Found");
return;
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
}
1) But for some reason textbox6would display the last number in 'id' column regardless of username searched
2) Also, I cant figure out how to sum the every cell in 'earned' for that specific user searched
[Example of datagridview from MySql]1
Im still a beginner in c#
Since you're already iterating through the rows with the foreach there's no need to recalculate the count of matches each time within the foreach. Instead you can increment a counter and add to an earned total for all of the rows that match.
The reason why textbox6 seemed to have the value of the last row's "id" column (which was actually a count of all of the rows in the grid) is because of the Count condition:
.Count(roww => row.Cells[1].Value.ToString() == searchValue)
which should be:
.Count(roww => roww.Cells[1].Value.ToString() == searchValue)
With it as roww => row and being within the if condition it would return the count of all rows not just the matched rows. But again, having the .Count is unnecessary.
Here's a modified version that iterates through the rows and increments a counter and adds to the earned total for the rows that match the selection criteria:
private void button5_Click(object sender, EventArgs e)
{
string searchValue = textBox5.Text;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
decimal earnedTotal = 0;
int matches = 0;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if(!row.IsNewRow)
{
if((string)row.Cells[1].Value == searchValue)
{
row.Selected = true;
decimal earned;
if (decimal.TryParse((string)row.Cells[2].Value, out earned))
earnedTotal += earned;
matches++;
}
else
{
row.Selected = false;
}
}
}
if(matches == 0)
MessageBox.Show("Record is not avalable for this Name: " + textBox5.Text, "Not Found");
textBox6.Text = matches.ToString();
txtEarnedTotal.Text = earnedTotal.ToString();
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
}
Basically I am writing a simple phone directory. This application has a listview window, a search (text) window and a button to search. Once the user inputs a name in the search window and hit the search button, the program selects and highlight all users corresponding to the search criteria.
No problem….
A unique scenario developed however if the user selects another item in the listview window. The previous items found are/will be still highlighted…
How can I deselect/remove the highlight on the found items whenever/ifever the user select another item immediately after the search?
Below is the code attached to the search button:
Thanks in advance
private void button3_Click(object sender, EventArgs e){
string s = " Search Via Forename";
int result = 0;
int count = 0;
result = string.Compare(textBox1.Text, s);
switch ((result == 0) || (String.IsNullOrEmpty(textBox1.Text))){
case true: MessageBox.Show("Please input forename...");
break;
default: foreach (ListViewItem item in listView1.Items){
if (item.Text.ToLower().StartsWith(textBox1.Text.ToLower())){
item.Selected = true;
item.BackColor = Color.CornflowerBlue;
item.ForeColor = Color.White;
count++;
}else{
item.Selected = false;
item.BackColor = Color.White;
item.ForeColor = Color.Black;
}
}
if (listView1.SelectedItems.Count == 1){
listView1.Focus();
}
textBox1.Text = " Search Via Forename";
textBox1.ForeColor = Color.Silver;
break;
}
}
Before your highlightning code, make a loop through all the items and set their item.Selected to false.
foreach (ListViewItem item in listView1.Items){
if (item.Selected)
item.Selected = false;
}
First removed the selection piece of your code. In fact I would just clear selections all together. The color change that your doing is effectively doing the highlighting for you, so from the information you've provided I don't think its necessary to select them.
private void button3_Click(object sender, EventArgs e){
string s = " Search Via Forename";
int result = 0;
int count = 0;
result = string.Compare(textBox1.Text, s);
switch ((result == 0) || (String.IsNullOrEmpty(textBox1.Text))){
case true: MessageBox.Show("Please input forename...");
break;
default: foreach (ListViewItem item in listView1.Items){
item.Selected = false;
if (item.Text.ToLower().StartsWith(textBox1.Text.ToLower())){
item.BackColor = Color.CornflowerBlue;
item.ForeColor = Color.White;
count++;
}else{
item.BackColor = Color.White;
item.ForeColor = Color.Black;
}
}
if (listView1.SelectedItems.Count == 1){
listView1.Focus();
}
textBox1.Text = " Search Via Forename";
textBox1.ForeColor = Color.Silver;
break;
}
}
Next I would use the selection changed event to detect when a selection was made and clear all the formatting I did.
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (ListViewItem item in listView1.Items)
{
item.BackColor = Color.White;
item.ForeColor = Color.Black;
}
}
You didn't specify win forms or WPF so I assumed win forms and made an example that way. If your using WPF i believe the event you would need to subscribe to is the OnSelectionChanged event for the list view control.
After looking at the code a bit more, I realize your using a switch statement to handle a Boolean operation which is not correct. I've added how I would have changed that check below.
private void button3_Click(object sender, EventArgs e)
{
string s = " Search Via Forename";
int result = 0;
int count = 0;
result = string.Compare(textBox1.Text, s);
// Do the check on the input
if ((result == 0) || (string.IsNullOrEmpty(textBox1.Text)))
{
MessageBox.Show("Please input forename...");
// after notifying the user just return
return;
}
foreach (ListViewItem item in listView1.Items)
{
item.Selected = false;
if (item.Text.ToLower().StartsWith(textBox1.Text.ToLower()))
{
item.BackColor = Color.CornflowerBlue;
item.ForeColor = Color.White;
count++;
}
else
{
item.BackColor = Color.White;
item.ForeColor = Color.Black;
}
}
if (listView1.SelectedItems.Count == 1)
{
listView1.Focus();
}
}
Edited question totally for more understanding.
I have a count function, and I have a label who checks the current count
Here is the label
private void currentCountLabel_TextChanged(object sender, EventArgs e)
{
}
How do I make so once the label reaches as example 50, a function starts. like play sound?
//////////////////////////////
Here is the current one that #btc sources, gave me
private void currentCountLabel_Click(object sender, EventArgs e)
{
if (String.Compare(currentCountLabel.Text, "5") == 0)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"sound.wav");
player.Play();
}
}
But it wont play automaticly, how do I make it to play when it reaches the number?
///////////////////////////////////////////////////////////////////////////////
private void currentCountLabel_TextChanged(object sender, EventArgs e)
{
if (String.Compare(currentCountLabel.Text, "5") == 0)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"meme.wav");
player.Play();
}
}
private void writeToFile()
{
if (Properties.Settings.Default.OBSToggle)
{
if (Properties.Settings.Default.ReverseOrder)
{
File.WriteAllText(#"Count.txt", String.Format("{0} {1}", Count.ToString(), Message));
}
else
{
File.WriteAllText(#"Count.txt", String.Format("{0} {1}", Message, Count.ToString()));
}
}
private void KeyBoardHook_KeyUp(object sender, KeyEventArgs e)
{
if (Properties.Settings.Default.HotKeyEnabled && e.KeyCode == Properties.Settings.Default.HotKeyIn)
{
if (Properties.Settings.Default.SaveCount)
{
Count = Count + 1;
Properties.Settings.Default.Count = Count;
currentCountLabel.Text = Properties.Settings.Default.Count.ToString();
}
else
{
Count = Count + 1;
currentCountLabel.Text = Count.ToString();
}
Message = messageTextBox.Text;
writeToFile();
e.Handled = true;
}
if (Properties.Settings.Default.HotKeyEnabled && e.KeyCode == Properties.Settings.Default.HotKeyDe && Count != 0)
{
if (Properties.Settings.Default.SaveCount)
{
Count = Count - 1;
Properties.Settings.Default.Count = Count;
currentCountLabel.Text = Properties.Settings.Default.Count.ToString();
}
else
{
Count = Count - 1;
currentCountLabel.Text = Count.ToString();
}
Message = messageTextBox.Text;
writeToFile();
e.Handled = true;
}
}
You need a static variable to hold the current count. Initialized to zero. Then increment it each time the function executes.
Then an if statement to evaluate the count and take whatever action.
I can't believe I got drained by this small problem trying to find the solution playing with the intellisense. No luck Just starting c# GUI. Just need a quick answer please.
if (listBox1.SelectedValue== "Chicken")
{
total += 15;
ord += " Chicken";
label4.Text = "chicken selected";
}
what the hell is wrong with this.
I want to execute the statements when the user selected the item "chicken" from listbox1.
public partial class Form1 : Form
{
double total = 0;
int x = 0;
string ord = "";
private void placeToolStripMenuItem_Click(object sender, EventArgs e)
{
checkBox1.Checked = false;
radioButton1.Checked = false;
radioButton2.Checked = false;
radioButton3.Checked = false;
radioButton4.Checked = false;
listBox1.SelectedItems.Clear();
if (checkBox1.Checked)
{
total += 1;
ord += " Water";
}
if (checkBox1.Text == "Extra Meat")
{
total += 1;
ord += ord+" Extra Meat ";
}
if (comboBox1.Text == "Extra Rice")
{
total += 1;
ord += " Extra Rice";
}
if (comboBox1.Text == "Extra Veggies")
{
total += 1;
ord +=" Extra Veggies";
}
if (listBox1.SelectedValue== "Chicken")
{
total+=15;
ord+=" Chicken";
label4.Text = "chicken selected";
}
if (listBox1.Text == "Pizza $8") //< my pathetic attempt to figure it out with intelisense
{
total+=8;
ord+="Pizza ";
label4.Text = "qwe";
}
if (listBox1.SelectedItem == "Spaghetti $12")//< my pathetic attempt to figure it out with intelisense
{
total+=12;
ord+=" Spaghetti";
}
if (listBox1.SelectedItem == "Fries $8")
{
total+=8;
ord+=" Fries";
}
if (listBox1.SelectedItem == "Burger $10")
{
total+=10;
ord+=" Burger";
}
//radiobutton
if (radioButton1.Checked)
{
total+=5;
ord += " Pineapple Juice";
}
if (radioButton2.Checked)
{
total+=6;
ord += " Mango Juice";
}
if (radioButton3.Checked)
{
total+=7;
ord += " Apple Juice";
}
if (radioButton4.Checked)
{
total+=8;
ord += " Orange Juice";
}
MessageBox.Show("Order Done");
}
private void clearToolStripMenuItem_Click(object sender, EventArgs e)
{
ord = "";
total = 0;
}
private void displayToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Order: " + ord+"\nTotal: "+total);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
}
You code cannot work, since you clear all the selections before you are processing the order. Move this code to the very end of the placeToolStripMenuItem_Click method:
// Process the order here ...
MessageBox.Show("Order Done");
checkBox1.Checked = false;
radioButton1.Checked = false;
radioButton2.Checked = false;
radioButton3.Checked = false;
radioButton4.Checked = false;
listBox1.SelectedItems.Clear();
I think that your approach is wrong. You should not have to make all these if-statements. Instead create a Product class
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public override ToString()
{
return String.Format("{0} ${1}", Name, Price);
}
}
Then add products to your listbox:
listbox1.Items.Add(new Product{ Name = "Chicken", Price = 15 });
listbox1.Items.Add(new Product{ Name = "Pizza", Price = 8 });
...
Then you can work with the selected item like this:
var product = listBox1.SelectedItem as Product;
if (product != null) {
total += product.Price;
ord += " " + product.Name;
label4.Text = product.Name + " selected";
}
Also declare total as decimal. Doubles are good for scientific calculations, but can easily yield results like 7.49999999 instead of 7.5. Decimals have been introduced especially for currency calculations. They are not very fast but they don't convert decimal numbers into binary numbers internally, instead the decimal digits are preserved. The problem with binary numbers is that for instance 1/10 cannot be represented accurately just like 1/3 cannot be represented accurately in the decimal system.
You can even add products to your radio buttons
radioButton3.Tag = new Product{ Name = "Apple Juice", Price = 7 };
A more advanced method would be to create your own radio button control with a Product property, but this solution will do it for now.
Then you can loop through all your radio buttons like this
foreach (var radioButton in Controls.OfType<RadioButton>()) {
if (radioButton.Checked) {
var p = (Product)radioButton.Tag;
total += p.Price;
ord += " " + p.Name;
}
}
You need to use SelectedItem.
if (listBox1.SelectedItem == "Chicken")
My program is throwing a Nullreferenceexception on me.
on this line:
if (listBox1.SelectedItem.ToString() == "Chicken $15")
I have to initialize it i guess but i have no idea how to initialize a listBox.
First Method:
if (listBox1.SelectedIndex != -1) //first check if any item is selected
if (listBox1.SelectedItem.ToString() == "Chicken")
Second Method:
if (listBox1.Text == "Chicken")
and just remove the line:
private void placeToolStripMenuItem_Click(object sender, EventArgs e)
{
listBox1.SelectedItems.Clear(); //remove this line
It clears your selected items, that's why you are not getting into any if condition.