【问题标题】:Shorthand for creating a ViewDataDictionary with both a model and ViewData items?使用模型和 ViewData 项创建 ViewDataDictionary 的简写?
【发布时间】:2010-10-11 02:45:31
【问题描述】:

有没有办法通过一行代码创建一个带有模型和附加属性的ViewDataDictionary。我正在尝试对强类型视图进行RenderPartial 调用,同时组装模型和一些额外的显示配置属性,而无需跨多行显式组装 ViewDataDictionary。考虑到 RenderPartial 重载同时采用模型 object 和 ViewDataDictionary 似乎是可能的,但看起来只要它们都被填充,它就会简单地忽略 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,添加新参数并在@987654330 中使用它@调用。

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

同样,尝试将 ViewDataDictionary 与显式 Model 和 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 };

当然,如果没有他 [最终准确] 的回答,我仍然会旋转我的轮子,所以,圆得到了正方形。

【问题讨论】:

    标签: asp.net-mvc renderpartial


    【解决方案1】:

    使用object initializer 和集合初始化器:

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

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

    然后只传递整个事情而不单独设置 MyModelObject:

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

    【讨论】:

    • 这似乎创建了一个 ViewDataDictionary ,其 Model 等于匿名对象,然后用 MyModelObject 替换 Model 属性,不留下任何附加属性。它确实教会了我可以将构造函数与其他初始化程序结合起来;我不知道的东西-谢谢。
    • 我刚刚检查了源代码。设置模型不会清除字典。
    • 我同意;设置模型不会清除字典。但是您没有在此代码中设置字典。您使用包含 SomeDisplayParameter 属性的匿名对象的模型创建 ViewDataDictionary。然后,使用初始化程序,将模型更改为 MyModelObject。
    • 我明白你的意思。 ViewDataDictionary(ViewDataDictionary) 和 ViewDataDictionary(object) 构造函数的工作方式不同。我将更新示例)。
    • 我找到了一个有效的语法(下一个答案),但我不知道幕后发生了什么让它工作。我想如果我浏览 MVC 源代码,我可能能够遵循这个特定初始化器语法中使用的逻辑。
    【解决方案2】:

    使用 Craig 的回答作为起点——我什至不知道你可以将构造函数调用和对象初始化程序结合起来——我偶然发现了来自巴勒莫的这个 snippet,它导致了一个有效的组合。他使用某种字典速记,当被ViewDataDictionary 对象初始化程序使用时,不知何故最终填充了ModelState。

    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,我仍然看不到这最终是如何工作的,但它似乎确实同时维护了原始模型对象和视图的“附加”参数。这种语法肯定有许多其他排列不起作用-您不能将模型与字典组合在单个对象中,或者对字典值使用对象初始化器语法-但上述版本似乎有效。

    【讨论】:

      【解决方案3】:

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

      我认为可能有用的是这个(请原谅 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"})
      

      编辑器模板只是存在的部分视图

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

      我的 Address 模板是一个强类型的局部视图,但 EditorFor 方法提供了使用匿名对象轻松添加其他视图数据项的能力。

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

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

      【讨论】:

        【解决方案4】:

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

        示例

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

        HtmlHelper 扩展

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

        【讨论】:

        • 正是我想要的!谢谢
        【解决方案5】:

        这在旧式 mvc aspx 视图中对我有用:

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

        这里的问题是,在构造函数中,我使用当前视图数据“new ViewDataDictionary(this.ViewData)”,这是一个包含验证消息所需的模型状态的视图数据字典。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-26
          • 2022-01-19
          • 2020-10-20
          • 1970-01-01
          • 1970-01-01
          • 2021-07-31
          • 1970-01-01
          • 2022-06-27
          相关资源
          最近更新 更多