我正在开发一个MVC页面,该页面应该呈现基于XML文件的表单。
XML是类型'设置'的序列化类对象。它可以包含布尔,字符串和整数数组 - 以及同一个类的零个或多个相同子元素的数组(元素的递归嵌套以反映XML的灵活结构)。
这应该是某些配置XML文件的通用解决方案。
MVC页面应该显示表单,允许编辑它并保存设置 - 将类序列化回配置XML文件。这样就行了,即我可以编辑数据并保存。
它还应该允许动态添加元素(道歉,布局是一个非常初始的版本,它不显示元素的嵌套Root => Config(s)=> Stage(s)=>语言(一个或多个)。
现在,从视觉角度将项目添加到表单中可以正常工作,但是当发布表单时,SubElements数组不包含新项目。
现在让我给你看一些代码:
public class ConfigModel : IPluginConfiguration
{
public ConfigModel()
{
}
public StringPluginSetting[] StringSettings { get; set; }
public BooleanPluginSetting[] BooleanSettings { get; set; }
public IntegerPluginSetting[] IntegerSettings { get; set; }
public PickListPluginSetting[] PickListSettings { get; set; }
public PluginConfigElement[] SubElements { get; set; }
public int PluginFrequencyMinutes { get; set; }
public bool IsDeactivated { get; set; }
public bool IsTemplate { get; set; }
}
主视图
@model TestAppForConfigHelpers.Models.ConfigModel
@if (Model != null)
{
using (Html.BeginForm())
{
@Html.Partial("_GlobalSettings")
<br/>
<br/>
for (int i = 0; i < Model.SubElements.Length; i++)
{
<br/>
<p>Config @i</p>
<br/>
@Html.EditorFor(m => Model.SubElements[i])
}
<br/>
<input type="submit" value="Save configuration"/>
}
}
编辑模板:
@model ConfigHelperTest.ConfigurationHelper.PluginConfigElement
<div>
<table id="parentTable_@Model.GetHashCode()" class="table-bordered" style="margin-left: @string.Format(HomeController.Margin+"px")">
<tr class="label-primary">
<td colspan="99"><input type="button" class="btn-xs" value="Add" id="@string.Format("addNewElement" + Model.GetHashCode())" />@Model.ElementType</td>
</tr>
<tr>
<td>
@Html.HiddenFor(model => model.ElementType)
@Html.EditorFor(model => model.StringSettings)
</td>
</tr>
</table>
@if (Model.SubElements != null)
{
for (int i = 0; i < Model.SubElements.Length; i++)
{
@Html.EditorFor(m => Model.SubElements[i])
}
}
</div>
添加元素的Javascript:
<script type="text/javascript">
$(document).ready(function() {
$('#addNewElement'+@Model.GetHashCode()).on('click', function() {
var modelDataJson = '@Html.Raw(Json.Encode(Model))';
$.ajax({
url: '@(Url.Action("AddNewElement", "Home"))',
type: 'post',
data: { elementInJson: modelDataJson},
success: function(partialView) {
var id = 'parentTable_' + @Model.GetHashCode();
$('#'+id).parent().parent().append(partialView);
}
});
});
});
</script>
JavaScript调用的控制器操作
public ActionResult AddNewElement(string elementInJson)
{
PluginConfigElement element =
new JavaScriptSerializer().Deserialize<PluginConfigElement>(elementInJson);
//simply add a new one based on the source one, with all subelements etc
return PartialView("~/Views/Shared/EditorTemplates/PluginConfigElement.cshtml", element);
}
任何帮助表示赞赏!
干杯
更新代码
根据Stephen的建议,我稍微更新了代码 - 删除了不需要的控制器操作,停止使用循环编辑器模板并更改了点击事件上的javascript被触发的方式。
主要观点:
@if (Model != null)
{
using (Html.BeginForm())
{
<div id="formDiv">
@Html.Partial("_GlobalSettings")
<br/>
<br/>
@Html.EditorFor(m => Model.SubElements)
<br/>
<input type="submit" value="Save configuration"/>
</div>
}
}
编辑模板+ javascript:
@model ConfigHelperTest.ConfigurationHelper.PluginConfigElement
<div>
<table class="table-bordered" >
<tr class="label-primary">
<td colspan="99"><input type="button" class="btn-xs addNewElement" value="Add" onclick="addNewElement(this)" />@Model.ElementType</td>
</tr>
<tr>
<td>
@Html.HiddenFor(model => model.ElementType)
@Html.EditorFor(model => model.StringSettings) //custom editor template below
//@Html.EditorFor(model => model.BooleanSettings) not used now for simplicity
</td>
</tr>
</table>
@if (Model.SubElements != null)
{
@Html.EditorFor(m => Model.SubElements)
}
</div>
<script type="text/javascript">
function addNewElement(element) {
//todo
}
</script>
现在,我想使用建议的in this answer方法,但我不知道应该在哪里放置隐藏的模板div - 更重要的是,如果我已经存在,那么这个隐藏的div应该包含什么使用编辑器模板来设置可能的设置对象(字符串,整数,布尔值)......
<div id="NewSubElement" style="display: none">
</div>
设置数组的编辑器模板
@model ConfigHelperTest.ConfigurationHelper.PluginSetting
@if (Model != null)
{
<tr>
<td><b>
@Html.HiddenFor(m => m.Name)
@Html.DisplayFor(m => m.Name)
</b>
</td>
<td>
@Html.EditorFor(m => m.Value)
@Html.HiddenFor(m => m.IsOptional)
</td>
</tr>
}