单击时 - 使 @Html.DisplayFor 成为可编辑的文本字段

Posted

技术标签:

【中文标题】单击时 - 使 @Html.DisplayFor 成为可编辑的文本字段【英文标题】:On Click - Make @Html.DisplayFor an editable text field 【发布时间】:2014-07-19 01:52:29 【问题描述】:

所以我正在玩我制作的练习网站,我想尝试一个功能,让我可以选择表中的任何数据值,对其进行编辑,然后将其保存到数据库中。

现在我有一个“编辑”按钮,它在控制器中运行自动生成的编辑方法,并且有自己的用于编辑和保存的视图,但我想在索引视图中尝试这个编辑功能(或至少将数据传递给此索引视图中的编辑函数)

这是页面现在的样子

我还有一个行扩展脚本,它显示一些我也希望可编辑的附加信息。 (都在同一个视图中)

查看Index.cshtml的代码

@model IEnumerable<WebApplication2.Entities.Movie>

@
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

<style type="text/css">
    table tr button 
        opacity: 0.5;
        float: right;
    

    table tr:hover button 
        opacity: 1;
    
</style>

<br />
<br />
<br />
<br />
<div class="panel panel-primary" style="width:100%">
    <div class="panel-heading">
        <span style="font-size: 30px; font-style:oblique"><span style="font-size:larger;"><span style="margin-right: 5px" class="glyphicon glyphicon-film"></span>Movies</span></span>
    </div>

    <div class="col-lg-offset-8 col-lg-4">
        <button type="button" style="margin:3px" class="btn btn-success btn-block" onclick="location.href='@Url.Action("Create")';return false;"><span style="font-size:larger"><span style="margin-right: 5px" class="glyphicon glyphicon-plus"></span>Add New Movie</span></button>

    </div>

    <table class="table table-striped table-hover table-responsive table-condensed">
        <tr>
            <th>
                <h4 style="font-size:x-large"><span style="font-weight:bolder">Title</span></h4>
            </th>
            <th>
                <h4 style="font-size:x-large"><span style="font-weight:bolder">Release Date</span></h4>
            </th>
            <th>
                <h4 style="font-size:x-large"><span style="font-weight:bolder">@Html.DisplayNameFor(model => model.Description)</span></h4>
            </th>
            <th>
                @using (Html.BeginForm("Index", "Movie"))
                
                    <div class="dropdown">
                        <select class="btn btn-group-lg btn-default col-lg-4" style="margin-top: 15px; height: 36px; opacity: 1" data-toggle="dropdown" name="Filter">
                            <option value="0" disabled selected>Filter By...</option>
                            <option value="1">Movie Name</option>
                            <option value="2">Description</option>
                        </select>
                    </div>

                    <input type="text" name="searchString" class="col-lg-6" style="margin-top: 16px; text-align:center; height:35px; font-size:20px" placeholder="enter text" />
                    <button type="submit" class="btn btn-group-lg btn-primary col-lg-2 glyphicon glyphicon-arrow-right" style="margin-top: 15px; height:36px; opacity:1" value="" />
                
            </th>
        </tr>

        @foreach (var item in Model)
        
            <tr>
                <td class="col-lg-2">
                    <span style="font-size: 17px;">@Html.DisplayFor(modelItem => item.Name)</span>
                </td>
                <td class="col-lg-3">
                    <span style="font-size: 17px;">@Html.DisplayFor(modelItem => item.ReleaseDate)</span>
                </td>
                <td class="col-lg-3">
                    <span style="font-size: 17px; font-style:italic">@Html.DisplayFor(modelItem => item.Description)</span>
                </td>
                <td class="col-lg-3 col-lg-offset-1">
                    <button type="button" class="btn btn-warning col-lg-4" onclick="location.href='@Url.Action("Edit", "Movie", new  id = item.ID )';return false;"><span style="margin-right: 5px" class="glyphicon glyphicon-pencil"></span>Edit</button>
                    <button type="button" class="btn btn-danger col-lg-4 col-lg-offset-4" onclick="location.href='@Url.Action("Delete", "Movie", new  id = item.ID )' ;return false;"><span style="margin-right: 5px" class="glyphicon glyphicon-trash"></span>Delete</button>
                </td>
            </tr>
            <tr>
                <td colspan="12">
                    <p style="font-size: 17px; font-style: italic; font-family: 'Roboto', sans-serif">
                        Movie ID: @Html.DisplayFor(modelItem => item.ID)
                        <br />
                        Placeholder
                    </p>
                </td>
            </tr>
        
    </table>
    <span style="font-style: italic; font-size: 15px; font-family: 'Roboto', sans-serif; padding-top:0px" />click for details</span>
</div>

<script>

    $(function () 
        $("td[colspan=12]").find("p").hide();
        $("td[colspan=12]").addClass("nopadding");

        $("tr").click(function () 
            var $target = $(this);
            var $detailsTd = $target.find("td[colspan=12]");
            if ($detailsTd.length) 
                $detailsTd.find("p").slideUp();
                $detailsTd.addClass("nopadding");
             else 
                $detailsTd = $target.next().find("td[colspan=12]");
                $detailsTd.find("p").slideToggle();
                $detailsTd.toggleClass("nopadding");
            
        );
    );

</script>
@Scripts.Render("~/bundles/myscript")

电影的控制器代码

namespace WebApplication2.Controllers

    public class MovieController : Controller
    
        private MoviesEntities db = new MoviesEntities();

        // GET: /Movie/
        public ActionResult Index(string Filter, string searchString)
        

            if (String.IsNullOrEmpty(searchString) || (Int32.Parse(Filter) == 0))
            
                return View(db.Movies.ToList());
            
            else
            
                var parameter = Int32.Parse(Filter);
                return View(db.Movies.Where(x => (parameter == 1 && x.Name.Contains(searchString)) || (parameter == 2 && x.Description.Contains(searchString))).Distinct().ToList().OrderBy(x => x.Name));
            

        

        // GET: /Movie/Details/5
        public ActionResult Details(int? id)
        
            if (id == null)
            
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            
            Movie movie = db.Movies.Find(id);
            if (movie == null)
            
                return HttpNotFound();
            
            return View(movie);
        

        // GET: /Movie/Create
        public ActionResult Create()
        
            return View();
        

        // POST: /Movie/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "ID,Name,ReleaseDate,Description")] Movie movie)
        
            if (ModelState.IsValid)
            
                db.Movies.Add(movie);
                db.SaveChanges();
                return RedirectToAction("Index");
            

            return View(movie);
        

        // GET: /Movie/Edit/5
        public ActionResult Edit(int? id)
        
            if (id == null)
            
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            
            Movie movie = db.Movies.Find(id);
            if (movie == null)
            
                return HttpNotFound();
            
            return View(movie);
        

        // POST: /Movie/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "ID,Name,ReleaseDate,Description")] Movie movie)
        
            if (ModelState.IsValid)
            
                db.Entry(movie).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            
            return View(movie);
        

        // GET: /Movie/Delete/5
        public ActionResult Delete(int? id)
        
            if (id == null)
            
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            
            Movie movie = db.Movies.Find(id);
            if (movie == null)
            
                return HttpNotFound();
            
            return View(movie);
        

        // POST: /Movie/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        
            Movie movie = db.Movies.Find(id);
            db.Movies.Remove(movie);
            db.SaveChanges();
            return RedirectToAction("Index");
        

        protected override void Dispose(bool disposing)
        
            if (disposing)
            
                db.Dispose();
            
            base.Dispose(disposing);
        
    

是的,所以通常我单击“编辑”按钮,转到新视图,然后进行更改并将其保存到数据库。但我想在索引视图中完成所有这些操作,只需单击数据本身(@Html.DisplayFor(modelItem =&gt; item.INSERT_ITEM_NAME):标题、发布日期、描述、电影 ID、占位符)并将相应的选项转换为文本字段进行编辑。

参考:在此期间我还会出现一个“保存”按钮,以实际保存将替换编辑和删除的更改,直到编辑完成。

再次,我不确定这是否完全可能,但我们将不胜感激!

【问题讨论】:

【参考方案1】:

在您的 Razor 模板中,您将需要 @Html.DisplayFor(...)@Html.EditorFor(...)。文本域应该是隐藏的,点击显示文本后,javascript 需要隐藏显示文本并显示文本域,然后设置焦点:

<span class="item-display">
    @Html.DisplayFor(modelItem => modelItem.Description)
</span>
<span class="item-field">
    @Html.EditorFor(modelItem => modelItem.Description)
</span>

一些 CSS:

.item-field: 
    display: none;

还有一些 jQuery 可以很好地衡量:

$(document.documentElement)
    .on("click", "span.item-display", function(event) 
        $(event.currentTarget)
            .hide()
            .next("span.item-field")
            .show()
            .find(":input:first")
            .focus()
            .select();
    )
    .on("keypress", "span.item-field", function(event) 
        if (event.keyCode != 13)
            return;

        event.preventDefault();

        var $field = $(event.currentTarget),
            $display = $field.prev("span.item-display");

        $display.html($field.find(":input:first").val());
        $display.show();
        $field.hide();
    );

JSFiddle:http://jsfiddle.net/A3bg6/1/

在文本字段上按 ENTER 时,它将隐藏字段并显示显示,并更新显示。

【讨论】:

非常漂亮!有什么办法让我点击其他地方并取消文本框吗?我也将尝试在此期间交换按钮(保存按钮在编辑时出现,删除按钮在不被编辑时出现) 非常感谢!最后一个问题,然后我如何将此更改传递给我的 Edit 方法?再次感谢您! 您不需要将该更改传递回您的 MVC 应用程序。您输入的表单字段会自动映射回您的 Edit 方法的 movie 参数。 当我在输入新的更改后刷新时,就像从未发生过更改...应该更新吗? 您必须编写一些 AJAX 代码才能做到这一点,或者正常提交表单。这个我留给你。 :-)

以上是关于单击时 - 使 @Html.DisplayFor 成为可编辑的文本字段的主要内容,如果未能解决你的问题,请参考以下文章

@Html.DisplayFor 的 MVC6 替代品

MVC3 Html.DisplayFor -- 是不是可以让这个控件生成一个 ID?

在 MVC5 中使用 Html.DisplayFor() 的日期格式

我想了解 @Html.DisplayFor(modelItem => item.FirstName) 中的 lambda 表达式

SQL Server 数据库集,配置集 - 但来自数据库的数据未使用 @Html.DisplayFor<>() 显示?

为啥我的 DisplayFor 没有循环通过我的 IEnumerable<DateTime>?