17

Razor ビュー内のドロップダウン リストに項目のリストがあります。データベースでは、各項目に 3 つの値が関連付けられています。データベース ID、短い名前 (表示用)、長い名前 (サービスに渡すため) です。ドロップダウンには短い名前を表示する必要があるため、データベース ID を値として、短い名前をテキストとしてドロップダウンに入力しています。

ただし、ユーザーがアイテムを選択するとき、長い名前をクエリ パラメータとして jQuery を使用して検索サービスに渡す必要があります。たとえば、Cortina を選択した場合、「Ford Cortina 1979 Blue」をサービスに渡す必要があります。私の最初の考えは、長い名前をデータダッシュ属性として保存することですが、もっと良い方法があるのではないかと思っています. そう

  • ドロップダウン リストに 3 つの値すべてを保存するにはどうすればよいですか?
  • データ ダッシュ属性を使用する場合、すべての LONG_NAME 値を Html.DropDownListFor に組み込む方法、またはドロップダウン リストに追加する方法を教えてください。

DB:

CARID SHORT_NAME LONG_NAME
1     Viper     Dodge Viper 1982
2     Boxster   Porsche Boxster 2009 Black
3     Cortina   Ford Cortina 1979 Blue

ドロップダウンを作成するコントローラ ヘルパー:

public static IEnumerable<SelectListItem> GetSelectList(this IEFRepository repository, string typeName)
{
    var vehicle = repository.TypeTypes.FirstOrDefault(t => t.Name.ToUpper() == typeName);
    if (vehicle != null)
    {
        var carList = vehicle.SubTypes.ToList().OrderBy(s => s.Name);
        var selectList = new SelectList(subTypeList, "SubTypeID", "Name");

        return selectList;
    }
}

ドロップダウンを作成するために使用するコードは次のとおりです。

<div class="editor-field">
    @Html.DropDownListFor(model => model.CarID,
        new SelectList(ViewBag.Cars, "Value", "Text", "1"))
    @Html.ValidationMessageFor(model => model.CarShortName)
</div>

出力は次のとおりです。

<select id="CarID" name="CarID" data-val="true" data-val-number="The field CarID must be a number." data-val-required="The CarID field is required.">
    <option value="2">Boxster</option>
    <option value="3">Cortina</option>
    <option selected="selected" value="1">Viper</option>
</select>
4

5 に答える 5

29

誰もがこれらの問題を解決するための「古典的な」方法を忘れていforeachます。ループを使用して、実際に入力htmlを記述します。唯一の欠点は、自動属性のもの(検証など)を追加する必要があることです。これは、目的によっては大したことではない場合があります。

何かのようなもの:

<select> // add other attributes as expected
@foreach(var type in Model.MyFancyTypes) {
<option value="@type.SubTypeID" data-description="@type.Description" 
    @if(ViewBag.TypeSelected == type.SubTypeID) {
        selected="selected"
    }>@type.Name</option>
}
</select>
于 2013-01-28T19:33:07.773 に答える
22

jQuery 関数で実行するアクションを決定するために、各リスト項目に 3 番目の値を渡す必要がある、同様の状況がありました。これが私の解決策です(ドロップダウンの各項目に任意の数の属性を追加できます):

まず、次のように SelectListItemWithAttributes クラスを作成しました。

    public class SelectListItemWithAttributes : SelectListItem {
        public IDictionary<string, string> HtmlAttributes { get; set; }
    }

これにより、追加の属性が付加された選択リストのアイテムを作成できます。

次に、DropDownListWithItemAttributesFor という HTML ヘルパー メソッドを次のように作成しました。

public static MvcHtmlString DropDownListWithItemAttributesFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, IEnumerable<SelectListItemWithAttributes> selectList) {
    string name = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression)); 

    var selectDoc = XDocument.Parse(htmlHelper.DropDownList(name, (IEnumerable<SelectListItem>)selectList).ToString());

    var options = from XElement el in selectDoc.Element("select").Descendants()
                          select el;

    for (int i = 0; i < options.Count(); i++){
        var option = options.ElementAt(i);
        var attributes = selectList.ElementAt(i);

        foreach (var attribute in attributes.HtmlAttributes){
                    option.SetAttributeValue(attribute.Key, attribute.Value);
        }
    }

    selectDoc.Root.ReplaceNodes(options.ToArray());
    return MvcHtmlString.Create(selectDoc.ToString());
}

これにより、新しい SelectListWithAttributes クラスを属性として使用してドロップダウンを作成できます。基本的に、ドロップダウン リストの HTML を作成し、それを XML ドキュメントに解析してから、HtmlAttributes 配列内の任意の項目を追加の属性としてドロップダウン内の各項目に追加します。

第三に、私の ViewModel コードには次のものがあります。

private List<SelectListItemWithAttributes> pDropDownDatas = null;
public List<SelectListItemWithAttributes> DropDownDatas {
    get {
        var DropDownDataItems = (
            from c in db.GetDropDownDataList(1, 1000)
            where c.AccountTypeID == this.AccountTypeID
            select new SelectListItemWithAttributes() { Text = c.Title, Value = c.ID.ToString(), HtmlAttributes = new Dictionary<string, string> { { "data-callback", c.RequiresCallback.ToString().ToLower() } } } ).ToList()
            ;

        DropDownDataItems.Insert(0, new SelectListItemWithAttributes() { Text = "-- Select --", Value = "", HtmlAttributes = new Dictionary<string, string> { { "data-callback", "false" } } });

        return DropDownDataItems;
    }
}

これにより、最終的にドロップダウンに入力される SelectListItemsWithAttributes のリストが作成されます。これは、ビューモデルではなくコントローラーにある可能性があります。ビューモデルのプロパティにすることを選択しました。

最後に、ビューでは次のようになります。

@Html.DropDownListWithItemAttributesFor(m => m.DropDownDataID, Model.DropDownDatas)

これにより、SelectListItemsWithAttributes のリストを含むビューモデルのプロパティを使用して、ページにドロップダウンが表示されます。

このソリューションは、インターネットで見つけたさまざまなソリューションから構築したため、すべてがオリジナルではありませんでしたが、自分に合ったものにまとめました。

これが問題の解決に役立つことを願っています。

于 2012-07-01T21:54:39.707 に答える
8

フォーム送信を受信するはずのコントローラー アクション内で、選択した値の ID を使用してデータベースにクエリを実行し、長い表示名を取得して、意図したことを実行できます。

DropDownListForヘルパーはオプションへの HTML5 属性の追加をサポートしていませんが、追加data-*したとしても、標準フォーム送信の一部として送信されません。別の手法 (隠しフィールド、AJAX、クエリ文字列パラメーターなど) を使用してサーバーに送信するには、javascript を使用する必要があります。

しかし、何らかの理由でオプション タグに追加の属性が必要な場合は、いつでもカスタム ヘルパーを作成できます。

于 2012-07-01T20:24:31.800 に答える
1

これに戻るだけです。@nikeaaの答えは確かに実行可能な解決策ですが、特にXDocumentを使用すると少し重いと思いました。ここで扱っているのは TypeType (Cars) と SubType (車の種類のリスト - Viper、Granada、Hunter、Zodiac、Wolsley 1660 など) です。TypeType は、トラック、自転車などの場合もあります。したがって、これを解決する方法を次に示します。

コントローラーに JsonResult メソッドを追加して、必要な 3 つのプロパティを持つ匿名オブジェクトを返しました。

public class VehicleController : Controller
{
    // etc.
    public JsonResult GetSubTypesForTypeType(string typeTypeName)
    {
        var cars = pronova2Repository.GetTypeWithSubTypes(typeTypeName);

        return cars == null
        ? Json(new object[0], JsonRequestBehavior.AllowGet)
        : Json(cars.SubTypes.OrderBy(s => s.Name).Select(
            s => new { s.SubTypeID, s.Name, s.Description }).ToArray(),
            JsonRequestBehavior.AllowGet);
    }
    // etc.
}

次にjsで:

ドロップダウンに入力します。

// populate the cars drop down when the select list is available
if ($('select#SubTypeID').length) {
    var carsSelect = $('select#SubTypeID');
    var carsList = populateCarsList("CARS");
    var carsListHtml = createCarsSelectList(carsList);
    carsSelect.html('');
    carsSelect.append(carsListHtml);

    $('#SubTypeID').change(function (e) {
        clearFormData();
    });
}

関数を呼び出して、ajax 呼び出しを介してサブタイプ (車) を取得します。

function populateCarsList(typeTypeName) {
    var carsList;

    $.ajax({
        url: '/Vehicle/GetSubTypesForTypeType',
        data: { typeTypeName: typeTypeName },
        async: false
    }).done(function (data) {
        carsList = data;
    }).error(function (msg, url, line) {
        alert("Error retrieving cars from Vehicle/GetSubTypesForTypeType. Error message: " + line);
    });

    return carsList;
}

「data-*」属性として説明を追加した選択リストを作成する関数:

function createCarsSelectList(selectData) {
    var html = '',
        len = selectData.length,
        selected,
        description;

    for (var i = 0; i < len; i++) {

        // "Viper" should be selected by default
        if (selectData[i].Name.toLocaleUpperCase() === "VIPER") {
            selected = ' selected="selected" ';
        } else {
            selected = '';
        }

        // Add the description (as a "data-" attribute), some descritions are null
        if (selectData[i].Description != null) {
            description = selectData[i].Description;
        } else {
            description = '';
        }

        html += '<option value="' + selectData[i].SubTypeID + '" data-description="' + description + '"' + selected + '>' + selectData[i].Name + '</option>';
    }

    return html;
}
于 2012-07-25T13:35:30.060 に答える