views:

3422

answers:

6

I am creating concatenated strings based on the data in each row of my ListView control. I need to figure out how to remove the first element in each string which pertains to a single row of the ListView. How might I accomplish this? This is a C# winforms project.

Here is my current code:

        foreach (ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
        {
            string HazPackErrRow = " ";

            foreach (ListViewItem.ListViewSubItem HazPackErrSub in HazPackErrItems.SubItems)
            {
                HazPackErrRow += " " + HazPackErrSub.Text + ",";
            }
            // Remove comma after last element of string.
            HazPackErrRow = HazPackErrRow.Substring(0, HazPackErrRow.Length - 2); 
            MessageBox.Show(HazPackErrRow); // List concatenated subitems
        }
+4  A: 

Just don't add it in the first place?

foreach (ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
    {
        string HazPackErrRow = " ";

        bool first = true;
        foreach (ListViewItem.ListViewSubItem HazPackErrSub in HazPackErrItems.SubItems)
        {
            if (first) 
                first = false;
            else
                HazPackErrRow += " " + HazPackErrSub.Text + ",";
        }
        // Remove comma after last element of string.
        HazPackErrRow = HazPackErrRow.Substring(0, HazPackErrRow.Length - 2); 
        MessageBox.Show(HazPackErrRow); // List concatenated subitems
    }
Inferis
... and then rewrite it to use a StringBuilder too :)
Jon Skeet
True, but that wasn't what he was asking. :)
Inferis
This works. Thanks!
transmogrify
+1 for the StringBuilder !
Wookai
+1  A: 

You can use IList<T>.Skip():

foreach (var HazPackErrSub in HazPackErrItems.SubItems.Skip(1))

Because other people seem to be rewriting your code, why not I? =]

foreach(ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
{
    string HazPackErrRow = String.Join(", ", HazPackErrItems.SubItems.Skip(1).Select(t => t.Text).ToArray());

    MessageBox.Show(HazPackErrRow); // List concatenated subitems
}
strager
You need to call ToArray - String.Join doesn't work with IEnumerable<string>.
Jon Skeet
@Jon Skeet, Ah, thanks for the correction.
strager
A: 

If I understand the problem correctly, you could just use a for loop and start the index at 1 instead of 0.

yodaj007
+3  A: 

This is based on Inferis's answer, but it uses a StringBuilder and avoids the need for the final Substring call:

foreach (ListViewItem errors in HazmatPackageErrorListview.Items)
{
    StringBuilder builder = new StringBuilder();

    bool first = true;
    foreach (ListViewItem.ListViewSubItem error in errors.SubItems)
    {
        if (first)
        {
            first = false;
        }
        else
        {
            if (builder.Length > 0)
            {
                builder.Append(", ");
            }
            builder.Append(error.Text);
        }
    }
    MessageBox.Show(builder.ToString()); // List concatenated subitems
}

Here's an alternative way of tackling the delimiter issue:

foreach (ListViewItem errors in HazmatPackageErrorListview.Items)
{
    StringBuilder builder = new StringBuilder();

    bool first = true;
    string prefix = "";
    foreach (ListViewItem.ListViewSubItem error in errors.SubItems)
    {
        if (first)
        {
            first = false;
        }
        else
        {
            builder.Append(prefix);
            prefix = ", ";
            builder.Append(error.Text);
        }
    }
    MessageBox.Show(builder.ToString()); // List concatenated subitems
}

Of course, there's a simpler way:

foreach (ListViewItem errors in HazmatPackageErrorListview.Items)
{
    string[] bits = errors.SubItems.Skip(1)
                          .Select(item => item.Text)
                          .ToArray();
    string errorLine = string.Join(", ", bits);
    MessageBox.Show(errorLine);
}
Jon Skeet
With this, the string begins with a comma.
strager
I was in the middle of fixing that :)
Jon Skeet
Answer stealer! ;P I don't really like your solution to the issue I commented on earlier... Seems kinda hackish.
strager
I prefer that way to having to take it off the end earlier. There's an alternative way though... I'll edit.
Jon Skeet
@Jon Skeet, I think that method's better (and acceptable by me, though I would break on first instead of a larger if).
strager
+3  A: 

If you can use Linq, use String.Join(), it reads a lot easier:

    foreach (ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
    {
        string HazPackErrRow = string.Join(", ", HazPackErrItems.SubItems.Skip(1).Select(s => s.Text).ToArray())

        MessageBox.Show(HazPackErrRow); // List concatenated subitems
    }
Chris Shaffer
A: 

add the comma at the beginning, then you only have to do one check, rather than a check on every iteration


string HazPackErrRow = "";
foreach (ListViewItem.ListViewSubItem HazPackErrSub in HazPackErrItems.SubItems)        
{
            HazPackErrRow +=  "," + " " + HazPackErrSub.Text;        
}
// Remove comma before first element of string.
if(HazPackErrRow.Length > 0)
 HazPackErrRow = HazPackErrRow.Substring(1);

Edit: Um, ignore me, I misread the question.

Kevin