0

独自の種類のパラメーターを使用して MultiSelectList を構築するための MVC ヘルパーを構築しようとしています。少し前に作成した SelectFor ヘルパーに基づいています。SelectFor は次のようになります。

    public delegate object Property<T>(T property);
    public delegate object Property<T, K>(T property, K propertyKey);

    public static HtmlString SelectFor<TModel, TProperty, TListItem>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> forExpression,
        IEnumerable<TListItem> enumeratedItems,
        Property<TListItem> idExpression,
        Property<TListItem> displayExpression,
        Property<TListItem> titleExpression,
        object htmlAttributes,
        bool blankFirstLine) where TModel : class
    {
        //initialize values
        var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
        var propertyName = metaData.PropertyName;
        var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();
        var enumeratedType = typeof(TListItem);

        //build the select tag
        var returnText = string.Format("<select id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
        if (htmlAttributes != null)
        {
            foreach (var kvp in htmlAttributes.GetType().GetProperties()
             .ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
            {
                returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
                 HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
            }
        }
        returnText += ">\n";

        if (blankFirstLine)
        {
            returnText += "<option value=\"\"></option>";
        }

        //build the options tags
        foreach (TListItem listItem in enumeratedItems)
        {
            var idValue = idExpression(listItem).ToStringOrEmpty();
            var displayValue = displayExpression(listItem).ToStringOrEmpty();
            var titleValue = titleExpression(listItem).ToStringOrEmpty();
            returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
                HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
            if (idValue == propertyValue)
            {
                returnText += " selected=\"selected\"";
            }
            returnText += string.Format(">{0}</option>\n", displayValue);
        }

        //close the select tag
        returnText += "</select>";
        return new HtmlString(returnText);
    }

MultiSelectFor はわずかに異なるだけで、重要な違いが 1 つあります。は のプロパティ タイプのforExpressionジェネリックになります。このコレクションは、リスト項目を「事前選択」するために使用され、フォーム上で選択された項目の戻り値になります。私はこれでさらに進んだ(と思う)が、まだかなり迷っている.IEnumerableidExpression

    public static HtmlString MultiSelectListFor<TModel, TProperty, TProperty, TPropertyKey>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, IEnumerable<TPropertyKey>>> forExpression,
        IEnumerable<TProperty> enumeratedItems,
        Property<TProperty, TPropertyKey> idExpression,
        Property<TProperty> displayExpression,
        Property<TProperty> titleExpression,
        object htmlAttributes) where TModel : class
    {
        //initialize values
        var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
        var propertyName = metaData.PropertyName;
        var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();
        var enumeratedType = typeof(TProperty);

        //build the select tag
        var returnText = string.Format("<select multiple=\"multiple\" id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
        if (htmlAttributes != null)
        {
            foreach (var kvp in htmlAttributes.GetType().GetProperties()
             .ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
            {
                returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
                 HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
            }
        }
        returnText += ">\n";

        //build the options tags
        foreach (TProperty listItem in enumeratedItems)
        {
            //this part here needs to change:
            var idValue = ???.ToStringOrEmpty();

            var displayValue = displayExpression(listItem).ToStringOrEmpty();
            var titleValue = titleExpression(listItem).ToStringOrEmpty();
            returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
                HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
            if (propertyValue.Contains(idValue))
            {
                returnText += " selected=\"selected\"";
            }
            returnText += string.Format(">{0}</option>\n", displayValue);
        }

        //close the select tag
        returnText += "</select>";
        return new HtmlString(returnText);
    }

助けていただければ幸いです。

更新 答えてくれてありがとう!ジェネリックは時々私を混乱させます。完全なソリューションは次のとおりです。

    public delegate object Property<T>(T property);

    public static HtmlString MultiSelectListFor<TModel, TKey, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, IEnumerable<TKey>>> forExpression,
        IEnumerable<TProperty> enumeratedItems,
        Func<TProperty, TKey> idExpression,
        Property<TProperty> displayExpression,
        Property<TProperty> titleExpression,
        object htmlAttributes) where TModel : class
    {
        //initialize values
        var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
        var propertyName = metaData.PropertyName;
        var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();
        var enumeratedType = typeof(TProperty);

        //build the select tag
        var returnText = string.Format("<select multiple=\"multiple\" id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
        if (htmlAttributes != null)
        {
            foreach (var kvp in htmlAttributes.GetType().GetProperties()
             .ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
            {
                returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
                 HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
            }
        }
        returnText += ">\n";

        //build the options tags
        foreach (TProperty listItem in enumeratedItems)
        {
            var idValue = idExpression(listItem).ToStringOrEmpty();
            var displayValue = displayExpression(listItem).ToStringOrEmpty();
            var titleValue = titleExpression(listItem).ToStringOrEmpty();
            returnText += string.Format("<option value=\"{0}\" title=\"{1}\"",
                HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
            if (propertyValue.Contains(idValue))
            {
                returnText += " selected=\"selected\"";
            }
            returnText += string.Format(">{0}</option>\n", displayValue);
        }

        //close the select tag
        returnText += "</select>";
        return new HtmlString(returnText);
    }

    public static HtmlString MultiSelectListFor<TModel, TKey, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, IEnumerable<TKey>>> forExpression,
        IEnumerable<TProperty> enumeratedItems,
        Func<TProperty, TKey> idExpression,
        Property<TProperty> displayExpression,
        Property<TProperty> titleExpression) where TModel : class
    {
        return htmlHelper.MultiSelectListFor(forExpression, enumeratedItems, idExpression, displayExpression, titleExpression, null);
    }

助けてくれてありがとう!

4

1 に答える 1

4

を求めているようですねExpression<Func<TModel, IEnumerable<TListItem>>

別のジェネリック パラメータを作成し、それを ID プロパティと for 式の両方に使用する必要があります。

public static HtmlString MultiSelectListFor<TModel, TKey, TListItem>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, IEnumerable<TKey>>> forExpression,
    IEnumerable<TListItem> enumeratedItems,
    Func<TListItem, TKey> idExpression,
于 2012-03-20T18:55:47.927 に答える