This is a migrated thread and some comments may be shown as answers.

ASP.NET MVC Razor Grid with editable foreign key dropdown column

9 Answers 636 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Erwin
Top achievements
Rank 1
Erwin asked on 31 May 2012, 03:26 AM
Hi all,

I am trying to create an Ajax Telerik grid in Razor that has an updateable foreign key column that shows a dropdown list. I've copied my page pretty much like the example, and everything works. I can add new records, delete them and edit them. The only thing that doesn't work is that I get a textfield with the integer when I update a record in my grid, instead of a dropdown list with all the possibilities of the foreign key table.

Anyone have any ideas on how I could fix this? See code below.

Telerik grid:
@(Html.Telerik().Grid<EditableAccount>()
    .Name("Grid")
    .ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Text).ImageHtmlAttributes(new { style = "margin-left:0" }))
    .DataBinding(dataBinding => dataBinding.Ajax()
        .Insert("InsertAccount", "Administration")
        .Update("SaveAccount", "Administration")
        .Delete("DeleteAccount", "Administration"))
    .DataKeys(keys => { keys.Add(a => a.AccountId); })
    .Columns(columns =>
    {
        columns.ForeignKey(b => b.BankId, (IEnumerable)ViewData["Banks"], "ID", "Name").Width(50);
        columns.Bound(a => a.AccountNumber).Width(110);
        columns.Command(commands =>
        {
            commands.Edit().ButtonType(GridButtonType.Image);
            commands.Delete().ButtonType(GridButtonType.Image);
        }).Width(16);
    })
    .Editable(editing => editing.Mode(GridEditMode.InLine))
    .Pageable()
    .Scrollable()
    .Sortable()
)

Controller:
[GridAction]
public ActionResult Accounts()
{
    ViewData["Banks"] = db.Banks.Select(b => new { Id = b.BankId, Name = b.Name });
    return View(new GridModel(accountRepository.All()));
}
 
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult InsertAccount()
{
    //Create a new instance of the EditableProduct class.
    EditableAccount account = new EditableAccount();
 
    //Perform model binding (fill the product properties and validate it).
    if (TryUpdateModel(account))
    {
        //The model is valid - insert the product.
        accountRepository.Insert(account);
    }
 
    //Rebind the grid
    return View(new GridModel(accountRepository.All()));
}
 
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult SaveAccount(int id, int bankId)
{
    EditableAccount account = new EditableAccount
    {
        AccountId = id,
        Bank = db.Banks
                   .Where(b => b.BankId == bankId)
                   .Select(b => b.Name).SingleOrDefault(),
        BankId = bankId
    };
 
    TryUpdateModel(account);
 
    accountRepository.Update(account);
 
    return View(new GridModel(accountRepository.All()));
}
 
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult DeleteAccount(int id)
{
    //Find a customer with ProductID equal to the id action parameter
    EditableAccount account = accountRepository.One(a => a.AccountId == id);
 
    if (account != null)
    {
        //Delete the record
        accountRepository.Delete(account);
    }
 
    //Rebind the grid
    return View(new GridModel(accountRepository.All()));
}

Model:
public class EditableAccount
{
    [ScaffoldColumn(false)]
    public int AccountId { get; set; }
 
    [Required]
    [UIHint("GridForeignKey")]
    [DisplayName("Bank")]
    public int BankId { get; set; }
    public string Bank { get; set; }
 
    [Required]
    [DisplayName("AccountNumber")]
    public int AccountNumber { get; set; }
}


Repository:

public IList<EditableAccount> All()
{
    IList<EditableAccount> result =
            (from account in db.Accounts
             select new EditableAccount
             {
                 AccountId = account.AccountId,
                 Bank = account.Bank.Name,
                 BankId = account.BankId,
                 AccountNumber = account.AccountNr
             }).ToList();
 
    return result;
}
 
/// <summary>
/// Ones the specified predicate.
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
public EditableAccount One(Func<EditableAccount, bool> predicate)
{
    return All().Where(predicate).FirstOrDefault();
}
 
/// <summary>
/// Inserts the specified account.
/// </summary>
/// <param name="account">The account.</param>
public void Insert(EditableAccount insertedAccount)
{
    Account account = new Account();
    account.BankId = insertedAccount.BankId;
    account.AccountNr = insertedAccount.AccountNumber;
    db.Accounts.InsertOnSubmit(account);
    db.SubmitChanges();
}
 
/// <summary>
/// Updates the specified account.
/// </summary>
/// <param name="account">The account.</param>
public void Update(EditableAccount updatedAccount)
{
    Account account = db.Accounts.SingleOrDefault(a => a.AccountId == updatedAccount.AccountId);
    account.BankId = updatedAccount.BankId;
    account.AccountNr = updatedAccount.AccountNumber;
    db.SubmitChanges();
}
 
/// <summary>
/// Deletes the specified account.
/// </summary>
/// <param name="account">The account.</param>
public void Delete(EditableAccount deletedAccount)
{
    Account account = db.Accounts.SingleOrDefault(a => a.AccountId == deletedAccount.AccountId);
    db.Accounts.DeleteOnSubmit(account);
    db.SubmitChanges();
}

9 Answers, 1 is accepted

Sort by
0
Joel
Top achievements
Rank 1
answered on 31 May 2012, 09:26 PM
+1 for this.   I'm having exact same problem with the same code structure. 
0
Douglas
Top achievements
Rank 1
answered on 01 Jun 2012, 05:49 PM
i'm having the same problem..

did you figure this out?

i don't think something this straightforward should be so difficult to implement..

in webforms with a gridview it was a pretty easy thing to do..not so here.
0
Accepted
Joel
Top achievements
Rank 1
answered on 01 Jun 2012, 07:14 PM
Solved the problem (at least for me):

Just copy the GridForeignKey.cshmtl file (on my computer it is under "C:\Program Files (x86)\Telerik\Extensions for ASP.NET MVC Q1 2012\EditorTemplates-Razor") to your project. Put it under "Views\Shared\EditorTemplates" folder (create it if you have to).

Apparently there are also currency, datetime, integer, etc. templates also, you can copy those as well to automatically use those formats.


0
Douglas
Top achievements
Rank 1
answered on 01 Jun 2012, 07:27 PM
That's IT!

Thanks!!

0
Erwin
Top achievements
Rank 1
answered on 04 Jun 2012, 10:02 PM
Thanks a lot! That solved my problem! :D
0
Phil
Top achievements
Rank 1
Veteran
Iron
answered on 28 May 2020, 01:42 PM

I was having this issue for a few hours.

I was going in circles following a few tutorials with no luck such as 

https://docs.telerik.com/aspnet-mvc/html-helpers/data-management/grid/templates/editor-templates?_ga=2.10332085.162479736.1590480235-1736843189.1576230525

I got to the stage where I could get it to render either a dropdown, but the data was not passed back, or the data passing as it was not a dropdown.

Thought I would post here i to say thank you as creating the foreign key file seemed to fix it for me.

I don't have the files on my local directory but if you create the file manually as the link below says

https://demos.telerik.com/aspnet-mvc/grid/foreignkeycolumn

@model object
@(Html.Kendo().DropDownListFor(m => m)
    .BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
it magically works.

I created a partial view with no model within Razor.

I'll have to grab the files or go looking for the other datatypes.

Thanks

0
Raja Patukuri
Top achievements
Rank 1
answered on 02 Sep 2020, 03:05 PM

Phil,

foreignkeycolumn worked for me too. It shows drop-downs in the inline editor in both create and edit options but the issue for me is, in edit mode, it is not returning updated values from the drop-downs to the controller update action method but previous (data before editing) data.

I am following https://demos.telerik.com/aspnet-core/grid/foreignkeycolumn

Any idea about it?

 

0
Phil
Top achievements
Rank 1
Veteran
Iron
answered on 02 Sep 2020, 03:50 PM

Hi

To get mine working I have a model with a DropDownViewModel.

This has a SelectedId, Value and name

Something like:

public class DropdownViewModel
{
   public int Value {get;set;}
   public int SelectedId {get;set;}
    public string NameValue {get;set;}
}

 

I load the data I want in the dropdown and put it into the viewData as am IEnumurable. So in my "Index.cshtml".
Something like

 

private async Task CreateListItems()
{
     List<DropdownViewModel> dropdownValues = new List<DropdownViewModels>();
 
       for(int i = 0; i<5; i ++)
       {
               dropdownValues.add(new DropdownViewModel(i,i.toString());
       }

 

        ViewData["dropdown"] = dropdownValues;

}

 

This just gives the number 1 to 5 with the value and label as an example.

Then in the actual grid the foreign key column looks something like this:

x.ForeignKey(f => f.Dropdown.SelectedId, (System.Collections.IEnumerable)ViewData["dropdown"],"SelectedId""Value")
                    .Title("Title");

Make sure the names in the strings match the value of the model. 

 

When you pass back the edited version it should have two fields. One with the old value that was displayed, and one with the new selected value.

Hope this helps.

 

0
Raja Patukuri
Top achievements
Rank 1
answered on 02 Sep 2020, 04:46 PM

Phil,

I just passed IEnumerable type data insread of list to drop-down and did not make any changes to the code, worked. Thank you for the explanation though.

Tags
Grid
Asked by
Erwin
Top achievements
Rank 1
Answers by
Joel
Top achievements
Rank 1
Douglas
Top achievements
Rank 1
Erwin
Top achievements
Rank 1
Phil
Top achievements
Rank 1
Veteran
Iron
Raja Patukuri
Top achievements
Rank 1
Share this question
or