ASP.NET CORE MVC 选择标签助手 - 如何在不使用 ModelView 的情况下设置选定值
Posted
技术标签:
【中文标题】ASP.NET CORE MVC 选择标签助手 - 如何在不使用 ModelView 的情况下设置选定值【英文标题】:ASP.NET CORE MVC select tag helper - how to set selected value without using ModelView 【发布时间】:2016-09-22 20:46:04 【问题描述】:在 ASP.NET MVC Core 项目的以下代码中,Get 操作方法 Test(...)
显示的是年份的下拉列表。默认情况下,下拉列表将列表中的第一年(即 2000 年)显示为 Selected value
。如果我想在同一个列表中显示特定年份作为选定值,我该如何实现它from action method
Test(...)
不使用 ViewModel 技术?选择标记帮助程序或 DropdownList html 帮助程序的解决方案都可以 - 但必须从操作方法设置 Selected 值。
简而言之,您如何将特定年份设置为此列表中的选定值:ViewBag.YearsList = Enumerable.Range(2000, 15).Select(g => new SelectListItem Value = g.ToString(), Text = g.ToString() ).ToList();
模型:
public class BloggingContext : DbContext
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
public DbSet<Blog> Blogs get; set;
public DbSet<Post> Posts get; set;
public class Blog
public int BlogId get; set;
public string Url get; set;
public IList<Post> Posts get; set;
public class Post
public int PostId get; set;
public string Title get; set;
public string Content get; set;
public int PostYear get; set;
public int BlogId get; set;
public Blog Blog get; set;
控制器:仅显示相关的操作方法。
public class BlogsController : Controller
private readonly BloggingContext _context;
public BlogsController(BloggingContext context)
_context = context;
// GET: Blogs
public async Task<IActionResult> Index()
return View(_context.Blogs.ToList());
// GET: /Blogs/Test
[HttpGet]
public async Task<IActionResult> Test(string returnUrl = null)
ViewData["ReturnUrl"] = returnUrl;
ViewBag.YearsList = Enumerable.Range(2000, 15).Select(g => new SelectListItem Value = g.ToString(), Text = g.ToString() ).ToList();
//return View(await _context.Blogs.Include(p => p.Posts).ToListAsync());
var qrVM = from b in _context.Blogs
join p in _context.Posts on b.BlogId equals p.BlogId into bp
from c in bp.DefaultIfEmpty()
select new BlogsWithRelatedPostsViewModel BlogID = b.BlogId, PostID = (c == null ? 0 : c.PostId), Url = b.Url, Title = (c == null ? string.Empty : c.Title), Content = (c == null ? string.Empty : c.Content) ;
return View(await qrVM.ToListAsync());
// POST: /Blogs/Test
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Test(IList<BlogsWithRelatedPostsViewModel> model, string GO, int currentlySelectedIndex, string returnUrl = null)
ViewData["ReturnUrl"] = returnUrl;
ViewBag.YearsList = Enumerable.Range(2000, 15).Select(g => new SelectListItem Value = g.ToString(), Text = g.ToString() ).ToList();
if (!string.IsNullOrEmpty(GO))
var qrVM = from b in _context.Blogs
join p in _context.Posts on b.BlogId equals p.BlogId into bp
from c in bp.DefaultIfEmpty()
where c == null? true : c.PostYear.Equals(currentlySelectedIndex)
select new BlogsWithRelatedPostsViewModel BlogID = b.BlogId, PostID = (c == null ? 0 : c.PostId), Url = b.Url, Title = (c == null ? string.Empty : c.Title), Content = (c == null ? string.Empty : c.Content) ;
return View(await qrVM.ToListAsync());
else if (ModelState.IsValid)
foreach (var item in model)
var oPost = _context.Posts.Where(r => r.PostId.Equals(item.PostID)).FirstOrDefault();
if (oPost != null)
oPost.Title = item.Title;
oPost.Content = item.Content;
oPost.PostYear = currentlySelectedIndex;
oPost.BlogId = item.BlogID; //according to new post below the blogId should exist for a newly created port - but just in case
else
if (item.PostID == 0)
Post oPostNew = new Post BlogId = item.BlogID, Title = item.Title, Content = item.Content, PostYear = currentlySelectedIndex ; //need to use currentlySelectedIndex intead of item.FiscalYear in case of adding a record
_context.Add(oPostNew);
await _context.SaveChangesAsync();
//return RedirectToLocal(returnUrl);
return View(model);
// If we got this far, something failed, redisplay form
return View();
Test.cshtml 视图
@model IList<ASP_Core_Blogs.Models.BlogPostViewModels.BlogsWithRelatedPostsViewModel>
<div class="row">
<div class="col-md-12">
<form asp-controller="Blogs" asp-action="Test" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
@
IEnumerable<SelectListItem> yearsList = (IEnumerable<SelectListItem>)ViewBag.YearsList;
var currentlySelectedIndex = 0; // Currently selected index (usually will come from model)
<strong>Select a Post Year</strong>
<h6>Choose a year and a URL to begin:</h6>
<label>Year:</label><select asp-for="@currentlySelectedIndex" asp-items="yearsList"></select><input type="submit" class="btn btn-default" name="GO" value="GO" />
<table class="table">
<thead>
<tr>
<th></th>
<th></th>
<th>Url</th>
<th>Title</th>
<th>Content</th>
</tr>
</thead>
<tbody>
@for (int i=0; i< Model.Count(); i++)
<tr>
<td>@Html.HiddenFor(r => r[i].BlogID)</td>
<td>@Html.HiddenFor(r => r[i].PostID)</td>
<td>
@Html.TextBoxFor(r => r[i].Url)
</td>
<td>
@Html.TextBoxFor(r => r[i].Title)
</td>
<td>
@Html.TextBoxFor(r => r[i].Content)
</td>
</tr>
</tbody>
</table>
<button type="submit" class="btn btn-default">Save</button>
</form>
</div>
</div>
【问题讨论】:
【参考方案1】:由于您想避免使用视图模型,因此不能使用DropDownListFor
,但可以使用DropDownList
@Html.DropDownList("fieldname", new SelectList(ViewBag.YearsList, ViewBag.SelectedYear))
【讨论】:
【参考方案2】:您可以在action方法中设置选择值如下:
ViewBag.YearsList = Enumerable.Range(2000, 15)
.Select(g => new SelectListItem
Value = g.ToString(),
Text = g.ToString(),
Selected = (g == currentlySelectedIndex)
).ToList();
这仅在您未绑定到模型时才有效:
<select name="selectedYear" asp-items="yearsList"></select>
【讨论】:
【参考方案3】:您可以解决此声明列表并为一个特定项目设置 Selected 值,您可以通过任何方式(linq、索引等)获取该项目。
示例代码:
var list = Enumerable.Range(2000, 15).Select(g => new SelectListItem Value = g.ToString(), Text = g.ToString() ).ToList();
// Select the item using index reference, this line selects '2010' item
list[10].Selected = true;
ViewBag.YearsList = list;
【讨论】:
使用您的建议,当我单击视图上的GO
按钮时,ViewBag.YearsList
没有更改所选值。例如,对于一个测试,我从下拉列表中选择年份为 2005 年,并在发布视图发送的模型时单击 Go
按钮,它仍将 2005 显示为选定值,而不是在 POST 操作中设置的 2010方法Test(...)
您可以通过 url 参数发送选择的年份 y 通过 ViewBag 返回值以上是关于ASP.NET CORE MVC 选择标签助手 - 如何在不使用 ModelView 的情况下设置选定值的主要内容,如果未能解决你的问题,请参考以下文章
使用标签助手调用控制器,包括来自 asp.net core mvc 中搜索栏的数据