【问题标题】:Kendo UI DropDownList ForeignKey in GridKendo UI DropDownList ForeignKey in Grid
【发布时间】:2014-04-30 20:42:16
【问题描述】:

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

【问题讨论】:

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


    【解决方案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 的人好运,我希望这个示例对您有所帮助!

    【讨论】:

      【解决方案2】:

      可空的 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

      【讨论】:

        猜你喜欢
        • 2021-11-18
        • 2013-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-10
        相关资源
        最近更新 更多