网格中的Kendo UI DropDownList外键

时间:2014-04-30 20:42:17

标签: asp.net-mvc kendo-grid html-helper kendo-dropdown

我正在尝试使用HTML帮助程序在Kendo UI Grid中设置下拉列表 当我单击编辑网格时,会出现下拉列表,我可以选择一个值。但是,当我单击更新时,这不会保存在数据库中(尽管简单的字符串WordName字段可以) 我还希望WordViewModel中的CatId值在您不编辑字段时也显示为单词/下拉列表。

据我所知,我没有将int CatId链接到GetCategories列表的内容。我该如何连接这两个?我已经阅读了一些关于column.ForeignKey的内容,但我不明白。以下是我的所有相关代码。

我的WordViewModel(从类似的,稍微复杂的数据库模型加载)

public class WordViewModel
{
    public int WordId { get; set; }
    [Required]
    public string WordName { get; set; }
    public Nullable<int> CatId { get; set; }
}

我的分类模型(由数据库生成)

public partial class Category
{
    public Category()
    {
        this.Words = new HashSet<Word>();
    }

    public int CatId { get; set; }
    public string CategoryName { get; set; }
    public bool IsActive { get; set; }

    public virtual ICollection<Word> Words { get; set; }
}

这是我在Index.cshtml中的网格剃刀代码

@(Html.Kendo().Grid<WordViewModel>
    ()
    .Name("wordGrid")
    .DataSource(dataSource => dataSource
        .Ajax()
        .Model(model =>
        {
            model.Id(word => word.WordId); // Specify the property which is the unique identifier of the model
            model.Field(word => word.WordId).Editable(false); // Make the ID property not editable
        })
        .Read(read => read.Action("Read", "Words"))  //Populate the grid with Words
        .Update(update => update.Action("Update", "Words"))  // Action invoked when the user saves an updated data item
    )
    .Editable(editable => editable.Mode(GridEditMode.InLine)) // Use inline editing mode
    .Columns(columns =>
    {
        columns.Bound(c => c.WordName);
        columns.Bound(c => c.CatId).EditorTemplateName("_CategoryDropdown");  //link to EditorTemplate with the same name
        columns.Command(commands =>
        {
            commands.Edit(); // The "edit" command will edit and update data items
        }).Title("Commands").Width(200);
    })
    .Filterable()
)

编辑模板_CategoryDropdown.cshtml

@(
 Html.Kendo().DropDownList()
                   .Name("Category")  //is this Name important?
                   .DataTextField("CategoryName")
                   .DataValueField("CategoryId")
                   .DataSource(source =>
                   {
                       source.Read(read => { read.Action("GetCategories", "Words"); });
                   })
                   .OptionLabel("Select a category")
)

我的功能是从数据库中获取下拉列表。

    public JsonResult GetCategories()
    {
        var items = db.Categories.ToList().Select(c => new Category
        {
            CatId = c.CatId,
            CategoryName = c.CategoryName
        });
        return Json(items, JsonRequestBehavior.AllowGet);
    } 

2 个答案:

答案 0 :(得分:1)

这是一个有效的解决方案。我没有使用column.ForeignKey,而是最终手动将CatId与CategoryName连接,并在WordViewModel中包含两者。

我的最终档案:

public class WordViewModel
{
    public int WordId { get; set; }
    [Required]
    public string WordName { get; set; }
    public string CategoryName { get; set; }  //I added this field which is actually displayed on the grid
    public Nullable<int> CatId { get; set; }  //only used temporarily to transfer data
}

我几乎没有最终引用类别模型。

在我的网格中,我将CategoryId上的绑定更改为在CategoryName上绑定。基本上在我的解决方案中,我只在视图中引用了Category Name,并且只是在控制器的Read / Update函数中将CategoryName与CategoryId匹配。

//The Title string below needs to be the same as the Name field in the EditorTemplate and possibly the same as the name in the model
columns.Bound(c => c.CategoryName).Title("CategoryName").EditorTemplateName("_CategoryDropdown");  

此文件的位置很重要。 查看/共享/ EditorTemplates / _CategoryDropdown.cshtml:

@(
 Html.Kendo().DropDownList()
    .Name("CategoryName")  //This name has to be the same as the Title on the main grid page
    .DataTextField("CategoryName")
    .DataValueField("CategoryName")
    .DataSource(source =>
    {
       source.Read(read => { read.Action("GetCategories", "Words"); });
    })
    .OptionLabel("Select a category")
)

Words / GetCategories功能正确。

我必须在Words / Read中做一些工作才能从类别ID中获取类别名称

    public ActionResult Read([DataSourceRequest] DataSourceRequest request)
    {
        var items = db.Words.Select(w => new WordViewModel
        {
            WordId = w.WordId,
            CatId = w.CatId,
            CategoryName = "",
            WordName = w.WordName
        }).ToList();  //need .ToList to be able to iterate through it
        //finish building the word
        foreach(var item in items)
        {
            if(item.CatId!=null)
            {
                //add CategoryName corresponding to each CatId
                //In my database I have a table for Categories which matches up CatId to CategoryName
                Category cat = db.Categories.Select(c => c).Where(c => c.CatId == item.CatId).FirstOrDefault();
                item.CategoryName = cat.CategoryName;
            }
        }
        return Json(items.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
    }

和Words / Update中的一些东西做反向名称 - &gt; Id:

public ActionResult Update([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")] WordViewModel word)
{
    if (ModelState.IsValid)
    {
        // Create a new Product entity and set its properties from the posted ProductViewModel
        var entity = new Word 
        {
            WordId = word.WordId,
            CategoryName = word.CategoryName,
            WordName = word.WordName
        };

        if (word.CategoryName != "")
        {
            //match CategoryWord to CatID
            Category cat = db.Categories.Select(c => c).Where(c => c.CategoryName == word.CategoryName).FirstOrDefault();
            entity.CatId = cat.CatId;
        }

        // Attach the entity
        db.Words.Attach(entity);
        // Change its state to Modified so Entity Framework can update the existing product instead of creating a new one
        db.Entry(entity).State = EntityState.Modified;
        // Update the entity in the database
        db.SaveChanges();
    }
    // Return the updated product. Also return any validation errors.
    return Json(new [] { word }.ToDataSourceResult(request, ModelState));
}

可能会有一些小错误,因为这与我的真实代码相比有点简化,但所有重要的部分都在那里。弄清楚所有的联系以及我可以依靠剑道进行与我手动操作相比我很难弄明白。祝所有试图使用Kendo Grid的人好运,我希望这个例子有所帮助!

答案 1 :(得分:0)

Nullable CatId就是问题所在。在这里查看修复Kendo MVC dropdown lists inside inline Kendo MVC grids。第二个选项如下,但这个选项仅适用于InLine。

function onSave(e) {
    // kendo nullable dropdown bug workaround
    $("#wordGrid tbody [data-role=dropdownlist]").each(function () {
        var kd = $(this).data("kendoDropDownList");
        if (kd) {
            var v = kd.value();
            var p = kd.list.attr('id').replace('-list', '');
            if(p) e.model.set(p, v);
        }
    })
}

还有一个建议使用默认值,但它从来没有对我有用。 see here