【问题标题】:Pass property expression to method for selecting value from object将属性表达式传递给从对象中选择值的方法
【发布时间】:2014-06-21 03:48:42
【问题描述】:

我要做的是创建一个 html 扩展方法来在 mvc 项目中构建一组单选按钮。我知道我可以编写一个 for 循环,但这将是在其他项目中重用的非常有用的方法,所以我想弄清楚这一点。

我想要做的是能够传递单选按钮所针对的模型属性的表达式(因此我可以将单选按钮命名为相同的东西并选择所选选项),这是一组对象选项,以及用作单选按钮值的选项对象的属性。

这是我目前所拥有的,但它不起作用。 (我收到错误“无法将方法组 'Value' 转换为非委托类型 'string'。您是否打算调用该方法?”)。

public static HtmlString RadioOptionsFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> modelExpression, 
        IEnumerable<object> radioOptions,  
        Expression<Func<object, string>> valueExpression)
    {
        StringBuilder sb = new StringBuilder();
        var propertyName = ((MemberExpression)(modelExpression.Body)).Member.Name;

        radioOptions.Select(el => sb.Append(htmlHelper.RadioButton(propertyName, valueExpression.Compile()(el))));

        return new HtmlString(sb.ToString());
    }


@Html.RadioOptionsFor(x => x.Category, Model.CategoryOptions, e => e.Value)

更新: 好的,所以 StriplingWarrior 帮助我找到了一个可行的解决方案。问题是将第二个表达式函数的参数声明为对象。它应该是一个泛型类型,所以我只需要更改它的方法声明。我还添加了一个辅助方法来构建一个带有包装标签元素的单选按钮。我还做了一些 linq stringbuilding,所以我不必循环两次。最后,我添加了选择模型的当前值并删除单选按钮元素的重复 ID。这是最终的解决方案。

public static string RadioButtonWithLabel<TModel>(this HtmlHelper<TModel> htmlHelper, string name, string value, string selectedValue)
    {
        var sb = new StringBuilder();
        sb.Append("<label for=\"").Append(name).AppendLine("\">")
            .AppendLine(htmlHelper.RadioButton(name, value, selectedValue.Equals(value), new { id = "" }).ToString())
            .Append(value).AppendLine("</label>");

        return sb.ToString();
    }

    public static HtmlString RadioOptionsFor<TModel, TProperty, TElement>(this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> modelExpression, 
        string selectedValue,
        IEnumerable<TElement> radioOptions,  
        Expression<Func<TElement, string>> valueExpression)
    {
        var propertyName = ((MemberExpression)(modelExpression.Body)).Member.Name;

        var result = radioOptions.Aggregate(new StringBuilder(), (sb, el) => sb.Append(htmlHelper.RadioButtonWithLabel(propertyName, valueExpression.Compile()(el), selectedValue)));

        return new HtmlString(result.ToString());
    }

这样称呼

@Html.RadioOptionsFor(x => x.Category, Model.Category, Model.CategoryOptions, e => e.Value)

【问题讨论】:

    标签: c# expression radiobuttonlist


    【解决方案1】:

    Expression&lt;Func&lt;object, string&gt;&gt; valueExpression 期望你的表达式产生一个字符串:e.Value 的类型是什么?

    似乎e.Value 不应该存在,因为e 是一个对象。这是一种扩展方法吗?如果是这样,您可能需要通过:

    e => e.Value()
    

    因此,解读您的错误消息:它无法将“Value”(它是一个方法或委托)转换为表达式所期望的 string:您是否打算调用该方法来产生一个字符串?

    【讨论】:

    • e.Value 应该是集合中要用作单选按钮值的元素的属性。因此,在我的示例中,我传递了一个 XElement 集合,并且我想使用 XElement 对象的 Value 属性作为单选按钮的值,我最终将添加一个检查以验证该属性是否为字符串类型
    • @Alex:您编写上述代码的方式,e 被转换为object,所以它上面没有Value 属性。也许这应该是一个泛型类型?
    猜你喜欢
    • 2017-06-21
    • 2011-06-30
    • 2013-06-26
    • 1970-01-01
    • 2015-05-15
    • 2017-08-20
    • 1970-01-01
    • 2015-08-18
    • 2011-09-20
    相关资源
    最近更新 更多