Telerik MVC Grid: Как использовать DropDownList в столбце? - PullRequest
2 голосов
/ 17 августа 2011

У меня есть сетка Telerik MVC в приложении MVC 3 с Razor, которая связана с Ajax.Сейчас я пытаюсь добавить столбец раскрывающегося списка, чтобы пользователи могли использовать его в режиме редактирования, но не могу понять, как это сделать.Сетка отображает список Продуктов, и я хочу, чтобы в раскрывающемся списке содержалась коллекция ProductCategories, с которой может быть связан Продукт.Я занимаюсь этим часами и у меня нет идей.Я действительно надеюсь, что кто-то здесь может помочь:)

Я ссылался на демо Telerik, которое находится здесь .

Я думаю, что часть, которая вешает меня, находится в справочном представлении, которое использует демо.В демоверсии это называется «ClientEmployee (Editor)».В моем случае я поместил помощника в файл с именем «ProductCategoryDropList.cshtml».В этом помощнике мне трудно заставить DropDownList правильно связываться.Я думаю, что это может быть потому, что я не настраиваю метод BindTo () с правильными данными как-то.Я отметил эту путаницу в приведенном ниже примере вспомогательного кода DropDownList с параметром 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" рядом со столбцом, с которым я пытаюсь работать. </p>

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

Ответы [ 3 ]

1 голос
/ 22 августа 2011

В настоящее время я сталкиваюсь с той же проблемой, что и вы, и действительно, ребята из Telerik написали вам. Частичное представление предварительно отображается на сервере (содержимое включено). Это может быть достаточным решением, если список допустимых значений является статическим, но ...

... представьте, что вы хотите иметь разные списки допустимых значений для каждой строки сетки. В этом случае эта концепция неосуществима ...

Поскольку в сетке имеется только одно комбо (на столбец), я нашел только одно решение - обработать событие сетки onEdit, где вы можете связать комбинированное поле с данными с помощью AJAX. В обработчике grid onEdit вы можете получить доступ ко всем полям данных соответствующей строки, поэтому вы можете использовать их для привязки.

С уважением, Ондрей.

1 голос
/ 18 августа 2011

Мне удалось это немного решить, но у меня все еще есть вопрос. вот что я изменил, чтобы заставить его работать:

Создан объект 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())
                    });
}

Затем я использовал объект ViewData в DropDownListHelper, как это ...

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

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

Мой вопрос сейчас таков: должен ли я использовать объект ViewData? Я хотел бы иметь возможность использовать свойство моей модели. Но по какой-то причине моя Модель всегда пуста в файле Helper. И, если я попытаюсь поместить код DropDownList в код создания Grid, DropDownList не будет работать вообще.

Итак, у меня есть другие варианты?

0 голосов
/ 20 августа 2011

Я спросил об этом хороших людей из Telerik. Вот ответ, который они дали мне:

Модель не указана, поскольку отображается частичное представление DropDownList. для редактирования AJAX. В этом случае сетка предваряет все частичное представление редактор шаблонов, чтобы он мог использовать их на стороне клиента В таком случае Модель будет нулевой. Если вы использовали привязку сервера и редактирование модели будет установлено правильное значение.

На данный момент, я собираюсь принять этот пост как ответ на мой вопрос. К сожалению, я должен принять свой собственный ответ в этом случае, но ... ну, у меня не было других вариантов на выбор:)

...