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

发布于 2024-11-30 02:47:09 字数 6277 浏览 0 评论 0原文

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

我一直在引用 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())
                    });
}

视图:

这有点长,但我尝试通过将“// <--- DropList Here”放置在列旁边来简化它我正在努力与.

@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 Helper:

@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;
}

I have a Telerik MVC grid, in an MVC 3 application with Razor, which is being Ajax-bound. I am now trying to add a drop list column to it, so that users can use it in edit mode, but can't figure out how. The grid displays a list of Products, and I want the drop list to contain a collection of ProductCategories, to which the Product can be associated. I've been at this for hours now and I'm out of ideas. I really hope someone here can help :)

I have been referencing a Telerik demo, which is located here.

I think the part that is hanging me up is in a help view that the demo uses. In the demo, this is called "ClientEmployee(Editor)." In my case, I've placed the helper in a file called "ProductCategoryDropList.cshtml". In this helper, I'm having a tough time getting the DropDownList to bind correctly. I think this might be because I'm not setting up the BindTo() method with the right data somehow. I've marked this point of confusion in the sample DropDownList Helper code, below, with "SomeCollectionReference," as the first parameter in a "new SelectList()" constructor call. When I try to put "Model" in that spot, I get a NullReferecne exception. When I try to access ViewBag data containing the list, I get a message similar to "the SelectList doesn't have a ProductCategoryID column," or something like that. So, I'm not sure what else to try.

I'm not sure how clear this description of my problem is, but in an effort to be complete, I've included the code that I think is relevant below.

Controller:

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())
                    });
}

View:

This is a bit long, but I've tried to simplify it by placing "// <--- DropList Here" next to the column that I am trying to work with.

@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>
}

Model:

[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 Helper:

@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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泛滥成性 2024-12-07 02:47:09

我设法解决了这个问题,但我仍然有一个问题。这是我为了让它工作而进行的更改:

在控制器中创建了一个 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 对象?我希望能够使用我的模型中的属性。但是,由于某种原因,我的模型在帮助程序文件中始终为 NULL。而且,如果我尝试将 DropDownList 代码放入网格创建代码中,则 DropDownList 根本不起作用。

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

I managed to work this out, somewhat, but I still have a question. here's what I changed to get it working:

Created a ViewData object in the controller, like this ...

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())
                    });
}

Then, I used the ViewData object in the DropDownListHelper, like this ...

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

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

My question now is ... do I have to use the ViewData object? I'd love to be able to use a property off of my model. But, for some reason my Model is always NULL inside the Helper file. And, if I try to place the DropDownList code inside the Grid creation code, the DropDownList doesn't work at all.

So, do I have any other options?

家住魔仙堡 2024-12-07 02:47:09

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

想象一下您希望每个网格行都有不同的允许值列表。在这种情况下,这个概念不可行...

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

问候,翁德雷。

Currently I'm facing same problem as you write and it is really true what Telerik guys wrote you. Partial view is pre-rendered on server (content included). This may be sufficient solution, if the list of allowed values is static, but...

...imagine that you want to have different list of allowed values for each grid row. In that case this concept is not feasible...

Since there is just one combo (per column) within grid, only one solution I found is to handle onEdit grid event where you can databind combo box to allowed values using AJAX. In grid onEdit handler you can access all data fields of proper row, so you can use them for binding purposes.

Regards, Ondrej.

愁杀 2024-12-07 02:47:09

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

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

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

I asked the good support folks at Telerik about this. Here is the answer they gave me:

The Model is null because the DropDownList partial view is rendered
for ajax editing. In that case the grid prerenders all partial view
editor templates so it can use them on the client-side. In that case
Model will be null. If you used server binding and editing the Model
would be set to the right value.

At this point, I'm going to accept this post as the answer to my question. It's unfortunate that I have to accept my own answer in this case, but ... well, I didn't get any others to choose from :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文