Remove highlight from ListView items....deselecting - c#

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();
}
}

Related

Select / Deselect Multiple items in multiple listboxes

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.

Reset background colour of listview using TextChanged event after search

I have a textbox that I can use to search for items and subitems in a listview. Once matches are found the BG colour of the items changes. This works fine, but when I delete the entry from the textbox the items and subitems still remain highlighted until I enter another search.
I am not sure if it is the event that I am using or if it is a problem with my logic. I want the items to be highlighted dynamically as the user types in the search but if they delete the entry I want the BG colour to change back to white.
private void txtSearchMenu_TextChanged(object sender, EventArgs e)
{
string searchVal = txtSearchMenu.Text.ToLower();
if (searchVal != "")
{
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
if (subSearch.Text.ToLower().Contains(searchVal) == true)
{
subSearch.BackColor = Color.MediumAquamarine;
}
else
{
subSearch.BackColor = Color.White;
}
}
item.UseItemStyleForSubItems = false;
}
}
}
when I delete the entry from the textbox the items and subitems still remain highlighted until I enter another search
This is because you do nothing if textbox is blank.
Move check for empty string inside foreach like this:
private void txtSearchMenu_TextChanged(object sender, EventArgs e)
{
string searchVal = txtSearchMenu.Text.ToLower();
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
// move condition here
if (searchVal != "" && subSearch.Text.ToLower().Contains(searchVal) == true)
{
subSearch.BackColor = Color.MediumAquamarine;
}
else
{
subSearch.BackColor = Color.White;
}
}
item.UseItemStyleForSubItems = false;
}
}
As Sintar said:
private void txtSearchMenu_TextChanged(object sender, EventArgs e)
{
string searchVal = txtSearchMenu.Text.ToLower();
if (searchVal != "")
{
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
if (subSearch.Text.ToLower().Contains(searchVal) == true)
{
subSearch.BackColor = Color.MediumAquamarine;
}
else
{
subSearch.BackColor = Color.White;
}
}
item.UseItemStyleForSubItems = false;
}
}
else
{
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
subSearch.BackColor = Color.White;
}
}
}
}

Multi Column Search in a ListView

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;
}

Copy selected items from ListView1 to ListView2

Could someone please point me in the right direction?
I have got one populated ListView and trying to get the selected items into another ListView. The code I've got doesn't produce any errors, neither does it
display any of the selected items.
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);
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++;
item.BackColor = Color.DodgerBlue;
item.ForeColor = Color.White;
statusBar1.Panels[2].Text = "Found: " + count.ToString();
} else {
item.BackColor = Color.White;
item.ForeColor = Color.Black;
}
}
if (count > 1){
listView2.Visible = true;
foreach (ListViewItem item in listView1.Items){
listView2.Items.Add((ListViewItem)item.Clone());
}
}
}
if (count > 1){ should be if (count > 0){ or if (count >= 1){ ... in case there is only one match present. Moreover, don't see you are adding selected items
why dont you do the clone directly in the first foreach?
foreach (ListViewItem item in listView1.Items)
if(item.Text.ToLower().StartsWith(textBox1.Text.ToLower()))
listView2.Items.Add((ListViewItem)item.Clone());
As you are doing it now, you dont select any item in the first list, only changing colors. Try using the SelectedIndices or SelectedItems properties.

How should I change the visibility of a TextBox when a ComboBox value changes?

I'm new to programming and I'm trying to change the value of a textbox depending of a selected value on a combo box, since the values are numerical 1 to 20, and depending on the selection it will be the number of text boxes visible. I'm using the event selected index changed.
Here is my code:
private void cbxPIN_SelectedIndexChanged(object sender, EventArgs e)
{
int pines = Convert.ToInt32(cbxPIN.SelectedItem.ToString());
if (pines == 1)
{
textbox1.visible = true;
}
else if (pines == 2)
{
textbox1.visible = true;
textbox2.visible = true;
}
...
else if (pines == n)
{
textbox1.visible = true;
textbox2.visible = true;
...
textboxn.visible = true;
}
}
since there are like 25 different numeric values on the combo box is there an easier way of doing this? asides from comparing each different value?
Something like a loop.
At the least, I'd rewrite it like this, to reduce duplication:
private void cbxPIN_SelectedIndexChanged(object sender, EventArgs e)
{
int pines = Convert.ToInt32(cbxPIN.SelectedItem.ToString());
if (pines >= 1)
textbox1.Visible = true;
if (pines >= 2)
textbox2.Visible = true;
...
if (pines >= n)
textboxn.Visible = true;
}
Actually, I'd add all the TextBox controls to a collection, possibly in the constructor:
List<TextBox> TextBoxes = new List<TextBox> { textbox1, textbox2, ... textboxn };
Then use LINQ's Take() method to grab the first xx number of controls and iterate through them:
foreach (var tb in TextBoxes.Take(pines))
textBox.Show();
You want to use a loop structure. You should validate that the number of loops to perform is > 0 and < the number of textboxes you have available, but I'll leave error handling to you.
private void cbxPIN_SelectedIndexChanged(object sender, EventArgs e)
{
int pines = Convert.ToInt32(cbxPIN.SelectedItem.ToString());
TextBox textBox;
for (int i = 1; i <= pines; i++)
{
// get the control from the form's controls collection by the control name
textBox = this.Controls["textbox" + pines.ToString()] As TextBox
textBox.Visible = true;
}
}

Categories

Resources