tags:

views:

808

answers:

2

Hello

I have a loop, where I need to use the values from 2 IEnumerable's, and I need to get the current index and value for "labels", so I can print out labelname for each one.

public static string CheckBoxList(this HtmlHelper htmlhelper, IEnumerable<string> values, IEnumerable<string> labels, string name, IDictionary<string, object> HtmlAttributes)
    {
        if (labels == null)
            return "";

        StringBuilder sb = new StringBuilder();


        string[] modelValues = new string[] {};

        ModelState modelState;

        if(htmlhelper.ViewData.ModelState.TryGetValue(name, out modelState)) {
            modelValues = ((string[])modelState.Value.RawValue);
        }


        foreach(string s in values)
        {
            bool isChecked = modelValues.Contains(s);

            sb.Append(CreateCheckBox(name, s, isChecked, HtmlAttributes));

            sb.Append(" <label for=\"" + name + "\"> " + labels + "</label><br />");
        }


        return sb.ToString();
    }

How can I print out current value for "labels" in that loop? Also I need the "index", need to build a unique ID for checkbox so label will work.

Thanks in advance. /M

A: 

If you want to use foreach loop then you need something like that:

int i = 0;
foreach (string s in values) {
    bool isChecked = modelValues.Contains(s);
    sb.Append(CreateCheckBox(name, s, isChecked, HtmlAttributes));
    sb.Append(" <label for=\"" + name + "\"> " + labels.ElementAt(i) + "</label><br />");
    i++;
}

However for loop may be better in this case

// IEnumerable doesn't have Count property so you need to use Count() 
// extension method from System.Linq namespace.
int length = values.Count();
for (int i = 0; i < length; i++) {
    bool isChecked = modelValues.Contains(values.ElementAt(i));
    sb.Append(CreateCheckBox(name, values.ElementAt(i), isChecked, HtmlAttributes));
    sb.Append(" <label for=\"" + name + "\"> " + labels.ElementAt(i) + "</label><br />");
}
RaYell
`IEnumerable` also does not support fetching elements by index. You would need to convert it to a list first (using the `ToList` extension method for instance).
Fredrik Mörk
Using the `Count()` method has a potential performance cost: If the sequence doesn't implement `ICollection<T>` then `Count()` will need to iterate through every element, and you're calling it on every cycle of the `for` loop!
LukeH
@Fredrik Mörk - Linq namespace provides a extension method `ElementAt()` that can replace `[i]`. Anyway it was my mistake indeed that I used brackets.
RaYell
@Luke - This can be easy fixed if you count this number of elements and assign it to a value. I have updated my code.
RaYell
@RaYell: The `ElementAt()` method has similar performance costs to `Count()` unless the sequence implements `IList<T>`. So your edits will (potentially) have worse performance than before, especially the `for` loop which has three separate calls to `ElementAt()` in every iteration of the loop.
LukeH
+1  A: 

I assume that values and labels contain an equal amount of values and that that they are sorted in a way that the first value corresponds to the first label and so on. If that is the case you can probably get an enumerator for each of the IEnumerable<string> objects and iterate over the collections using the enumerators. Also, you can add an int variable that you increment for each iteration and use it for creating unique id's:

public static string CheckBoxList(this HtmlHelper htmlhelper, IEnumerable<string> values, IEnumerable<string> labels, string name, IDictionary<string, object> HtmlAttributes)
{
    if (labels == null)
        return "";

    StringBuilder sb = new StringBuilder();
    string[] modelValues = new string[] { };
    ModelState modelState;

    if (htmlhelper.ViewData.ModelState.TryGetValue(name, out modelState))
    {
        modelValues = ((string[])modelState.Value.RawValue);
    }

    IEnumerator<string> valueEnumerator = values.GetEnumerator();
    IEnumerator<string> labelEnumerator = labels.GetEnumerator();
    int index = 0;
    while (valueEnumerator.MoveNext() && labelEnumerator.MoveNext())
    {
        bool isChecked = modelValues.Contains(valueEnumerator.Current);
        sb.Append(CreateCheckBox(name, valueEnumerator.Current, isChecked, HtmlAttributes));
        sb.Append(string.Format(" <label for=\"{0}\" id=\"label-{1}\">{2}</label></br>", name, index, labelEnumerator.Current);
        index++;
    }

    return sb.ToString();
}
Fredrik Mörk