【问题标题】:MVC4 ViewData.TemplateInfo.HtmlFieldPrefix generates an extra dotMVC4 ViewData.TemplateInfo.HtmlFieldPrefix 生成一个额外的点
【发布时间】:2014-11-01 10:02:18
【问题描述】:

我正在尝试获取正确的输入名称,以便可以绑定我的视图模型上的对象集合。

   @{ViewData.TemplateInfo.HtmlFieldPrefix = listName;}
            @Html.EditorFor(m => m, "DoubleTemplate", new { 
                Name = listName,
                Index = i,
                Switcher = (YearOfProgram >= i +1)
            })

正如您在此处看到的,我传入“listName”作为模板的前缀,listName =“MyItems”的值。

这是我的模板:

@model Web.Models.ListElement

@if (ViewData["Switcher"] != null)
{
    
    var IsVisible = (bool)ViewData["Switcher"];
    var index = (int)ViewData["Index"];
    var thisName = (string)ViewData["Name"] + "[" + index + "].Value";
    var thisId = (string)ViewData["Name"] + "_" + index + "__Value";
    if (IsVisible)
    {
        @*<input type="text" value="@Model.Value" name="@thisName" id ="@thisId" class="cell@(index + 1)"/>*@
        @Html.TextBoxFor(m => m.Value, new { @class ="cell" + (index + 1)})
        @Html.ValidationMessageFor(m => m.Value)
    }
}

但是我发现生成的名字变成了这样:MyItems.[0].Value

它有一个额外的点。我怎样才能摆脱它?

顺便说一句,我尝试在模板中手动指定名称,但发现该名称被 Html 帮助程序覆盖。

更新

我必须手动设置 HtmlFieldPrefix 的原因是当 MyItems 从主视图传递到部分视图时,属性名称(MyItems 是对象列表)会丢失。当局部视图调用我的模板并在 MyItems 中传入一个对象时,模板本身无法确定 MyItems 的名称,因为它自上次“传入”以来已经丢失。

这就是为什么我必须手动设置 html 字段前缀名称。我什至尝试使用类似于反射的东西(但不是连任,我忘记了名字)来检查传入对象的名称,发现它返回“模型”。


更新 2

我尝试了 Stephen 的方法,但找不到 html 帮助器 PartialFor()。

我什至尝试在我的主视图中使用它:

Html.Partial(Model, "_MyPartialView");

在局部视图中:

@model MvcApplication1.Models.MyModel
<h2>My Partial View</h2>


@Html.EditorFor(m => m.MyProperty)

这是我的模板:

@model  MvcApplication1.Models.ListElement

@Html.TextBoxFor(m => m.Value)

这是我的模型:

 public class MyModel
    {
        private List<ListElement> myProperty;
        public List<ListElement> MyProperty
        {
            get
            {
                if (myProperty == null)
                {
                    this.myProperty = new List<ListElement>() { new ListElement() { Value = 12 }, new ListElement() { Value = 13 }, new ListElement() { Value = 14 }, new ListElement() { Value = 15 }, };
                }
                return this.myProperty;
            }
            set
            {
                this.myProperty = value;
            }
        }
    }

    public class ListElement
    {
        [Range(0, 999)]
        public double Value { get; set; }
    }

这是我的控制器:

public ActionResult MyAction()
{
    return View(new MyModel());
}

它只为我生成原始文本(“12131415”),而不是用 12 13 14 15 填充的想要的文本框。

但是如果我指定了模板名称,它会抛出一个异常:

The template view expecting ListElement, and cannot convert
List<ListElement> into ListElement.

【问题讨论】:

  • 通过覆盖默认行为来理解您试图实现的目标有点困难。你模式有public ListElement MyItems { get; set; } 的属性吗?如果没有,您将如何在回发时绑定它?你有另一个 EditorTemplate 用于 typeof ListElement 吗?
  • 嗨 @StephenMuecke 是的,我的模型有 MyItems(MyViewModel 有 MyItems)。我将 MyViewModel 绑定到使用 PartialView _MyPartialView 的 MyView.cshtml 页面,这个局部视图使用模板。我说的是这个模板中属性名称的丢失。我找到了一个解决方案,但它可能不是最好的。
  • 但是你不需要设置HtmlFieldPrefix的值。如果您正确使用EditorTemplate,MVC 将为您执行此操作(您不应使用接受模板名称的重载)。
  • 嗨@StephenMuecke 我已根据您的问题更新了我的帖子,请参阅我的更新部分。欢呼
  • 我将很快发布一个答案,说明您如何做到这一点,但我有点不确定Switcher 是什么,但我们可以在之后解决这个问题

标签: asp.net-mvc-4 razor-2


【解决方案1】:

无需设置HtmlFieldPrefix 值。如果您使用基于属性类型的EditorTemplate(并且没有模板名称),MVC 将正确命名元素。

假定模型

public class ListElement
{
  public string Value { get; set; }
  ....
}

public class MyViewModel
{
  public IEnumerable<ListElement> MyItems { get; set; }
  ....
}

编辑器模板 (ListElement.cshtml)

@model YourAssembly.ListElement
@Html.TextBoxFor(m => m.Value)

主视图

@model YourAssembly.MyViewModel
...
@Html.EditorFor(m => m.MyItems) // note do not specify the template name

这将呈现

<input type="text" name="MyItems[0].Value" ...>
<input type="text" name="MyItems[1].Value" ...>
....

如果你想使用局部模型,你可以将整个模型传递给局部模型

MyPartial.cshtml

@model @model YourAssembly.MyViewModel
@Html.EditorFor(m => m.MyItems)

在主视图中

@Html.Partial("MyPartial")

或者创建一个扩展方法

public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper,
  Expression<Func<TModel, TProperty>> expression, string partialViewName)
  {
    string name = ExpressionHelper.GetExpressionText(expression);
    object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
    var viewData = new ViewDataDictionary(helper.ViewData)
    {
      TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = name }
    };
    return helper.Partial(partialViewName, model, viewData);
  }
}

并用作

@Html.PartialFor(m => m.MyItems, "MyPartial")

在局部

@model IEnumerable<YourAssembly.ListElement>
@Html.EditorFor(m => m)

【讨论】:

  • 嗨斯蒂芬,谢谢你的帮助。但情况不同。 Main View ---> Partial View(passed in the MyItems) ---> MyTemplate(passed in the one object in MyItems, eg MyItems[i]) 我尝试以正常方式使用它们,但发现 MyItems 的名称为丢失并变为 [0].Value。哦,顺便说一句,为什么不指定模板名称???
  • 您仍然可以使用部分执行此操作(我会更新答案)。不使用模板名称的重载的原因是您丢失了名称的默认索引 - 请参阅this question 以获得更详细的解释
  • 哈哈看起来不错。我会试一试,让你知道它是怎么回事。谢谢 :)
  • 嗨斯蒂芬,我试过你的方法。我什至在我的 MVC 中找不到 @Html.PartialFor() 助手。我用的是 MVC4,你的版本是多少?
  • @Franva,PartialFor() 是我为您创建的扩展方法 - 请参阅我的答案中的代码 - 以 public static MvcHtmlString PartialFor&lt;TModel ... 开头的代码块
【解决方案2】:
  1. 这样调用你的部分:
@Html.Partial("_SeatTypePrices", Model.SeatTypePrices, new ViewDataDictionary
{
    TemplateInfo = new TemplateInfo() {HtmlFieldPrefix = nameof(Model.SeatTypePrices)}
})
  1. 局部视图:
@model List
@Html.EditorForModel()
  1. 编辑器模板实现:

    @using Cinema.Web.Helpers
    @model Cinema.DataAccess.SectorTypePrice
    @Html.TextBoxFor(x => Model.Price)
    

这样,您的局部视图将包含带有前缀的项目列表。 然后从您的EditorTemplates 文件夹中调用EditorForModel()

【讨论】:

    【解决方案3】:

    我发现我可以在我的模板中更改 HtmlFeildPrefix 的值。

    所以我为解决我的问题所做的只是直接在模板中为 HtmlFeildPrefix 分配正确的值,而不是在调用模板的页面中。

    希望对你有帮助。

    【讨论】:

      【解决方案4】:

      如果我想传递 HtmlFieldPrefix,我使用以下构造:

      <div id="_indexmeetpunttoewijzingen">
          @Html.EditorFor(model => model.MyItems, new ViewDataDictionary()
          {
              TemplateInfo = new TemplateInfo()
              {
                  HtmlFieldPrefix = "MyItems"
              }
          })
      </div>                       
      

      【讨论】:

        猜你喜欢
        • 2014-09-03
        • 1970-01-01
        • 2020-04-02
        • 1970-01-01
        • 2019-08-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-07
        • 1970-01-01
        相关资源
        最近更新 更多