Using Html.DropDownListFor as part of a paging solution in a razor view

40 views Asked by At

I've spent hours on this, and I'm obviously missing something. Code extracts below are from a cut-down version of my actual app.

My viewmodel contains this:

public IEnumerable<SelectListItem> DisplayPageOptions { get; set; }
public string SelectedPageOption { get; set; }
            
private static SelectListItem item1 = new SelectListItem() { Text = "25", Value = "25" };
private static SelectListItem item2 = new SelectListItem() { Text = "50", Value = "50" };
private static SelectListItem item3 = new SelectListItem() { Text = "100", Value = "100" };
public SelectList selectList = new SelectList(new[] { item1, item2, item3 }, "Value", "Text", item1);

My razor view contains this:

@Html.DropDownListFor(m => m.SelectedPageOption, Model.DisplayPageOptions, "Pages to display", new { onchange = @"submit()" })

My controller contains this:

SymbolViewModel vm = SymbolViewModel.Instance;
if (vm.SelectedPageOption == null)
{
    vm.SelectedPageOption = "25";
}
vm.DisplayPageOptions = vm.selectList;
SymbolDataService service = new();
vm.Load(service);
return View(vm);

My intention is that the user selects 25, 50, or 100 from the dropdown and a corresponding number of rows is displayed. My understanding is that the Html.DropDownListFor should bind to the SelectedPageOption property, which I would then use in the ViewModel to load the correct number of rows.

However, the change in dropdown value has no effect on the SelectedPageOption property, so the page is reloaded always with the original default '25' rows - taken from the value that is set in the controller. I have tried making SelectedPageOption an Int, having seen examples on the web. I hadn't wanted to do this originally because the SelectedListItem Values have to be strings. It makes no difference. I also tried not using a singleton pattern for the viewmodel - also no effect.

The binding is not completely ineffective. Whatever default value I set in the controller, this is the value that appears in the dropdown. But the binding does not work the other way. If anyone can cast some light on what's going on, I'd appreciate it.

EDIT: What I didn't originally point out, and what turned out to be relevant, is that my controller method containing the above code is asynchronous.

1

There are 1 answers

0
MartinC On

I finally worked out what was going on. Because my controller Index method is asynchronous, I need to await the model update before reloading my viewmodel. It seems obvious now!

SymbolViewModel vm = SymbolViewModel.Instance;
await TryUpdateModelAsync(vm);