1

私は MVC を初めて使用しますが、すべてのドキュメント、すべての質問、見つけることができるすべてのブログ投稿を読んでいます。

「作成」アクションとビューを作成しようとしています。私のデータ入力は比較的単純で一般的です。ドロップダウン リストとテキスト ボックスがあります。私の場合は、ユーザーの連絡先チャネルを作成しています。ドロップダウン ボックスで電子メールとテキスト メッセージのどちらかを選択し、テキスト ボックスに適切な形式の電子メール アドレスまたは携帯電話番号のいずれかの関連する連絡先情報を入力します。

これが私のビューページの(少し簡略化された形式の)です:

 <tr>
     <td><%= Html.DropDownList("ChannelDescription", Model.ChannelDescription, "Select a Channel", new { id = "ChannelDDL", onchange="ChannelDDLChanged()" })%>
         <br />
         <%= Html.ValidationMessage("ChannelDescription", "Please Select a Channel") %>
      </td>
      <td>
           <%= Html.TextBox("SubscriberNotificationAddr") %> <br />
           <%= Html.ValidationMessage("SubscriberNotificationAddr", "Please enter a contact address or number") %>
       </td>
  </tr>

ViewDataDictionary を使用するのではなく、厳密に型指定された ViewData モデルを使用しています。ChannelDescription 要素は SelectList であり、選択肢のリストで初期化され、選択はありません。

フォームの初期表示、フォームへのデータ入力、およびコントローラーによるフォームからのデータの抽出はうまくいきます。

私の問題は、データに不正な形式の電子メール アドレスや携帯電話番号などのエラーが含まれていて、ビューに戻る必要がある場合、ドロップダウン リストの選択を再表示することに成功していないことです。ChannelDescription 要素は、ユーザーの選択を選択項目としてコントローラーで再作成されます。ビューのその行にブレークポイントを設定し、項目リストの選択された要素の Selected プロパティが true に設定されていることを確認しましたが、デフォルトの「チャネルの選択」が表示されたままです。

これは非常に一般的な状況のようで、それほど難しいことではありません。私は何を間違っていますか?

参考までに、これは MVC 1.0 (リリース)、Windows 7、および VS 2008 で、Firefox 3.5.2 で実行されています。

4

3 に答える 3

1

上記の回答を見た後、確認したいと思いました。なぜなら、私が見たすべての例は、厳密に型指定された ViewDataModel ではなく、実際に ViewDataDictionary を使用していたからです。

そこで、いくつかの実験を行いました。プレーンな ViewDataDictionary を使用する非常に単純なビューを作成し、名前付きキーで値を渡しました。選択したアイテムを問題なく保持しました。次に、そのビュー (およびコントローラー) を別のビューにカット アンド ペーストし、厳密に型指定されたビューデータ モデルに切り替えるために必要なものだけを変更しました。見よ、それは選択されたアイテムも永続化しました。

では、単純なテストとアプリケーションの違いは他にあるでしょうか? 私のテストでは、単純に "Html.DropDownList("name", "optionLabel")" を使用しました。ただし、私のアプリケーションでは、HTML 属性を追加する必要があり、HtmlAttributes を含む利用可能な唯一のオーバーロードには、選択リストも含まれています。

選択リスト パラメーターを使用した DropDownList オーバーロードが壊れていることがわかりました。ダウンロードした MVC ソース コードを見ると、DropDownList が名前のみ、または名前と optionLabel を指定して呼び出されると、最終的に ViewData からターゲット選択リストを取得し、次の呼び出しでプライベート SelectInternal メソッドを呼び出します。

    return SelectInternal(htmlHelper, optionLabel, name, selectList, true /* usedViewData */, false /* allowMultiple */, (IDictionary<string, object>)null /* htmlAttributes */);

ただし、selectList パラメーターを指定して呼び出すと、次のようになります。

   return SelectInternal(htmlHelper, optionLabel, name, selectList, false /* usedViewData */, false /* allowMultiple */, htmlAttributes);

違いは、最初のもの (正しく動作する) では "usedViewData" パラメータが true であるのに対し、2 番目のものでは false であることです。これは実際には問題ありませんが、SelectInternal ルーチンの内部欠陥を明らかにしています。

usedViewData が false の場合、ViewData モデルからオブジェクト変数「defaultValue」を取得します。ただし、実際には ViewData から返されるものが SelectList である場合、defaultValue は文字列または文字列の配列であるかのように使用されます。( IEnumerable<SelectListItem>)。

usedViewData が true の場合、defaultValue は null または文字列になります。

次に、defaultValue が null でない場合、これを含むコード ブロックに入ります。

        foreach (SelectListItem item in selectList) {
            item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
            newSelectList.Add(item);

selectList は渡された元の selectList であるため、項目は SelectListItem (文字列 Text、文字列 Value、および bool Selected) です。ただし、selectedValues は defaultValue から派生したものであり、文字列のリストではなく、SelectLists のリストになります。そのため、各項目について、selectedValues リストに item.Value が「含まれている」かどうかに基づいて Selected フラグを設定しています。まあ、SelectLists のリストが文字列を「含む」ことはないので、item.Selected は決して設定されません。(訂正: 実際には、デバッガーでさらにトレースした後、selectedValues は "ToString()" 呼び出しによって defaultValue から派生していることがわかりました。つまり、実際には文字列のリストですが、必要な値が含まれているのではなく、 「System.Web.Mvc.SelectList」を含む - 「ToString()」を適用した結果 SelectList のような複雑なオブジェクトに。結果は同じです - そのリストで探している値を見つけることはできません.)

次に、新しく構築された「newSelectList」を元の「selectList」に置き換え、そこから HTML の構築に進みます。

cagdas (あなたの名前をぶち壊して申し訳ありませんが、US キーボードでこれらの文字を作成する方法がわかりません) が上で述べたように、DropDownList HtmlHelper の代わりに使用する独自のメソッドを作成する必要があると思います。今回のリリース 1 とリリース 2 はベータ 2 であるため、自分で修正しない限りバグ修正は期待できないのではないでしょうか?

ところで、ここまでフォローしてくださったのであれば、このコードは src\SystemWebMvc\Mvc\Html\SelectExtensions.cs の 116 ~ 136 行あたりにあります。

于 2009-10-23T21:33:10.213 に答える
1

MVC チームの Brad Wilson と話し合ったところ、DropDownList ヘルパー メソッドの使用方法を誤解していると説明されました (私が読んだ限りでは、かなり一般的であると思われる誤解です)。

基本的に、ViewModel の名前付きパラメーターで SelectList を指定し、適切な項目が選択されたドロップダウン リストを作成するか、SelectList を別のパラメーターとして指定し、ViewModel の名前付きパラメーターを単に選択したアイテムの値の文字列。SelectList パラメーターを指定すると、名前付きの値が文字列または文字列のリストであり、SelectList ではないことが期待されます。

したがって、ViewModel は、ビュー (ドロップダウン リスト) 内の 1 つの概念的な項目に対して 2 つの要素を持つことになります。したがって、次のモデルがある場合があります。

string SelectedValue {get; set;}
SelectList DropDownElements { get; set;}

次に、DropDownElements に選択肢を事前設定できますが、モデル ビュー バインディングでは、SelectedValue 要素を処理するだけで済みます。私がそのようにすると、私にとってはかなりうまくいくようです。

于 2009-11-04T20:36:55.280 に答える
0

はい、私も DropDownList に指定した選択したアイテムを尊重させるのに非常に多くの問題がありました。

この質問の私の回答を確認してください。私が覚えている限り、それが私がそれを機能させる唯一の方法でした。ViewData を介してリストを渡す。

参考までに、その HtmlHelper メソッドの使用をやめました。私は今、ループでタグ<select>とタグを自分で出力し、自分でチェックしてタグのプロパティを設定しています。<option>selectedoption

于 2009-10-23T17:59:33.343 に答える