I have a quick question about listView's and how check if a ListView (which contains null items) has a certain string?
Here is the code which add to sepcific items (under column 5 in the listView). It basically checks if that item appears in Google search or not. If it does, it'll write yes to that specific row, if not it'll leave it blank:
string google2 = http.get("https://www.google.com/search?q=" + textBox1.Text + "");
string[] embedid = getBetweenAll(vid, "type='text/html' href='http://www.youtube.com/watch?v=", "&feature=youtube_gdata'/>");
for (int i = 0; i < embedid.Length; i++)
{
if (google2.Contains(embedid[i]))
{
listView1.Items[i].SubItems.Add("Yes");
}
}
Now what I am trying to do is check if that certain column contains items that say Yes. If it does color them Green if not don't.
Here's the code for that:
if (i.SubItems[5].Text.Contains("Yes"))
{
labelContainsVideo.ForeColor = System.Drawing.Color.Green;
}
My issue is I keep getting an error that says InvalidArgument=Value of '5' is not valid for 'index'.
My hunch is that there are null items in column 5 which might be messing it up but I dont know.
Any idea on how to fix this?
Check the Item to see if the SubItem Collection has the correct Number of values.
i.e.
int threshold = 5;
foreach (ListViewItem item in listView1.Items)
{
if (item.SubItems.Count > threshold)
{
if (item.SubItems[5].Text.Contains("Yes"))
{
// Do your work here
}
}
}
Related
I was trying to call multiple labels with multiple names from a for loop, but the thing is that i dont want to use the "foreach" to loop trough all the controls.
I want to make a direct reference to it, for example :
for(ai = 2; ai < 11 ; ai ++)
{
this.Controls("label" + ai).Text = "SomeRandomText";
}
How can i do this?
I already tried to find this question on the net, but all i find are answers with "foreach" loops.
Thanks!!
Assuming that your labels are named "lable2" through "label10", then you can do it like this:
for(int ai = 2; ai < 11 ; ai++)
{
this.Controls["label" + ai].Text = "SomeRandomText";
}
Here is a solution that is not dependent on the control's name so you are free to change the name of the label at any point in time without breaking your code.
foreach (var control in this.Controls)
{
if (control is Label)
{
int index;
if (control.Tag != null && int.TryParse(control.Tag.ToString(), out index) && index >= 2 && index < 11)
{
((Label)control).Text = "SomeRandomText";
}
}
}
Then, all you need to do is assign a value between 2 and 11 to each control's Tag property that you want updated. You can set this property through code or set the property in the designer.
You are also free to change the values of the Tag property as you see fit. Just make sure the index checks in the code line up with the tag values you choose!
I have a list of "Boxes". there is a value called "position" against each box in the list.
When my list of boxes is built, some are given a position (int) . Position is a value used by my code to determine where each box fits on my page.
So, I have a list with 13 boxes, I have one box with position =13 and one with position 4. the rest are currently null.
There is another field called "order" against a box. What I need to do now is order everything that doesn't have a "position" value by the value in "order". (order is not nullable).
Easy so far. However, what I now need to do is loop each value returned and give them a position value. BUT I need to skip over the position values that are already taken (currently 4 and 13).
This is what I am doing:
var orderedBoxes = (from a in boxes
orderby a.Order
where a.Position == null
select a).ToList();
List<int> takenPositions = (from a in boxes
where a.Position != null
select a.Position).ToList();
foreach (var box in orderedBoxes)
{
if (takenPositions.Contains(i))
{
// i++
// box.Position =i;
}
//box.Position =i;
}
i thought this might be ok, but upon reflection, what if takenPositions Does contains i and the value after i++ is also in takenPositions?
I feel I need some form of loop here to test the result of i++ after each increment.
Can anyone offer any help please!!
It might be solved if you'd change
if (takenPositions.Contains(i))
in
while (takenPositions.Contains(i))
It automatically increments until it finds a free position.
Sometimes I use the good old for loop:
int j = 0;
for (int i = 1; i <= boxes.Count; i++)
{
if (takenPositions.Contains(i)) continue;
orderedBoxes[j++].Position = i;
}
I'm trying to solve a simple algorithm a specific way where it takes the current row and adds it to the top most row. I know there are plenty of ways to solve this but currently I have a text file that gets read line by line. Each line is converted to an sbyte (there's a certain reason why I am using sbyte but it's irrelevant to my post and I won't mention it here) and added to a list. From there, the line is reversed and added to another list. Here's the code I have for that first part:
List<List<sbyte>> largeNumbers = new List<List<sbyte>>();
List<string> total = new List<string>();
string bigIntFile = #"C:\Users\Justin\Documents\BigNumbers.txt";
string result;
StreamReader streamReader = new StreamReader(bigIntFile);
while ((result = streamReader.ReadLine()) != null)
{
List<sbyte> largeNumber = new List<sbyte>();
for (int i = 0; i < result.Length; i++)
{
sbyte singleConvertedDigit = Convert.ToSByte(result.Substring(i, 1));
largeNumber.Add(singleConvertedDigit);
}
largeNumber.Reverse();
largeNumbers.Add(largeNumber);
}
From there, I want to use an empty list that stores strings which I will be using later for adding my numbers. However, I want to be able to add numbers to this new list named "total". The numbers I'll be adding to it are not all the same length and because so, I need to check if an index exists at a certain location, if it does I'll be adding the value I'm looking at to the number that resides in that index, if not, I need to create that index and set it's value to 0. In trying to do so, I keep getting an IndexOutOfRange exception (obviously because that index doesn't exist). :
foreach (var largeNumber in largeNumbers)
{
int totalIndex = 0;
foreach (var digit in largeNumber)
{
if (total.Count == 0)
{
total[totalIndex] = digit.ToString(); //Index out of Range exception occurs here
}
else
{
total[totalIndex] = (Convert.ToSByte(total[totalIndex]) + digit).ToString();
}
totalIndex ++;
}
}
I'm just at a loss. Any Ideas on how to check if that index exists; if it does not create it and set it's underlying value equal to 0? This is just a fun exercise for me but I am hitting a brick wall with this lovely index portion. I've tried to use SingleOrDefault as well as ElementAtOrDefault but they don't seem to be working so hot for me. Thanks in advance!
Depending on if your result is have small number of missing elements (i.e. have more than 50% elements missing) consider simply adding 0 to the list till you reach neccessary index. You may use list of nullable items (i.e. List<int?>) instead of regular values (List<int>) if you care if item is missing or not.
Something like (non-compiled...) sample:
// List<long> list; int index; long value
if (index >= list.Count)
{
list.AddRange(Enumerable.Repeat(0, index-list.Count+1);
}
list[index] = value;
If you have significant number of missing elements use Dictionary (or SortedDictionary) with (index, value) pairs.
Dictionary<int, long> items;
if (items.ContainsKey(index))
{
items[key] = value;
}
else
{
items.Add(index, value);
}
How can I get the visible items from a winforms listview? There doesn't seem to be a straightforward way, and I am reluctant to query items by control.clientrectangle or other hacks similar to the following:
https://stackoverflow.com/questions/372011/how-do-i-get-the-start-index-and-number-of-visible-items-in-a-listview)
When I say visible I mean the items are visible on the screen.
You can iterate from ListView.TopItem and check ListViewItem.Bounds property of each item whether it is located within the client area.
Better ListView Express is a freeware component that have also BottomItem property, so you can easily go through the visible items with a for loop (if both TopItem and BottomItem are not null):
for (int i = betterListView.TopItem.Index; i < betterListView.BottomItem.Index; i++)
{
// your code here
}
You can try this - it have the same interface as ListView and have many improvements over .NET ListView.
Sample code using GetItemAt
Looking at #Hans Passants comment I made a stab at actually creating code.
This code gets the top/bottom items. To get a Collection of visible items should be easy by out from Items where index is between index of top/bottom.
For me this worked much better than using Bounds, the bounds of the ListView appeared to have been higher then the visible part.
/// <summary>
/// Finds top/bottom visible items
/// </summary>
public static (ListViewItem, ListViewItem) GetTopBottomVisible(ListView listView)
{
ListViewItem topItem = listView.TopItem;
int lstTop = listView.Top;
int lstHeight = lstTop + listView.Height;
int lstBottom = lstHeight;
int step = lstHeight/2;
int x = listView.Left + listView.Width/2;
int y = lstTop + step;
ListViewItem bottomCandidate=null;
// iterate by interval halving
while ( step > 0 )
{
step /= 2; // halv interval
ListViewItem itm = listView.GetItemAt(x, y);
if ( itm == null )
{
// below last, move up
y -= step;
}
else if ( itm == bottomCandidate )
{
// Moving still in same item, stop here
break;
}
else
{
// above last, move down, storing candidate
bottomCandidate = itm;
y += step;
}
}
return (topItem, bottomCandidate);
}
If you are looking for a function that gives you only the visible item list, there is no such thing. You can go foreach item and check if its visible or not.
(If i understood your question right? Please give much clear explanation)
Is there a way to remove an item from a listbox based on a string?
I have been playing around for a few minutes and here is what i have so far but its not working
foreach(string file in LB_upload.Items)
{
ftp.Upload(file);
int x = LB_upload.Items.IndexOf(file);
LB_upload.Items.RemoveAt(x);
}
I could just loop through each item but I wanted to do something a little more elegant
while(LB_upload.Items.Count > 0)
{
ftp.Upload(LB_upload.Items[0].ToString());
LB_upload.Items.RemoveAt(0);
}
Based on your example, I'd do something like;
foreach(string file in LB_upload.Items)
{
ftp.Upload(file);
}
LB_upload.Items.Clear();
The problem you are probably encountering is that you are altering the list while iterating over this. This is a big no-no, and has been covered ad-nauseum on this site.
Based on the title of your question it sounds like you don't want to remove every item, just some of them. If that's the case:
for (int i = LB_upload.Items.Count - 1; i >= 0; i--)
{
if (somecondition)
{
ftp.Upload(LB_upload.Items[i]);
LB_upload.Items.RemoveAt(i);
}
}