使用模型和ViewData项创建ViewDataDictionary的简写?

时间:2009-03-03 20:19:20

标签: asp.net-mvc renderpartial

有没有办法用一行代码创建一个带有模型和附加属性的ViewDataDictionary。我试图在组装模型和一些额外的显示配置属性时对强类型视图进行RenderPartial调用,而无需跨多行显式组装ViewDataDictionary。似乎有可能在RenderPartial重载同时采用模型objectViewDataDictionary,但看起来只要它们都被填充就会忽略ViewDataDictionary

// FAIL: This will result in ViewData being a ViewDataDictionary
// where Model = MyModelObject and there are no other parameters available.
this.Html.RenderPartial("SomePartialView", MyModelObject, new ViewDataDictionary(new { SomeDisplayParameter = true }));

我找到了same problem的其他人,但他们的解决方案与我找到的相同的多线概念:使用模型创建离散ViewDataDictionary,添加新参数并使用它在RenderPartial电话中。

var SomeViewData = new ViewDataDictionary(MyModelObject);
SomeViewData.Add("SomeDisplayParameter", true);
this.Html.RenderPartial("SomePartialView", SomeViewData);

我总是可以将这个逻辑包装成一个ChainedAdd方法,该方法返回一个重复的字典,并添加了新的元素,但似乎我错过了一些创建ViewDataDictionary的方法来实现这一点我(这比我希望的要多一点)。

this.Html.RenderPartial("SomePartialView", new ViewDataDictionary(MyModelObject).ChainedAdd("SomeDisplayParameter", true));

public static ViewDataDictionaryExtensions {
    public static ViewDataDictionary ChainedAdd(this ViewDataDictionary source, string key, object value) {
        return source.ChainedAdd(new KeyValuePair<string,object>(key, value));
    }
    public static ViewDataDictionary ChainedAdd(this ViewDataDictionary source, KeyValuePair<string, object> keyAndValue) {
        ViewDataDictionary NewDictionary = new ViewDataDictionary(source);
        NewDictionary.Add(keyAndValue);
        return NewDictionary;
    }
}

同样,尝试使用显式ViewDataDictionaryModel组装ModelState只会导致编译错误,因为ModelState是只读的。

// FAIL: Compilation error
this.Html.RenderPartial("SomePartialView", new ViewDataDictionary { Model = MyModelObject, ModelState = new ViewDataDictionary( new { SomeDisplayParameter = true }});

ANSWER(S):看起来像Craig和我最终找到了两个单独的语法来完成工作。在这种情况下我肯定有偏见,但我喜欢先设置模型然后“装饰”它的想法。

new ViewDataDictionary(MyModelObject) { { "SomeDisplayParameter", true }, { "SomeOtherParameter", 3 }, { "SomeThirdParameter", "red" } };

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

当然,如果没有他的[最终定点]答案,我仍然会旋转我的车轮,所以,圆圈得到了正方形。

5 个答案:

答案 0 :(得分:26)

使用object initializer和集合初始值设定项:

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

内部ViewDataDictionary初始化其集合,然后使用构造函数重载填充“真正的”ViewDataDictionary,该重载采用ViewDataDictionary而不是object。最后,对象初始化器设置模型。

然后在不分别设置MyModelObject的情况下传递整个事物:

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

答案 1 :(得分:12)

使用Craig的答案作为起点 - 我甚至不知道你可以将构造函数调用和对象初始化程序结合起来 - 我偶然发现了来自Palermo的这个snippet,这导致了一个有效的组合。他使用某种字典速记,在ModelState对象初始值设定项使用时会以某种方式填充ViewDataDictionary

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" } };

鉴于您无法在初始化程序中明确设置ModelState,我仍然看不到这最终是如何工作的,但它似乎确实维护了原始模型对象和视图的“附加”参数。这种语法肯定有许多其他的排列不起作用 - 你不能将模型与单个对象中的字典结合使用,或者使用对象初始化器语法来表示字典值 - 但上述版本似乎有效。 / p>

答案 2 :(得分:2)

我在HtmlHelper上创建了一个扩展方法,将属性名称和值从匿名对象复制到ViewDataDictionary。

<强>示例

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);
}

答案 3 :(得分:0)

我带着完全相同的问题来到这里。

我认为可能有用(请原谅VB Razor语法)

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

但是你当然会在运行时遇到这个错误:

System.InvalidOperationException未被用户代码

处理

Message =传入字典的模型项类型为'VB $ AnonymousType_1`1 [System.String]',但此字典需要“ViewModel.Address”类型的模型项。

但我发现,无论如何,我真正想要使用的是编辑模板。

而不是使用RenderPartial:

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

编辑器模板只是一个生活的部分视图

〜/查看/ {型号|共享} /EditorTemplates/templatename.vbhtml

我的Address模板是强类型的局部视图,但EditorFor方法可以使用anon对象轻松添加其他视图数据项。

在上面的示例中,我不需要包含模板名称“Address”,因为MVC会查找与模型类型同名的模板。

您也可以用同样的方式覆盖显示模板。

答案 4 :(得分:0)

这对我来说在老式的mvc aspx视图中起作用了:

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

这里的事情是在构造函数中我使用当前的viewdata&#34; new ViewDataDictionary(this.ViewData)&#34;这是一个viewdatadictionary,包含验证消息所需的模型状态。