2009-08-10 26 views
0

2つのIEnumerableの値を使用する必要があるループがあります。現在のインデックスと値を "labels"にする必要があります。それぞれ。IEnumerableループの現在のインデックス+値の取得

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(); 
    } 

このループの「ラベル」の現在の値を印刷するにはどうすればよいですか?また、私は "インデックス"、ラベルが動作するようにチェックボックスの一意のIDを構築する必要があります。

ありがとうございます。 /M

答えて

2

私は値とラベルと仮定同じ量の値を含み、最初の値が最初のラベルに対応するようにソートされます。その場合は、IEnumerable<string>オブジェクトごとに列挙子を取得し、列挙子を使用してコレクションを反復処理することができます。また、各反復でインクリメントするint変数を追加し、ユニークなIDを作成するためにそれを使用することもできます:

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(); 
} 
0

あなたは、foreachループを使用したい場合、あなたはそのようなことが必要です。しかしforループが、この場合には良いかもしれ

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++; 
} 

// 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 />"); 
} 
+0

'IEnumerable'はインデックスで要素を取り出すこともサポートしていません。最初にリストに変換する必要があります(例えば、 'ToList'拡張メソッドを使用して)。 –

+0

'Count()'メソッドを使うとパフォーマンスが低下する可能性があります:シーケンスに 'ICollection 'が実装されていない場合、 'Count()'はすべての要素を反復処理する必要があります。 'for'ループ! – LukeH

+0

@FredrikMörk - Linq名前空間は '[i]'を置き換えることができる拡張メソッド 'ElementAt()'を提供します。とにかく括弧を使ったのは間違いでした。 – RaYell