Prevent double entries in ListView using C#? - c#

How can we access the items added to a ListView?
The thing I have to do is: add an item to the list view. I want to check if the item to add to the listview is already present in the ListView.
I'm using C# and Visual Studio 2005.

The ListView class provides a few different methods to determine if an item exists:
Using Contains on the Items collection
Using one of the FindItemWithText methods
They can be used in the following manner:
// assuming you had a pre-existing item
ListViewItem item = ListView1.FindItemWithText("test");
if (!ListView1.Items.Contains(item))
{
// doesn't exist, add it
}
// or you could find it by the item's text value
ListViewItem item = ListView1.FindItemWithText("test");
if (item != null)
{
// it exists
}
else
{
// doesn't exist
}
// you can also use the overloaded method to match sub items
ListViewItem item = ListView1.FindItemWithText("world", true, 0);

Just add your items and make sure you assign a name. Then
just use the ContainsKey method of the Items collection to
determine if it's there, like this.
for (int i = 0; i < 20; i++)
{
ListViewItem item = new ListViewItem("Item" + i.ToString("00"));
item.Name = "Item"+ i.ToString("00");
listView1.Items.Add(item);
}
MessageBox.Show(listView1.Items.ContainsKey("Item00").ToString()); // True
MessageBox.Show(listView1.Items.ContainsKey("Item20").ToString()); // False

You could do something like this:
ListViewItem itemToAdd;
bool exists = false;
foreach (ListViewItem item in yourListView.Items)
{
if(item == itemToAdd)
exists=true;
}
if(!exists)
yourListView.Items.Add(itemToAdd);

The following will help to locate a ListViewItem within the ListView control once you've added it:
string key = <some generated value that defines the key per item>;
if (!theListViewControl.Items.ContainsKey(key))
{
item = theListViewControl.Items.Add(key, "initial text", -1);
}
// now we get the list item based on the key, since we already
// added it if it does not exist
item = theListViewControl.Items[key];
...
Note
The key used to add the item to the ListView items collection can be any unique value that can identify the ListViewItem within the collection of items. For example, it could be a hashcode value or some property on an object attached to the ListViewItem.

A small correction in Robban's answer
ListViewItem itemToAdd;
bool exists = false;
foreach (ListViewItem item in yourListView.Items)
{
if(item == itemToAdd)
{
exists=true;
break; // Break the loop if the item found.
}
}
if(!exists)
{
yourListView.Items.Add(itemToAdd);
}
else
{
MessageBox.Show("This item already exists");
}

In case of multicolumn ListView, you can use following code to prevent duplicate entry according to any column:
Let us suppose there is a class Judge like this
public class Judge
{
public string judgename;
public bool judgement;
public string sequence;
public bool author;
public int id;
}
And i want to add unique object of this class in a ListView. In this class id is unique field, so I can check unique record in ListView with the help of this field.
Judge judge = new Judge
{
judgename = comboName.Text,
judgement = checkjudgement.Checked,
sequence = txtsequence.Text,
author = checkauthor.Checked,
id = Convert.ToInt32(comboName.SelectedValue)
};
ListViewItem lvi = new ListViewItem(judge.judgename);
lvi.SubItems.Add(judge.judgement ? "Yes" : "No");
lvi.SubItems.Add(string.IsNullOrEmpty(judge.sequence) ? "" : txtsequence.Text);
lvi.SubItems.Add(judge.author ? "Yes" : "No");
lvi.SubItems.Add((judge.id).ToString());
if (listView1.Items.Count != 0)
{
ListViewItem item = listView1.FindItemWithText(comboName.SelectedValue.ToString(), true, 0);
if (item != null)
{
// it exists
}
else
{
// doesn't exist
}
}

Related

c# How to prevent duplicate listview by column text

I need to prevent Duplicate entries from ListView controller by column text. if duplicate found I need to get the ListView Item for further process. I saw every one says
ListViewItem item = ListView3.FindItemWithText("test");
if (!listView1.Items.ContainsKey(txt))
{
// doesn't exist, add it
}
but how can I point which Column text?? I did prevent duplicates by adding ids into a array and after check array value exists. but in that case I can find which entry duplicated.
this is my code.
rd = cmd.ExecuteReader();
// Validation not working - duplicating ListviewItems
while (rd.Read()) {
ListViewItem lvvi = new ListViewItem(rd.GetString(0));
lvvi.SubItems.Add(rd.GetString(1));
lvvi.SubItems.Add(rd.GetString(5));
lvvi.SubItems.Add("1");
lvvi.SubItems.Add(rd.GetString(0));
int listViewItemID;
int[] ids;
ids = new int[100];
if (listView3.Items.Count > 0)
{
int addingItemID;
//ADD ListView ids into array
int i=0;
foreach (ListViewItem li in listView3.Items)
{
listViewItemID = Int32.Parse(li.SubItems[0].Text);
addingItemID = Int32.Parse(rd.GetString(0));
ids[i] = listViewItemID;
i++;
}
//Check item allready exsist
if (ids.Contains(Int32.Parse(rd.GetString(0))))
{
MessageBox.Show("sdsd");
}
else {
listView3.Items.Add(lvvi);
}
}
else {
listView3.Items.Add(lvvi);
}
}
//Calculate Price summery
this.calculatePrice();
Instead of looping to get all id's, you can loop through the items or use linq to find the specific id and keep the result. This can be done in an external function or by replacing the ids portion with the loop or use something like FirstOrDefault:
addingItemID = rd.GetString(0);
ListViewItem existing = listView3.Items.Cast<ListViewItem>().FirstOrDefault(li => li.SubItems[0].Text == addingItemID); //(not sure if the cast is needed)
if (existing != null)
{
//item exists, variable existing refers to the item
MessageBox.Show("sdsd");
}
else
{
listView3.Items.Add(lvvi);
}

How to set selected item of property grid

I need to set the selected item of my property grid. I'm getting an eventargs, which stores a string (this string tells me what property in my propertygrid the user wants to select).
The problem is i cannot find a collection of grid items, i can select one from. And also i dont know how to properly create a new GridItem object and set the SelectedGridItem property.
GridItem gridItem = ???;
detailsPropertyGrid.SelectedGridItem = gridItem;
thank you for your help.
Edit:
Its almost working now tahnk you VERY much.
GridItem gi = this.detailsPropertyGrid.EnumerateAllItems().First((item) =>
item.PropertyDescriptor != null &&
item.PropertyDescriptor.Name == colName);
this.detailsPropertyGrid.SelectedGridItem = gi;
this.detailsPropertyGrid.Select();
The only problem is: Now its selecting the Property Name field. Can I set the focus to the input field of the property?
Here are a couple of PropertyGrid extensions that can enumerate all items in a grid. This is how you can use it to select one item:
// get GridItem for a property named "Test"
GridItem gi = propertyGrid1.EnumerateAllItems().First((item) =>
item.PropertyDescriptor != null &&
item.PropertyDescriptor.Name == "Test");
// select it
propertyGrid1.Focus();
gi.Select();
// enter edit mode
SendKeys.SendWait("{F4}");
...
public static class PropertyGridExtensions
{
public static IEnumerable<GridItem> EnumerateAllItems(this PropertyGrid grid)
{
if (grid == null)
yield break;
// get to root item
GridItem start = grid.SelectedGridItem;
while (start.Parent != null)
{
start = start.Parent;
}
foreach (GridItem item in start.EnumerateAllItems())
{
yield return item;
}
}
public static IEnumerable<GridItem> EnumerateAllItems(this GridItem item)
{
if (item == null)
yield break;
yield return item;
foreach (GridItem child in item.GridItems)
{
foreach (GridItem gc in child.EnumerateAllItems())
{
yield return gc;
}
}
}
}

ListView CheckedItems find item by name

I need to check if an item with a particular name exists in the CheckedItems collection of a ListView.
So far I've tried:
ListViewItem item = new ListViewItem(itemName);
if (listView1.CheckedItems.IndexOf(item) >= 0)
return true;
and
ListViewItem item = new ListViewItem(itemName);
if (listView1.CheckedItems.Contains(item))
return true;
Neither of those worked. Is there a way to do this without looping through CheckedItems and checking them one by one?
You can benefit LINQ for this purpose:
bool itemChecked = listView1.CheckedItems.OfType<ListViewItem>()
.Any(i => i.Text == itemText);
//You can also retrieve the item with itemText using FirstOrDefault()
var checkedItem = listView1.CheckedItems.OfType<ListViewItem>()
.FirstOrDefault(i=>i.Text == itemText);
if(checkedItem != null) { //do you work...}
You can also use the ContainsKey to determine if the item (with name being itemName) is checked:
bool itemChecked = listView1.CheckedItems.ContainsKey(itemName);
Get rid of newing up a ListViewItem and do this instead:
ListViewItem itemYouAreLookingFor = listView1.FindItemWithText("NameToLookFor");
// Did we find a match?
if (itemYouAreLookingFor != null)
{
// Yes, so find out if the item is checked or not?
if(itemYouAreLookingFor.Checked)
{
// Yes, it is found and check so do something with item here
}
}
Using new, you are creating a new item which is not added to the list view (since it is new) and can therefore not be found when using listView1.Contains(item).
When you add an item, use a key/value pair and use contains on the values.

c# Is there a option to filter a listbox

I want to know if there is a possibility to filter a listbox. I mean it in such a way that is i add an item and the name is already in the listbox that you get a messagebox.show that tells you"Item already in the listbox". And that it won't be added twice.
You don't need to iterate throug the items as the Items collection of the ListBox implements the "Contains" method.
if (listBox1.Items.Contains(Item))
{
MessageBox.Show("ListBox already contains Item");
}
"Item" is in this case the Item from the other ListBox
Update. You could write:
if (listBox1.Items.Contains(listBox2.SelectedItem))
{
MessageBox.Show("ListBox already contains Item");
}
else
{
listBox1.Items.Add(listBox2.SelectedItem);
}
Use data binding might be one of the solutions:
List<string> SomeData=...
var filtered=SomeData.Where(...); // <-- Your filtering condition here
listBox1.DataSource = new BindingSource(choices, null);
Inside the event/method which adds list items inside your listbox you can add something like:
// search for list item in the listbox which has the text
ListItem li = theListBox.Items.FindByText("yourListItemName");
if (li != null)
{
// if list item exists display message
MessageBox.Show("ListBox already contains item with the name");
}
else
{
theListBox.Items.Add("yourListItemName");
}
here is a sample code try and implement it in you code
ListBox.ObjectCollection ListItem1= ListBox1.Items;
if(!string.IsNullOrEmpty(SearchBox.Text))
{
foreach (string str in ListItem1)
{
if (str.Contains(SearchBox.Text))
{
msgbox;
}
}
}

ListViewGroups not working correctly

I'm working with a ListView control in Windows Forms using C# and .NET 3.5. I have several items that I'm adding to this ListView control, and I have functionality in place that is supposed to allow the user to select different ways to group the items in the list. However, sometimes items get dumped into the automatically generated "Default" group for no explicable reason.
The code is too large to just put here, but let me explain what I'm doing algorithmically. Suppose we're starting with a ListView that contains items and may or may not already contain groups.
Cycle through every item and set
it's Group property to null.
Empty the ListView's Groups
collection.
Add new Groups to the ListView's
Group collection.
Cycle through every item and set the
Group property using a value
obtained from the ListView's Group
collection via index.
I've stepped through the code and observed everything as it should be. With each item it obtains the appropriate group from the ListView's Group collection and sets the Group property of the item, yet sometimes they end up listed under the "Default" group.
Has anyone else ever observed this or have any theories as to why it might be happening?
It doesn't sound familiar, and I can't reproduce (see below, which follows your approach). Can you post anything related to your "update the groups" code?
using System;
using System.Windows.Forms;
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
ListView lv;
Button btn;
Form form = new Form {
Controls = {
(lv = new ListView { Dock = DockStyle.Fill,
ShowGroups = true}),
(btn = new Button { Dock = DockStyle.Bottom,
Text = "Scramblle" })
}
};
Random rand = new Random();
for (int i = 0; i < 40; i++) {
lv.Items.Add("Item " + i);
}
btn.Click += delegate {
// 1: Cycle through every item and set it's Group
// property to null.
foreach (ListViewItem item in lv.Items) {
item.Group = null;
}
// 2: Empty the ListView's Groups collection.
lv.Groups.Clear();
// 3: Add new Groups to the ListView's Group collection.
int groupCount = rand.Next(lv.Items.Count) + 1;
for (int i = 0; i < groupCount; i++) {
lv.Groups.Add("grp" + i, "Group " + i);
}
// 4: Cycle through every item and set the Group property
// using a value obtained from the ListView's Group collection
// via index.
foreach (ListViewItem item in lv.Items) {
item.Group = lv.Groups[rand.Next(groupCount)];
}
};
Application.Run(form);
}
}
Is this happening on multiple threads?
It sounds like you might be adding some ListViewItems with Groups taken before the the groups were cleared.
Yes... It happened to me too. Try to set the Group before you add the item. I mean when you initialize the ListViewItem you add to the constructor the group it takes part of. That way is going to work.
Yes, I have seen similar behavior. The solution I followed is based on the code here.
public partial class ListViewExtended : ListView
{
private Collection<Dictionary<string, ListViewGroup>> groupTables = new Collection<Dictionary<string,ListViewGroup>>();
public ListViewExtended()
{
InitializeComponent();
}
/// <summary>
/// Create groups for each column of the list view.
/// </summary>
public void CreateGroups()
{
CreateGroups(false);
}
/// <summary>
/// Create groups for each column of the list view.
/// </summary>
public void CreateGroups(bool reset)
{
if (OSFeature.Feature.IsPresent(OSFeature.Themes))
{
if (reset)
{
this.groupTables.Clear();
}
for (int column = 0; column < this.Columns.Count; column++)
{
Dictionary<string, ListViewGroup> groups = new Dictionary<string, ListViewGroup>();
foreach (ListViewItem item in this.Items)
{
string subItemText = item.SubItems[column].Text;
// Use the initial letter instead if it is the first column.
if (column == 0)
{
subItemText = subItemText.Substring(0, 1).ToUpperInvariant();
}
if (!groups.ContainsKey(subItemText))
{
groups.Add(subItemText, new ListViewGroup(subItemText) { Name = subItemText });
}
}
this.groupTables.Add(groups);
}
}
}
/// <summary>
/// Sets the list view to the groups created for the specified column.
/// </summary>
/// <param name="column"></param>
public void SetGroups(int column)
{
if (OSFeature.Feature.IsPresent(OSFeature.Themes))
{
try
{
this.BeginUpdate();
this.Groups.Clear();
if (column == -1)
{
this.ShowGroups = false;
}
else
{
this.ShowGroups = true;
Dictionary<string, ListViewGroup> groups = groupTables[column];
this.Groups.AddRange(groups.Values.OrderBy(g => g.Name).ToArray());
foreach (ListViewItem item in this.Items)
{
string subItemText = item.SubItems[column].Text;
// For the Title column, use only the first letter.
if (column == 0)
{
subItemText = subItemText.Substring(0, 1).ToUpperInvariant();
}
item.Group = groups[subItemText];
}
groups.Values.ForEach<ListViewGroup>(g => g.Header = String.Format(CultureInfo.CurrentUICulture, "{0} ({1})", g.Name, g.Items.Count));
}
}
finally
{
this.EndUpdate();
}
}
}
}
In the code that actually adds the items to the listview, you want to do something like this:
this.itemsListView.Items.AddRange(items.ToArray());
this.itemsListView.CreateGroups(true);
this.itemsListView.SetGroups(0); // Group by the first column by default.

Categories