Shorthand for creating a ViewDataDictionary with both a model and ViewData items?

蓝咒 提交于 2019-11-28 17:52:53

Use an object initializer and collection initializers:

new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }})
    {
        Model = MyModelObject
    }

The inner ViewDataDictionary gets its collection initialized, then this populates the "real" ViewDataDictionary using the constructor overload which takes ViewDataDictionary instead of object. Finally, the object initializer sets the model.

Then just pass the whole thing without setting MyModelObject separately:

this.Html.RenderPartial("SomePartialView", null, 
    new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }})
        { Model = MyModelObject });

Using Craig's answer as a starting point--I didn't even know you could combine both a constructor call and an object initializer--I stumbled on this snippet from Palermo that leads to a combination that works. He uses some sort of dictionary shorthand that somehow ends up populating the ModelState when consumed by the ViewDataDictionary object initializer.

new ViewDataDictionary(MyModelObject) { { "SomeDisplayParameter", true }, { "SomeOtherParameter", 3 }, { "SomeThirdParameter", "red" } };
// Of course, this also works with typed ViewDataDictionary objects (what I ended up using)
new ViewDataDictionary<SomeType>(MyModelObject) { { "SomeDisplayParameter", true }, { "SomeOtherParameter", 3 }, { "SomeThirdParameter", "red" } };

I still don't see how this ends up working given that you cannot set the ModelState explicitly in an initializer, but it does seem to maintain both the original model object and the "appended" parameters for the view. There are definitely a number of other permutations of this syntax that do not work--you cannot combine the model with the dictionary in a single object or use object-initializer syntax for the dictionary values--but the above version seems to work.

I created an extension method on HtmlHelper to copy the property names and values from an anonymous object to a ViewDataDictionary.

Sample

Html.RenderPartial("SomePartialView", MyModelObject, new { SomeDisplayParameter = true })

HtmlHelper Extension

public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model, object viewData)
{
    var vdd = new ViewDataDictionary(model);
    foreach (var property in viewData.GetType().GetProperties()) {
        vdd[property.Name] = property.GetValue(viewData);
    }
    htmlHelper.RenderPartial(partialViewName, vdd);
}
Darrel Lee

I came here with the exact same question.

What I thought might work was this (pardon the VB Razor syntax)

 @Code Html.RenderPartial("Address", Model.MailingAddress, New ViewDataDictionary(New With {.AddressType = "Mailing Address"}))End Code

But of course you get this error at run-time:

System.InvalidOperationException was unhandled by user code

Message=The model item passed into the dictionary is of type 'VB$AnonymousType_1`1[System.String]', but this dictionary requires a model item of type 'ViewModel.Address'.

But what I found, is that what I really wanted was to use was Editor Template anyway.

Instead of RenderPartial use:

@Html.EditorFor(Function(model) model.MailingAddress, "Address",  New With {.AddressType = "Mailing Address"})

An editor template is just a partial view that lives

~/Views/{Model|Shared}/EditorTemplates/templatename.vbhtml

My template for Address is a strongly-typed partial view, but the EditorFor method gives the ability to add additional view data items easily with an anon object.

In the example above I didn't need to include the template name "Address", since MVC would would look for a template with the same name as the model type.

You can also override the display template in the same way.

Jeroen van der Meer

This is what worked for me in old style mvc aspx view:

<% Html.RenderPartial("ContactPartial", Model.ContactFactuur, new ViewDataDictionary(this.ViewData ) { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "Factuur" } }); %>

the thing here is that in the constructor I use the current viewdata "new ViewDataDictionary(this.ViewData)" which is a viewdatadictionary containing the modelstate that I need for the validationmessages.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!