gpt4 book ai didi

c# - 如何使用 MVC HTML 编辑器模板生成非顺序前缀集合索引?

转载 作者:行者123 更新时间:2023-11-30 21:06:20 25 4
gpt4 key购买 nike

下面的代码已经精简了很多,但基本上我想要实现的是如下:

我希望能够编辑问题及其包含的答案选择,同时能够从页面动态添加/删除问题/答案选择。理想情况下,我的项目的 HtmlFieldPrefix 是非顺序的,但 Html.EditorFor() 使用顺序索引。

我有一个包含答案选择的 IEnumerable 的问题 View 模型:

public class QuestionViewModel
{
public int QuestionId { get; set; }
public IEnumerable<AnswerChoiceViewModel> AnswerChoices { get; set; }
}

在我的问题部分 View (Question.ascx) 中,我有这个:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Models.QuestionViewModel>" %>

<%=Html.HiddenFor(m => m.QuestionId)%>
<%=Html.EditorFor(m => m.AnswerChoices) %>

以及答案选择编辑器模板 (AnswerChoiceViewModel.ascx):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Models.AnswerChoiceViewModel>" %>

<%=Html.HiddenFor(m => m.AnswerChoiceId)%>
<%=Html.TextBoxFor(m => m.Name)%>

当我呈现 Question.ascx 时,输出将如下所示:

<input type="hidden" id="QuestionId" value="1" />
<input type="hidden" id="Question.AnswerChoices[0].AnswerChoiceId" value="1" />
<input type="hidden" id="Question.AnswerChoices[0].Name" value="Answer Choice 1" />

<input type="hidden" id="QuestionId" value="2" />
<input type="hidden" id="Question.AnswerChoices[1].AnswerChoiceId" value="2" />
<input type="hidden" id="Question.AnswerChoices[1].Name" value="Answer Choice 2" />

我想知道的是如何为 EditorFor 提供自定义 GUID 索引,以便页面呈现如下:

<input type="hidden" id="QuestionId" value="1" />
<input type="hidden" id="Question.AnswerChoices[e1424d5e-5585-413c-a1b0-595f39747876].AnswerChoiceId" value="1" />
<input type="hidden" id="Question.AnswerChoices[e1424d5e-5585-413c-a1b0-595f39747876].Name" value="Answer Choice 1" />

<input type="hidden" id="QuestionId" value="2" />
<input type="hidden" id="Question.AnswerChoices[633db1c3-f1e6-470b-9c7f-c138f2d9fa71].AnswerChoiceId" value="2" />
<input type="hidden" id="Question.AnswerChoices[633db1c3-f1e6-470b-9c7f-c138f2d9fa71].Name" value="Answer Choice 2" />

我已经编写了一个辅助方法,它将获取当前上下文的前缀索引并将其存储在隐藏的“.Index”字段中,以便可以正确绑定(bind)非顺序索引。只想知道 EditorFor 如何分配索引,以便我可以覆盖它(或任何其他有效的解决方案)。

最佳答案

前一段时间我解决了这个问题并遇到了 S. Sanderson(Knockoutjs 的创建者)的帖子,他在帖子中描述并解决了类似的问题。我使用了他的部分代码并尝试修改它以满足我的需要。我将下面的代码放在某个类中(例如:Helpers.cs),在 web.config 中添加命名空间。

    #region CollectionItem helper
private const string idsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_";

public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName)
{
var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();

// autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync.
html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, itemIndex));

return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
}

public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix)
{
return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
}

private static Queue<string> GetIdsToReuse(HttpContextBase httpContext, string collectionName)
{
// We need to use the same sequence of IDs following a server-side validation failure,
// otherwise the framework won't render the validation error messages next to each item.
string key = idsToReuseKey + collectionName;
var queue = (Queue<string>)httpContext.Items[key];
if (queue == null)
{
httpContext.Items[key] = queue = new Queue<string>();
var previouslyUsedIds = httpContext.Request[collectionName + ".index"];
if (!string.IsNullOrEmpty(previouslyUsedIds))
foreach (string previouslyUsedId in previouslyUsedIds.Split(','))
queue.Enqueue(previouslyUsedId);
}
return queue;
}

private class HtmlFieldPrefixScope : IDisposable
{
private readonly TemplateInfo templateInfo;
private readonly string previousHtmlFieldPrefix;

public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
{
this.templateInfo = templateInfo;

previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
}

public void Dispose()
{
templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
}
}

#endregion

在你可以像这样拥有 EditorTemplate 或 partial 之后

@using (Html.BeginCollectionItem("AnswerChoices"))
{
@Html.HiddenFor(m => m.AnswerChoiceId)
@Html.TextBoxFor(m => m.Name)
}

并枚举您的列表呈现模板(部分)。

关于c# - 如何使用 MVC HTML 编辑器模板生成非顺序前缀集合索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11267354/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com