剑道内联编辑与IEnumerable模型属性

本文关键字:IEnumerable 模型 属性 编辑 | 更新日期: 2023-09-27 18:19:21

如果有人能提供以下建议,我将不胜感激:

我有一个模型包含另一个模型的集合:

public class ContractModel
{
    public ContractModel()
    {
          this.ContractCurrencyClauses = new HashSet<ContractCurrencyClause>();
    }
    public System.Guid ID { get; set; }
    public virtual ICollection<ContractCurrencyClause> ContractCurrencyClauses { get; set; }
   //other model properties
}
public partial class ContractCurrencyClause
{
    public System.Guid ID {get; set;} //PK
    public System.Guid CONTRACT_ID { get; set; } //FK on ContractModel(ID)
    public string CURRENCY { get; set; } 
    public Nullable<decimal> RATE { get; set; }
}

问题是,我不确定如何临时存储ContractCurrencyClauses的集合时,ContractModel正在创建。我将ContractModel的新实例传递给我的视图:

    [HttpGet]
    public ActionResult Create()
    {
        ContractModel Contract = context.Contracts.Create();
        Contract.ID = Guid.NewGuid();
        return PartialView(Contract);
    }

在我看来:

@model ContractModel
@using (Ajax.BeginForm("Create", null, new AjaxOptions() { ... }))
{
@Html.HiddenFor(model=>model.ID)
@(Html.Kendo().Grid(Model.ContractCurrencyClauses)
               .Name("ContractCurrencyClauses")
               .ToolBar(toolbar => toolbar.Create())
               .Columns(columns => {
                        columns.Bound(u => u.ID).Hidden(true);
                        columns.Bound(u => u.CONTRACT_ID).Hidden(true);
                        columns.Bound(u => u.CURRENCY);
                        columns.Bound(u => u.RATE);
                        columns.Command(command => { command.Edit(); command.Destroy(); });
                        })
                        .Editable(editable => editable.Mode(GridEditMode.InLine))
                        .DataSource(dataSource => 
                                dataSource.Ajax()
                                .Model(model =>
                                {
                                    model.Id(u => u.ID);                                        
                                    model.Field(u => u.CONTRACT_ID).DefaultValue(Model.ID);
                                    model.Field(u => u.ID).DefaultValue(Guid.NewGuid());
                                })
                         .Create(create => create.Action("CreateCurClause", "Contracts"))
                         .Update(update => update.Action("UpdateCurClause", "Contracts"))
                         .Destroy(destroy => destroy.Action("DestroyCurClause", "Contracts")))
                )
 }

当我提交新的网格条目时,我收到ContractCurrencyClause模型的null:

 public ActionResult CreateCurClause([DataSourceRequest]DataSourceRequest request, ContractCurrencyClause clause)
    {
        if(ModelState.IsValid)
        {
        }
        return Json(new[] { clause }.ToDataSourceResult(request, ModelState));
    }

我猜这是因为没有创建模型的新实例,当我按下网格工具栏中的Add按钮时,因为我看到JS错误:无法读取nullID属性。

第二,我不知道如何临时绑定和存储Model.ContractCurrencyClauses,以便在用户提交主表单时传递整个集合。

剑道内联编辑与IEnumerable模型属性

EDIT 2:

ContractsController

 public class ContractsController : Controller
    {
        //
        // Static variables for Demo only
        static ContractModel model;
        static ICollection<ContractCurrencyClause> tmpContractCurrencyClauses { get; set; }
        public ActionResult Index()
        {
            if (model == null)
            {
             model = new ContractModel();
             tmpContractCurrencyClauses = new HashSet<ContractCurrencyClause>();
             model.ContractCurrencyClauses = tmpContractCurrencyClauses;
            }
            model.ContractCurrencyClauses = tmpContractCurrencyClauses;
            return View(model);
        }
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(ContractCurrencyClause contract)
        {
            contract.CONTRACT_ID = new Guid();
            tmpContractCurrencyClauses.Add(contract);
            RouteValueDictionary routeValues = this.GridRouteValues();
            return RedirectToAction("Index", routeValues);
        }
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Update(ContractCurrencyClause contract)
        {
            tmpContractCurrencyClauses.Add(contract);
            RouteValueDictionary routeValues = this.GridRouteValues();
            return RedirectToAction("Index", routeValues);
        }
    }

Index.cshtml

@Html.HiddenFor(model=>model.ID)
@(Html.Kendo().Grid(Model.ContractCurrencyClauses)
               .Name("ContractCurrencyClauses")
               .ToolBar(toolbar => toolbar.Create())
               .Columns(columns => {
                        columns.Bound(u => u.CONTRACT_ID).Hidden(true);
                        columns.Bound(u => u.CURRENCY);
                        columns.Bound(u => u.RATE);
                        columns.Command(command => { command.Edit(); command.Destroy(); });
                        })
                        .Editable(editable => editable.Mode(GridEditMode.InLine))
                        .DataSource(dataSource => 
                                dataSource.Ajax()
                                .Model(model =>
                                {
                                    model.Id(u => u.CONTRACT_ID);
                                    //model.Id(u => u.CURRENCY);  Kendo datasource does not support composite data keys.  
                                     model.Field(u => u.CONTRACT_ID).DefaultValue(Model.ID);
                                })
                         .Create(create => create.Action("Create", "Contracts"))
                         .Update(update => update.Action("Update", "Contracts"))
                         .Destroy(destroy => destroy.Action("DestroyCurClause", "Contracts")))
                )

编辑1:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(ContractCurrencyClause contract)
    {
     ...
    }

你试过把剑道网格放在表单之外吗?

根据剑道文档

Kendo UI MVC Grid在服务器内部使用表单元素已启用编辑。这意味着小部件不能放置在另一个小部件中表单元素,因为嵌套表单不是标准兼容。

还用剑道文档验证create, update方法签名。

如果你需要一次发送所有数据,你可以像这样序列化网格

var form data = JSON.stringify(dataSource.data());

我终于找到了一个更好的解决方案,我使用InCell编辑:

  @(Html.Kendo().Grid(Model.ContractCurrencyClauses)
                          .Name("ContractCurrencyClauses")
                          .ToolBar(toolbar => { toolbar.Create(); })
                          .Columns(columns => {
                              columns.Bound(p => p.CONTRACT_ID).Hidden().ClientTemplate("#= CONTRACT_ID #" +
                                "<input type='hidden' name='ContractCurrencyClauses[#= index(data)#].CONTRACT_ID' value='#= CONTRACT_ID #' />"
                              );                                  
                              columns.Bound(p => p.CURRENCY).ClientTemplate("#= CURRENCY #" +
                               "<input type='hidden' name='ContractCurrencyClauses[#= index(data)#].CURRENCY' value='#= CURRENCY #' />"
                              ).EditorTemplateName("CurrencyDDL");
                              columns.Bound(p => p.RATE).ClientTemplate("#= RATE #" +
                               "<input type='hidden' name='ContractCurrencyClauses[#= index(data)#].RATE' value='#= RATE #' />"
                              );
                              columns.Command(command => { command.Destroy(); });
                          })
                        .Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Bottom))
                        .DataSource(dataSource => 
                            dataSource.Ajax()
                            .Model(model =>
                            {
                                model.Id(u => u.CONTRACT_ID);
                                model.Field(u => u.CONTRACT_ID).DefaultValue(Model.ID);                                   
                            })
                            .ServerOperation(false)
                            )
            )
<script>
    function index(dataItem) {
        var data = $("#ContractCurrencyClauses").data("kendoGrid").dataSource.data();
        return data.indexOf(dataItem);
    }
</script>

网格在我的主表单内,当我提交它时,我在控制器中收到ContractCurrencyClauses的整个列表。

类似的解决方案:Project