0

我正在尝试使用 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);
    } 
4

2 回答 2

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
}

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

在我的网格中,我将 CategoryId 上的绑定更改为 CategoryName 上的绑定。在我的解决方案中,我只在视图中引用了类别名称,并且只是在控制器的读取/更新函数中将 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 中的一些内容以执行反向 Name->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 的人好运,我希望这个示例对您有所帮助!

于 2014-05-02T14:19:54.840 回答
0

可为空的 CatId 是问题所在。在此处查看内联 Kendo MVC 网格内的 Kendo MVC 下拉列表的修复。接下来是第二个选项,但这个选项仅适用于 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);
        }
    })
}

还有一个使用默认值的建议,但它从未对我有用。看这里

于 2014-11-21T20:48:12.777 回答