简体   繁体   English

结合@ html.Editor for Razor中的多个属性

[英]Combine multiple properties in @html.Editorfor Razor

We have to combine multiple properties into one EditorFor field in a Razor view. 我们必须将多个属性组合到Razor视图中的一个EditorFor字段中。

We have the properties Quantity, UnitOfMeasure and Ingredient. 我们具有属性Quantity,UnitOfMeasure和成分。 These need to be combined so the user can just type what he or she needs ie 10 kg potatoes, instead of entering the information into multiple fields. 需要将这些内容组合起来,以便用户只需键入他或她需要的内容(即10公斤土豆),而不必将信息输入多个字段。

Once this is done, we also need autocomplete on the UOM and ingredient properties. 完成此操作后,我们还需要自动完成UOM和成分属性。

I have created a partial view for this code. 我已经为此代码创建了局部视图。

@model IEnumerable<RecipeApplication.Models.RecipeLine>
<div class="form-group">
    @Html.Label("Ingrediënten", htmlAttributes: new { @class = "control-label col-md-2" })
    <div>
        @foreach (var item in Model)
        {

            <p>
                @Html.EditorFor(modelItem => item.Quantity, new { htmlAttributes = new { @class = "form-control-inline" } })
                @Html.EditorFor(modelItem => item.UnitOfMeasure.Abbreviation, new { htmlAttributes = new { @class = "form-control-inline" } })
                @Html.EditorFor(modelItem => item.Ingredient.Name, new { htmlAttributes = new { @class = "form-control-inline" } })
            </p>

        }
    </div>

</div>

Obviously this is not the intention. 显然这不是意图。

And this is the code for the Edit functions: 这是“编辑”功能的代码:

    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        RecipeModel recipeModel = db.Recipes.Find(id);
        if (recipeModel == null)
        {
            return HttpNotFound();
        }

        GetRecipeLines(id);

        return View(recipeModel);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "Name,Description,ImageUrl")] RecipeModel recipeModel, int?id)
    {
        if (ModelState.IsValid)
        {
            db.Entry(recipeModel).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        GetRecipeLines(id);

        return View(recipeModel);
    }

I have looked on Google and StackOverflow but I can't find a proper answer to get this done. 我查看了Google和StackOverflow,但找不到正确的答案来完成此操作。

Personally I wouldn't even know where to start at this moment. 我个人现在甚至都不知道从哪里开始。

I hope someone can help figuring this out. 我希望有人可以帮助解决这个问题。

Thanks. 谢谢。

Add a new getter property on ReceipLine 在ReceipLine上添加新的getter属性

C# 6.0 Syntax: C#6.0语法:

public string QuantityUomIngredient =>
$"{Quantity} {UnitOfMeasure?.Abbreviation ?? ""} {Ingredient?.Name ?? ""}";

Then your view should look like this 然后您的视图应如下所示

@Html.EditorFor(modelItem => item.QuantityUomIngredient ...

And then build a custom model binder to parse QuantityUomIngredient into its corresponding properties (this part should be fun to implement). 然后构建一个自定义模型联编程序,以将QuantityUomIngredient解析为其相应的属性(该部分应该很有趣地实现)。 But be sure to do a good validation on the input so you have good data to parse. 但是请确保对输入进行良好的验证,以便您可以解析良好的数据。

Thanks for the anwer Leo Nix, it surely put me into the right direction. 感谢烦恼的利奥·尼克斯(Leo Nix),它肯定使我朝着正确的方向前进。

Here is the code I wrote so far and it seems to work like a charm. 这是我到目前为止编写的代码,它看起来像是一种魅力。 (I did not include error handling yet.) (我尚未包括错误处理。)

public class RecipeLine
{
    [Key]
    public int RecipeLineId { get; set; }
    public int RecipeId { get; set; }
    public double Quantity { get; set; }
    public virtual UnitOfMeasureModel UnitOfMeasure { get; set; }
    public virtual IngredientModel Ingredient { get; set; }
    public string QuantityUomIngredient => $"{Quantity} {UnitOfMeasure?.Abbreviation ?? ""} {Ingredient?.Name ?? ""}";
}

And the custom Binder I wrote. 还有我写的自定义活页夹。 This one took quite some extra research. 这项研究花了很多额外的时间。

 class RecipeLineCustomBinder : DefaultModelBinder
    {
        private RecipeApplicationDb db = new RecipeApplicationDb();

        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            HttpRequestBase request = controllerContext.HttpContext.Request;

            // Get the QuantityCustomIngredient from the webform. 
            string quantityUomIngredient = request.Form.Get("QuantityUomIngredient");
            // Get the IngredientID from the webform.
            int recipeID = int.Parse(request.Form.Get("RecipeId"));
            // Split the QuantityCustomIngredient into seperate strings. 
            string[] quantityUomIngredientArray = quantityUomIngredient.Split();
            //string[] quantityUomIngredientArray = quantityUomIngredient.Split(new string[] { " " }, 2, StringSplitOptions.RemoveEmptyEntries);

            if (quantityUomIngredientArray.Length >= 3)
            {
                // Get the quantity value
                double quantityValue;
                bool quantity = double.TryParse(quantityUomIngredientArray[0], out quantityValue);

                // Get the UOM value. 
                string uom = quantityUomIngredientArray[1];
                UnitOfMeasureModel unitOfMeasure = null;
                bool checkUOM = (from x in db.UnitOfMeasures
                                 where x.Abbreviation == uom
                                 select x).Count() > 0;
                if (checkUOM)
                {
                    unitOfMeasure = (from x in db.UnitOfMeasures
                                     where x.Abbreviation == uom
                                     select x).FirstOrDefault();
                }

                // Get the ingredient out of the array.
                string ingredient = "";
                for (int i = 2; i < quantityUomIngredientArray.Length; i++)
                {
                    ingredient += quantityUomIngredientArray[i];
                    if (i != quantityUomIngredientArray.Length - 1)
                    {
                        ingredient += " ";
                    }
                }

                bool checkIngredient = (from x in db.Ingredients where x.Name == ingredient select x).Count() > 0;
                IngredientModel Ingredient = null;
                if (checkIngredient)
                {
                    Ingredient = (from x in db.Ingredients
                                  where x.Name == ingredient
                                  select x).FirstOrDefault();
                }

                // Return the values. 
                return new RecipeLine
                {
                    Quantity = quantityValue,
                    UnitOfMeasure = unitOfMeasure,
                    Ingredient = Ingredient,
                    RecipeId = recipeID
            };
            }
            else
            {
                return null;
            }

        }
    }

In the Razor view this is the code that I used: 在Razor视图中,这是我使用的代码:

    <div class="form-group">
        @Html.LabelFor(model => model.QuantityUomIngredient, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.QuantityUomIngredient, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.QuantityUomIngredient, "", new { @class = "text-danger" })
        </div>
    </div>

I added the custom binder in Global.asax.cs 我在Global.asax.cs中添加了自定义活页夹

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        ModelBinders.Binders.Add(typeof(RecipeLine), new RecipeLineCustomBinder());
    }
}

And finally added the custom binder to the controller 最后将自定义资料夹添加到控制器

    [HttpPost]
    public ActionResult Create([ModelBinder(typeof(RecipeLineCustomBinder))] RecipeLine recipeLine)
    {
        if (ModelState.IsValid)
        {
            db.RecipeLines.Add(recipeLine);
            db.SaveChanges();
            return RedirectToAction("Index", new { id = recipeLine.RecipeId });
        }
        return View(recipeLine);
    }

I hope this will help other developers as well. 我希望这也会对其他开发人员有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM