May I know how can I identify the item in a SharePoint list view via an ID?
Due to some changes, I am unable to use foreach as in the situation where a row remains in the list, it resulted in repetitive processing of the same item.
Below is my code snippet and sample scenario.
foreach (SPListItem item in unprocessedView)
//list only contains items with "Processed" = false
{
//if "Type" = "report",
//set "Processed" = true.
//item does not appear in list anymore.
//if "Type" = "result"
//do nothing.
//item remains in list.
}
Let's say there are 2 items in unprocessedView.
1. result type.
2. report type.
With the conditions above, item 1. will not be processed, and remains in the list.
On the loop, 1. is processed again instead of moving on to item 2.
May I know how can I workaround this?
Thank you.
Modify the code snippet as below to make it works.
foreach (SPListItem item in unprocessedView)
{
if (item["Type"]!=null&&item["Type"].ToString() == "report")
{
item["Processed"] = true;
item.Update();
}
}
Related
I have got a list box called lstPTLNameDHOD which has multiple PTL names which gets selected using Ctrl. I want to display the selected names in a label or some way that the person submitted the form can see who exactly they are submitting it for.
My problem is I can only get one name to display on the label.
// Items collection
foreach (ListItem item in lstPTLNameDHOD.Items)
{
if (item.Selected)
{
lbl1stPTL.Text = item.Value.ToString();
}
}
This is being called on post back on the reason dropdown being changed.
You are only getting one name to display because your current code would always display name of the last item that is selected.
I don't have a visual studio handy but you could try this:
StringBuilder sbText = new StringBuilder();
// Items collection
foreach (ListItem item in lstPTLNameDHOD.Items)
{
if (item.Selected)
{
lbl1stPTL.Text = sbText.Append(item.Value.ToString()).ToString();
}
}
You can probably refine this by adding a space or a comma between two item names but I hope you get the idea and it helps!
Again, sorry for not having VS handy!
In my program I have 2 listviews and 1 button.
When I press the button, every listview item in the first listview will be selected in the second listview. The items in the first listview always exist in the second listview, but not the other way around.
I'm having trouble with selecting the items in the second listview. I'm trying to get the index with IndexOf.
foreach (ListViewItem item in firstListView.Items)
{
int index = secondListView.Items.IndexOf(item);
secondListView.Items[index].Selected = true;
}
I always get an error that index is -1 when I click the button. And I don't understand what I'm doing wrong.
SOLUTION
So what I tried to do here finding an index of an item which belongs to a different listview, and it doesn't work like that. Even though the text in both listviews are the same, the listview items are not identically the same because they are reference types.
I was not able to use the Text property because items could have the same text. So the solution I had was putting an unique integer in the Tag property for each ListViewItem. Since integers are value types, I can use that integer to check whether the ListViewItem in the first listview is in the second.
// Loop through each item in the first listview
foreach (ListViewItem item1 in firstListView.Items)
{
// For each item in the first listview, loop through the second listview to find if it's there
foreach (ListViewItem item2 in secondListView.Items)
{
// Check if item1 is identical to item2 by looking at its tag
if (int.Parse(item1.Tag) == int.Parse(item2.Tag))
{
// The item has been found and will be selected!
item2.Selected = true;
}
}
}
You can use such linq query to select items of the second list which exist in the first list too:
var items = from i1 in listView1.Items.Cast<ListViewItem>()
from i2 in listView2.Items.Cast<ListViewItem>()
where i1.SubItems.Cast<ListViewItem.ListViewSubItem>()
.Where((s, i) => s.Text != i2.SubItems[i].Text).Count() == 0
select i2;
items.ToList().ForEach(x => { x.Selected = true; });
Note:
When to try to use secondListView.Items.IndexOf method to find an item which belongs to the firstListView you can not expect it to find the item. The item you are trying to find its index, doesn't exists in second listview's item collection. You should find items using Text property of the item and sub items.
Well the same item obviously cant exist in two different lists.
If the text is the same, then try looking by it:
foreach (ListViewItem listViewItem in l1.Items)
{
var item = l2.Items.Cast<ListViewItem>().Where(lvi => lvi.Text == listViewItem.Text);
item.Selected=true;
}
Or:
foreach (ListViewItem listViewItem in l2.Items.Cast<ListViewItem>()
.Where(lvi => l1.Items.Cast<ListViewItem>().Any(lvi2 => lvi.Text == lvi2.Text))
{
listVieItem.Selected=true;
}
IndexOf returns -1 if it cannot find the object passed to it in the list. My guess is that you have an issue with your equality comparison. Do the objects in the lists implement IComparable? Otherwise they may not be finding the items correctly and are reverting to a bad equality comparison. ListViewItem may not be comparing how you expect.
you can try finding the item by text and then get the index like this
foreach (ListViewItem item in firstListView.Items)
{
var itm = secondListView.FindItemWithText(item.Text);
int index = secondListView.Items.IndexOf(itm);
secondListView.Items[index].Selected = true;
secondListView.Select();
}
what FindItemWithText will do is get the item in secondListView which will be of same name as in firstListView and IndexOf will get the index of item in secondListView
Edit
This solution is good when you have two lists whose items are same and does not include any repetition in name else if you have two items in secondListView with same name FindItemWithText will get the first item only.
What i've tried:
try 1:
for(int x = listBox1.SelectedIndices.Count - 1; x>= 0; x--)
{
int idx = listBox1.SelectedIndices[x];
listBox2.Items.Add(listBox1.Items[idx]);
listBox1.Items.RemoveAt(idx);
}
try 2:
ArrayList tmpArr = new ArrayList();
foreach (object obj in listBox1.SelectedItems)
{
listBox2.Items.Add(obj);
tmpArr.Add(obj);
}
foreach (object obj in tmpArr.ToArray())
{
listBox1.Items.Remove(obj);
}
Also tried everything in the following post: How to remove multiple selected items in ListBox?
Still nothing worked. What am I doing wrong?
var selectedItems = new object[listBox1.SelectedItems.Count];
listBox1.SelectedItems.CopyTo(selectedItems, 0);
foreach (var item in selectedItems)
{
listBox1.Items.Remove(item);
}
or with a bit of LINQ to simplify the code:
foreach (var item in listBox1.SelectedItems.Cast<object>().ToArray())
{
listBox1.Items.Remove(item);
}
The reasoning here is that you get all the selected items and put them into another list first. The original issue is that any change you make to the ListBox will change things like SelectedItems and SelectedIndices. Once you've created an independent array and put the selected items into it, nothing you do to the ListBox will affect that array so you can just enumerate it normally.
listbox1.BeginUpdate();
for (int x = listBox1.SelectedIndices.Count - 1; x >= 0; x--)
{
int idx = listBox1.SelectedIndices[x];
listBox1.Items.RemoveAt(idx);
}
listbox1.EndUpdate();
If you cannot guarantee that every object in the list is unique, then this is the correct way to do it, to ensure that the correct selected items get removed.
If you have multiples of the same object in your listbox, you have to refer to them by "index", otherwise if you remove them by "item" it will remove the first instance of any matching items it finds.
I am in the process of writing a bus route planner which called for replication of the waypoint markers in the list. These were stored as strings, so for example I might have had "w1", "w2", "w3"... "w2" (think of a bus going down a high street, looping round a couple of blocks and then returning down the other side to understand why I have that... I only need waypoint markers in the centre of the road, not in each lane)
If I had selected the last "w2" marker as part of a range and used the selectedItem() method to to remove them, it would have removed the first "w2", not the second one. By using the SelectedIndex() method, it removes based on position, not value, so duplicate values are left safely intact.
I just wanted to add that as I have just been dealing with this very same problem, so saw first hand the problem removing by SelectedItem() caused.
I'm working on an application of which requires me to have one list-box to hold data.
I'm having a little issue when deleting an object from a list-box. The issue comes into play when I fill the list-box with items from TWO separate lists.
Normally to delete the object I would get it's index and then remove it from the list in a separate class then reload the list-box to reflect the changes but in certain instances I need to fill the list-box with objects from two different lists and determining the origin of the object to delete from one of the two lists, well I'm not entirely sure how to do this.
this code is populating the list-box control.
//clear all items in the listbox
ViewListBox.Items.Clear();
//create the lists
List listOfPickups = visits.listPickups();
List listOfdeliveries = visits.listDeliveries();
//populate
ViewListBox.Items.AddRange(listOfPickups.ToArray());
ViewListBox.Items.AddRange(listOfdeliveries.ToArray());
this is how i delete when i am only loading the listbox from one list.
if (ViewListBox.SelectedIndex < 0)
{
EditSelectBtn.Enabled = false;
DeleteSelectBtn.Enabled = false;
}
else
{
if (MessageBox.Show("are you sure you want to delete the selected item?", "Are You Sure?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
visits.removePickup(this.ViewListBox.SelectedIndex);
//refresh listbox.
updateList("pickups");
}
else
{
//clicked no so do nothing!
ViewListBox.ClearSelected();
}
}
Any help would be greatly appretiated.
You can define type of selected item, and remove it from list with simple condition. Also removing by index will not help you here. Pass whole object instead
object item = ViewListBox.SelectedItem;
if (item is Pickup)
visits.removePickup(item);
else
visits.removeDelivery(item);
If items have same type, then use some other way to get item type (e.g. value of some property).
UPDATE One catch - you can determine item origin by comparing SelectedIndex with listOfPickups length, because you are adding pickup items first. If index is greater, than pickups count, then you are removing delivery. Subtract pickups count from selected index to get index of delivery item you need to remove.
List<Pickup> listOfPickups = visits.listPickups();
List<Delivery> listOfdeliveries = visits.listDeliveries();
ViewListBox.Items.AddRange(listOfPickups.ToArray());
ViewListBox.Items.AddRange(listOfdeliveries.ToArray());
//...
if (ViewListBox.SelectedIndex < listOfPickups.Count)
{
// this is a Pickup
visits.removePickup(ViewListBox.SelectedIndex);
}
else
{
// this is a delivery
int deliveryIndex = ViewListBox.SelectedIndex - listOfPickups.Count;
visits.removeDelivery(deliveryIndex);
}
List itemsToMove = new List();
foreach (ListViewItem item in lvScanRepository.SelectedItems)
{
itemsToMove.Add(item);
}
foreach (ListViewItem item in itemsToMove)
{
if (!lvBatch.Items.Contains(item))
{
lvScanRepository.Items.Remove(item);
lvBatch.Items.Add(item);
}
}
A ListViewItem can't belong to more than one ListView at the same time, so this condition:
if (!lvBatch.Items.Contains(item))
... will always be true.
What criteria do you want to use to determine whether the item in one ListView is "similar" to an item in another? Depending on that, you have a couple of options:
ListViewItem has a property called Name which can be used to uniquely identify items in a ListView. You can then call Items.ContainsKey(String) to see if an item exists with that name.
Alternatively you can search in lvBatch to find an item with the same Text as the one you're trying to add:
if (!lvBatch.Items.Cast<ListViewItem>().Any(i => i.Text == item.Text))
(You need to cast because ListViewItemCollection doesn't actually implement IEnumerable<ListViewItem>.)