Telerik MVC Grid:如何在列中使用 DropDownList?

Posted

技术标签:

【中文标题】Telerik MVC Grid:如何在列中使用 DropDownList?【英文标题】:Telerik MVC Grid: How to use DropDownList in a column? 【发布时间】:2011-10-28 14:08:12 【问题描述】:

我有一个 Telerik MVC 网格,在一个带有 Razor 的 MVC 3 应用程序中,它是 Ajax 绑定的。我现在正在尝试向其中添加一个下拉列表列,以便用户可以在编辑模式下使用它,但不知道如何。网格显示产品列表,我希望下拉列表包含 ProductCategories 的集合,Product 可以关联到这些集合。我已经在这几个小时了,我没有想法。我真的希望这里有人可以提供帮助:)

我一直在参考位于 here 的 Telerik 演示。

我认为困扰我的部分是演示使用的帮助视图。在演示中,这称为“ClientEmployee(Editor)”。就我而言,我已将帮助程序放在一个名为“ProductCategoryDropList.cshtml”的文件中。在这个助手中,我很难让 DropDownList 正确绑定。我认为这可能是因为我没有以某种方式使用正确的数据设置 BindTo() 方法。我在下面的示例 DropDownList Helper 代码中标记了这个混淆点,其中“SomeCollectionReference”作为“new SelectList()”构造函数调用中的第一个参数。当我尝试将“模型”放在那个位置时,我得到一个 NullReferecne 异常。当我尝试访问包含该列表的 ViewBag 数据时,我收到类似于“SelectList 没有 ProductCategoryID 列”或类似内容的消息。所以,我不确定还能尝试什么。

我不确定对我的问题的描述是否清楚,但为了完整起见,我在下面包含了我认为相关的代码。

控制器:

public ActionResult Index()

    ViewBag.ProductCategories = new SelectList(_productCategoryService.GetActiveProductCategories(), "ProductCategoryID", "ProductcategoryName");
    var products = _productService.GetProducts().ToList();
    var presentationModel = _mapper.MapAsList(products);
    return View(presentationModel);


//
// GET: /Product/
[GridAction]
public ViewResult _Index()

    ViewBag.ProductCategories = new SelectList(_productCategoryService.GetActiveProductCategories(), "ProductCategoryID", "ProductcategoryName");
    return View(new GridModel<ProductPresentationModel>
                    
                        Data = _mapper.MapAsList(_productService.GetProducts().ToList())
                    );

查看:

这有点长,但我尝试通过在我要使用的列旁边放置“//

@model IEnumerable<Models.PresentationModels.ProductPresentationModel>

@(Html.Telerik().Grid(Model).HtmlAttributes(new  style = "width: 100%;" )
        // Give the Grid an HTML id attribute value
        .Name("ProductGrid")
        // Establish the promiry key, to be used for Insert, Update, and Delete commands
        .DataKeys(dataKeys => dataKeys.Add(p => p.ProductID))
        // Add an Insert command to the Grid Toolbar
        .ToolBar(commands => commands.Insert().ButtonType(GridButtonType.ImageAndText))
        // Using Ajax Data Binding to bind data to the grid
        .DataBinding(dataBinding => dataBinding
                // Ajax Binding
                .Ajax()
                    .Select("_Index", "Product")
                    // Home.Insert inserts a new data record
                    .Insert("Create", "Product")
                    // Home.Update updates an existing data record
                    .Update("Edit", "Product")
                    // Home.Delete deletes an existing data record
                    .Delete("Delete", "Product")
        )
        .Columns(columns =>
        
            columns.Bound(p => p.ProductName).Width(120);
            columns.Bound(p => p.ProductDescription).Width(150);
            columns.Bound(p => p.PricePerMonth).Width(120);
            columns.Bound(p => p.ProductImagePath).Width(150)
            columns.Bound(p => p.ProductActive).Width(120)
                .ClientTemplate("<input type='checkbox' disabled='disabled' name='Active' <#= ProductActive ? checked='checked' : '' #> />");
            columns.Bound(p => p.ProductCategoryName); // <--- DropList Here
            columns.Command(commands =>
            
                commands.Edit().ButtonType(GridButtonType.Image);
                commands.Delete().ButtonType(GridButtonType.Image);
            );
        )
        .Editable(editing => editing.Mode(GridEditMode.PopUp))
        .ClientEvents(events => events.OnEdit("onEdit"))
        .Pageable()
        .Scrollable()
        .Sortable()
        .Filterable()
)

@section HeadContent 
    <script type="text/javascript">
        function onEdit(e) 
            $(e.form).find('#ProductCategoryName').data('tDropDownList').select(function (dataItem) 
                return dataItem.Text == e.dataItem['ProductCategoryName'];
            );
        
    </script>

型号:

[DisplayName(@"Category Name")]
[UIHint("ProductCategoryDropList"), Required]
[StringLength(255, ErrorMessage = @"Product Category Name cannot be more than 255 characters in length")]
public string ProductCategoryName

    get 
       
        string name = string.Empty;

        if (_model.ProductCategory != null)
        
            name = _model.ProductCategory.ProductCategoryName;
        

        return name;
    
    set 
    
        if (_model.ProductCategory != null)
        
            _model.ProductCategory.ProductCategoryName = value;
        
    

DropList 助手:

@model Models.PresentationModels.ProductPresentationModel

@(Html.Telerik().DropDownList()
        .Name("ProductCategoryName")
            .BindTo(new SelectList(<SomeCollectionReference>, "ProductCategoryID", "ProductCategoryName"))
)

ProductMapper:

public List<ProductPresentationModel> MapAsList(List<Product> products)

    //var categoryList = new SelectList(_productCategoryService.GetProductCategories().ToList(), "ProductCategoryID", "ProductCategoryName"); 

    var presentationModels = products
            .Select(x => new ProductPresentationModel()
            
                ProductID = x.ProductID,
                ProductCategoryID = ((x.ProductCategory != null) ? x.ProductCategory.ProductCategoryID : 0),
                ProductCategoryName = ((x.ProductCategory != null) ? x.ProductCategory.ProductCategoryName : String.Empty),
                ProductName = x.ProductName,
                ProductDescription = x.ProductDescription,
                PricePerMonth = x.PricePerMonth,
                ProductImagePath = x.ProductImagePath,
                ProductActive = x.ProductActive,
                ProductCategories = new SelectList(_productCategoryService.GetProductCategories().ToList(), "ProductCategoryID", "ProductCategoryName")//categoryList
            ).ToList();

    return presentationModels;

【问题讨论】:

【参考方案1】:

我设法解决了这个问题,但我仍然有一个问题。这是我为使其正常工作所做的更改:

在控制器中创建了一个 ViewData 对象,像这样...

public ActionResult Index()

    // ViewData object here ...
    ViewData["ProductCategories"] = new SelectList(_productCategoryService.GetActiveProductCategories(), "ProductCategoryID", "ProductCategoryName");
    var products = _productService.GetProducts().ToList();
    var presentationModel = _mapper.MapAsList(products);
    return View(presentationModel);


//
// GET: /Product/
[GridAction]
public ViewResult _Index()

    // ViewData object here ...
    ViewData["ProductCategories"] = new SelectList(_productCategoryService.GetActiveProductCategories(), "ProductCategoryID", "ProductCategoryName");
    return View(new GridModel<ProductPresentationModel>
                    
                        Data = _mapper.MapAsList(_productService.GetProducts().ToList())
                    );

然后,我在DropDownListHelper中使用了ViewData对象,像这样……

@using System.Collections
@model Models.PresentationModels.ProductPresentationModel

@(Html.Telerik().DropDownList()
        .Name("ProductCategoryName")
        .BindTo(new SelectList((IEnumerable)ViewData["ProductCategories"], "Value", "Text"))
);

我现在的问题是……我必须使用 ViewData 对象吗?我希望能够使用我的模型中的属性。但是,由于某种原因,我的模型在 Helper 文件中始终为 NULL。而且,如果我尝试将 DropDownList 代码放在 Grid 创建代码中,DropDownList 根本不起作用。

那么,我还有其他选择吗?

【讨论】:

【参考方案2】:

目前,我面临与您所写相同的问题,Telerik 人写给您的确实是真的。部分视图在服务器上预渲染(包括内容)。如果允许的值列表是静态的,这可能是足够的解决方案,但是...

...假设您希望为每个网格行设置不同的允许值列表。在那种情况下,这个概念是不可行的......

由于网格中只有一个组合(每列),我发现只有一个解决方案是处理 onEdit 网格事件,您可以使用 AJAX 将组合框数据绑定到允许的值。在网格 onEdit 处理程序中,您可以访问正确行的所有数据字段,因此您可以将它们用于绑定目的。

问候,翁德雷。

【讨论】:

很好的信息,Ondrej。您是否可以用一两个示例更新这篇文章,说明您所描述的内容?【参考方案3】:

我就此询问了 Telerik 的优秀支持人员。这是他们给我的答案:

Model 为 null,因为渲染了 DropDownList 部分视图 用于 ajax 编辑。在这种情况下,网格会预先呈现所有部分视图 编辑器模板,以便它可以在客户端使用它们。在这种情况下 模型将为空。如果您使用服务器绑定和编辑模型 将被设置为正确的值。

此时,我将接受这篇文章作为我问题的答案。不幸的是,在这种情况下我不得不接受自己的答案,但是……好吧,我没有其他人可以选择:)

【讨论】:

以上是关于Telerik MVC Grid:如何在列中使用 DropDownList?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Telerik Grid 中为 ASP.NET MVC 绑定图像

Telerik/ Kendo MVC Grid,按需加载网格,而不是页面加载

Telerik MVC Extensions Grid - 如何让网格过滤器应用于初始 LINQ 查询或传递给 db?

Telerik MVC Grid Ajax 手动绑定

asp.net MVC 4 Telerik Grid Ajax 问题

Telerik Kendo Grid (MVC) 更新后刷新