简体   繁体   English

嵌套编辑器模板问题 asp.net mvc

[英]Nested Editor Templates issue asp.net mvc

I see this answer from 7 years ago.我从 7 年前看到了这个答案 Just wondering if there have been any changes or work arounds to get this to work.只是想知道是否有任何更改或解决方法可以使其正常工作。

Problem问题

We are trying to "extend" a Kendo DropDownList editor template by creating specific editor templates that set a minimum set of unique attributes, then passes that info to the base Kendo DropDownList editor template to help keep things DRY.我们试图通过创建特定的编辑器模板来“扩展” Kendo DropDownList 编辑器模板,这些模板设置了一组最小的唯一属性,然后将该信息传递给基本的 Kendo DropDownList 编辑器模板以帮助保持干燥。 (I mean, that is a core principle in development so to see the tools not allow it is a bit puzzling.) (我的意思是,这是开发中的核心原则,所以看到工具不允许它有点令人费解。)

But it seems the model type details are lost when calling the Base editor via Html.Partial .但是,通过Html.Partial调用基本编辑器时,似乎 model 类型详细信息丢失了。 And using a truly nested Html.EditorFor within an editor template doesn't work either.在编辑器模板中使用真正嵌套的Html.EditorFor也不起作用。

For example:例如:

The model is marked as int? model 被标记为int? , but if the model value is populated, the html markup is rendered as Required. ,但如果填充了 model 值,则 html 标记呈现为必需。 If the model value is null, it is not.如果 model 值为 null,则不是。

Further, Validation Messages are genericized to the primitive type so instead of an error message like: "Account Id is required."此外,验证消息被通用化为原始类型,而不是像“需要帐户 ID”这样的错误消息。 you get "The Int32 field is required."你会得到“Int32 字段是必需的”。

Model: Model:

[Display(Name = "Expense Account")]
[UIHint("FinancialsChartOfAccounts-ExpenseEditor")]
public int? FinancialsPurchaseExpenseAccountId { get; set; }

"Derived" Editor “派生”编辑器

@{
    var editorOptionsModel = new OTIS.Domain.DDLEditorOptionsModel();
    editorOptionsModel.AreaName = "Shared";
    editorOptionsModel.ControllerName = "ManageDDLs";
    editorOptionsModel.ControllerAction = "GetChartOfAccountsExpense";
    editorOptionsModel.Width = ViewData["WidthPixels"] != null ? (string)ViewData["WidthPixels"] : null;
    editorOptionsModel.DefaultLabelText = ViewData["DefaultText"] != null ? (string)ViewData["DefaultText"] : "Select One...";
    
    ViewData["ddlEditorOptionsModel"] = editorOptionsModel;
}
@Html.Partial("~/Views/_Base/Shared/EditorTemplates/DDLEditor.cshtml", (int?)Model)

"Base" Editor: “基地”编辑:

@using Kendo.Mvc.UI;
@using Kendo.Mvc.UI.Fluent;
@{              
    //set default option values
    string strAreaName = "Shared";
    string strControllerName = "ManageDDLs";
    string strOptionLabel = "Select One...";
    string strControllerAction = (string)ViewData["ControllerAction"];
    string widthPixels = "100%";

    //check to see if any options are passed in via view data from the view
    if (ViewData["WidthPixels"] != null)
    {
        widthPixels = (string)(ViewData["WidthPixels"].ToString());
    }

    //see if a option model is passed in, and if so, use those values
    var ddlEditorOptionsModel = new OTIS.Domain.DDLEditorOptionsModel();

    if (ViewData["ddlEditorOptionsModel"] != null)
    {
        ddlEditorOptionsModel = (OTIS.Domain.DDLEditorOptionsModel)ViewData["ddlEditorOptionsModel"];
        strAreaName = ddlEditorOptionsModel.AreaName ?? strAreaName;
        strControllerName = ddlEditorOptionsModel.ControllerName ?? strControllerName;
        strControllerAction = ddlEditorOptionsModel.ControllerAction ?? strControllerAction;
        widthPixels = ddlEditorOptionsModel.Width ?? widthPixels;
        strOptionLabel = ddlEditorOptionsModel.DefaultLabelText ?? strOptionLabel;
    }

    IDictionary<string, object> htmlAttributes = new RouteValueDictionary();
    htmlAttributes["style"] = "width:" + widthPixels + ";min-width:250px;max-width:500px;";

    if (ViewData["HtmlAttributes"] != null)
    {
        htmlAttributes = Html.MergeHtmlAttributes(ViewData["HtmlAttributes"], htmlAttributes);
    }

    DropDownListBuilder builder;

    builder = Html.Kendo().DropDownListFor(model => model)
        .HtmlAttributes(htmlAttributes)
        .DataValueField("Value")
        .DataTextField("DisplayText")
        .OptionLabel(strOptionLabel)
        .Template("#= data.DisplayText.replace(' ', '&nbsp;') #");

    //set data source
    if (ddlEditorOptionsModel.Data == null)
    {
        builder.DataSource(source =>
        {
            source.Read(read =>
            {
                read.Action(strControllerAction, strControllerName, new { area = strAreaName });
            })
            .ServerFiltering(true);
        });
    }
    else
    {
        builder.BindTo(ddlEditorOptionsModel.Data);
    }

    if (ddlEditorOptionsModel.Height != null)
    {
        builder.Height(ddlEditorOptionsModel.Height.Value);
    }
}
@(builder)
    
@Html.ValidationMessageFor(model => model)

That seems like a lot of logic in the Editor templates/partials/views to me...在我看来,编辑器模板/部分/视图中有很多逻辑......

Why not move the logic out and into models?:为什么不将逻辑移出并移入模型?:

//Interface

public interface IKendoDropDownListModel
{

    string AreaName { get; set; }

    string ControllerName { get; set; }

    string ActionName { get; set; }

    string ClientTemplate { get; set; }

    string OptionLabel { get; set; }

    string DisplayText { get; set; }

    string Value { get; set; }

    int Width { get; set; }

}


//Base Editor Model

public class KendoDropDownListModel : IKendoDropDownListModel
{
    public KendoDropDownListModel(string areaName, string controllerName, string actionName)
    {
        AreaName = areaName;
        ControllerName = controllerName;
        ActionName = actionName;
        OptionLabel = "please select...";
        Width = 100;
    }

    public string AreaName { get; set; }

    public string ControllerName { get; set; }

    public string ActionName { get; set; }

    public string ClientTemplate { get; set; }

    public string OptionLabel { get; set; }

    public string DisplayText { get; set; }

    public string Value { get; set; }

    public int Width { get; set; }

}

//Inheriting Model

public class FinancialsChartOfAccountsDropdown : KendoDropDownListModel
{
    public FinancialsChartOfAccountsDropdown() : base("area", "controller", "action")
    {
        Width = 400;
    }

}

//Input/View Model example

public class ModelUsingDropdown
{
    public ModelUsingDropdown()
    {
        Dropdown = new FinancialsChartOfAccountsDropdown();
    }

    [UIHint("KendoDropDownListModel")]
    public FinancialsChartOfAccountsDropdown Dropdown { get; set; }

}

//Single Editor Template

@model IKendoDropDownListModel

@(Html.Kendo().DropDownListFor(m => m)
          .OptionLabel(Model.OptionLabel)
          .DataTextField("DisplayText")
          .DataValueField("Value")
            .DataSource(source => source
                      .Transport(transport => transport
                        .Read(read =>
                        {
                            read.Action(Model.Action, Model.Controller);
                        }))
                )
            .Width(Model.Width)
          )

Then when you post the model you just have to get the value from the object然后,当您发布 model 时,您只需从 object 获取值

    [HttpPost]
    public ActionResult SomeAction(ModelUsingDropdown model)
    {
        string valueFromDropdown = model.Dropdown.Value;

        return View();
    }

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

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