EditorFor()和additionalViewData:如何在helper类中添加数据?

Cym*_*men 17 asp.net-mvc views anonymous-types asp.net-mvc-3

EditorFor()可以采用一个object additionalViewData参数,填充的典型方法是:

EditorFor(model => model.PropertyName, new { myKey = "myValue" })

如何在自定义HTML帮助程序中检查additionalViewData的内容,添加或附加到键的现有值等?

我尝试过这些方法:

  • 转换为Dictionary<string, object>()和添加/追加值:不起作用,因为它看起来像MVC中的EditorFor的实现使用新的RouteValueDictionary(additionalViewData)将字典嵌入到字典中
  • 转换为RouteValueDictionary使用new RouteValueDictionary(additionalViewData)但具有与上述相同(或非常相似)的问题

我也愿意"你做错了" - 也许我错过了一个更简单的方法.请记住,我要做的是编写一个可重用的HTML帮助程序,并为自定义视图使用的additionalViewData添加一些值.有些值依赖于属性中的元数据,所以它只是使用一堆不同的模板并不是那么容易.

更新我正在做的事情的例子:

    public static MvcHtmlString myNullableBooleanFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> choice, string templateName, object additionalViewData)
    {            
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(choice, htmlHelper.ViewData);

        /*
    here need to add to additionalViewData some key values among them:
    { propertyName, metadata.PropertyName }

     */

        StringBuilder sb = new StringBuilder();
        sb.AppendLine(htmlHelper.EditorFor(choice, templateName, additionalViewData).ToString());
        MvcHtmlString validation = htmlHelper.ValidationMessageFor(choice);
        if (validation != null)
            sb.AppendLine(validation.ToString());
        return new MvcHtmlString(sb.ToString());
    }
Run Code Online (Sandbox Code Playgroud)

更新当我将匿名对象转换为a Dictionary<string, object>()并将该字典传递给时所发生的情况EditorFor():

我在Razor视图中设置了一个断点并检查了ViewData.似乎传入的字典EditorFor()放在另一个字典中Dictionary<string, object>().在"立即窗口"中,ViewData如下所示:

ViewData.Keys
Count = 4
    [0]: "Comparer"
    [1]: "Count"
    [2]: "Keys"
    [3]: "Values"
Run Code Online (Sandbox Code Playgroud)

查看字典中的字典内容如何?是的,实际数据在内部字典中,但不出所料,这不起作用.

添加赏金.

jhi*_*den 11

在我的情况下,我有一个布尔字段的编辑器,我想成为是/否收音机.我使用additionalViewData属性来设置要本地化的yes/no文本.似乎对我有用!

这是我的自定义编辑器的代码:

@model bool?       
@{
    var yes = ViewBag.TrueText ?? @Resources.WebSiteLocalizations.Yes;
    var no = ViewBag.FalseText ?? @Resources.WebSiteLocalizations.No;
}
<div class="title">
    @Html.LabelFor(model => model)
    @Html.RequiredFor(model => model)
</div>
<div class="editor-field">
    @Html.RadioButton("", "True", (Model.HasValue && Model.Value))@yes
    <br />
    @Html.RadioButton("", "False", (Model.HasValue && Model.Value == false))@no
    <br />
    @Html.ValidationMessageFor(model => model)
</div>
@Html.DescriptionFor(model => model)   
Run Code Online (Sandbox Code Playgroud)

以下是您如何调用此自定义EditorFor:

@Html.EditorFor(model => model.IsActive, new {TrueText = @Resources.WebSiteLocalizations.Active, FalseText = @Resources.WebSiteLocalizations.InActive})
Run Code Online (Sandbox Code Playgroud)


Sha*_*thy 5

如果我理解正确,您试图迭代匿名类型的属性.如果是这样:我如何在C#中迭代匿名对象的属性?

[编辑]好的,不止于此.这真的让我很烦,因为我喜欢C#而且它不会让我做Python所做的事情,我也很喜欢.所以这是一个解决方案,如果你使用的是C#4,但它很混乱,并且会解决我遇到的类似问题,但可能并不完全适合你:

    // Assume you've created a class to hold commonly used additional view data
    // called MyAdditionalViewData. I would create an inheritance hierarchy to
    // contain situation-specific (area-specific, in my case) additionalViewData.
class MyAdditionalViewData
{
    public string Name { get; set; }

    public string Sound { get; set; }
}     

/* In your views */
// Pass an instance of this class in the call to your HTML Helper
EditorFor(model => model.PropertyName, 
    new { adv = new MyAdditionalViewData { Name = "Cow", Sound = "Moo" } }) ;               

    /* In your HTML helper */
    // Here's the C# 4 part that makes this work.
dynamic bovine = new ExpandoObject();

// Copy values
var adv = x.adv;
if (adv.Name != null) bovine.Name = adv.Name;
if (adv.Sound != null) bovine.Sound = adv.Sound;

// Additional stuff
bovine.Food = "Grass";
bovine.Contents = "Burgers";

    // When the MVC framework converts this to a route value dictionary
    // you'll get a proper object, not a dictionary within a dictionary
var dict = new RouteValueDictionary(bovine);
Run Code Online (Sandbox Code Playgroud)

必须一个更好的方法.


Gat*_*ats 5

您是否尝试过将数据添加到

helper.ViewData[xxx] = yyy;
Run Code Online (Sandbox Code Playgroud)

ViewData集合是ViewContext的全局集合,因此我认为将其添加到全局ViewData将使其在呈现EditorTemplate时可用.

更多信息:据我了解,additionalViewdata属性只是一种简单的方法,可以在您决定渲染哪个控件后,动态地将集合/任何内容添加到全局ViewData中.仍然使用相同的上下文集合,而不是一个不同的对象作为添加到相同的上下文字典的后期和干净的方式.

我还没有尝试过这个,所以如果我错过了这一点,请说出来,我会删除答案.