代码之家  ›  专栏  ›  技术社区  ›  Bad Dub

常规渲染局部视图-将PropertyInfo转换为具体对象

  •  1
  • Bad Dub  · 技术社区  · 6 年前

    我正在用MVC(c#)制作一个向导。但是我的向导视图中有一个if语句,它是这样的:

    if (Model.Wizard.ClientDetails.GetStep() == Model.Wizard.CurrentStep)
    {
        @Html.PartialFor(x => x.Wizard.ClientDetails, "_Step");
    }
    else if (Model.Wizard.Preferences.GetStep() == Model.Wizard.CurrentStep)
    {
        @Html.PartialFor(x => x.Wizard.ClientPreferences, "_Step")
    }
    else if (Model.Wizard.ClientQuestions.GetStep() == Model.Wizard.CurrentStep)
    {
        @Html.PartialFor(x => x.Wizard.ClientQuestions, "_Step")
    }
    

    向导的设置非常通用,除了视图的这一部分,我选择显示哪个部分。从上面的代码可以看出 if 遵循相同的结构。唯一改变的是 Model.Wizard.**Property**

    我想把这个拿走 如果 这样我就不用担心写报告了 如果

    我想把代码改成这样:

    @Html.PartialFor(x => x.ExampleWizardTransaction.GetStepObject(), "_Step");
    

    GetStepObject 方法如下:

    public static T GetStepObject<T>(this IWizardTransaction wizardTransaction) 
         where T : class, new()
    {
        var properties = wizardTransaction.GetType().GetProperties()
                .Where(x => x.PropertyType.GetCustomAttributes(typeof(StepAttribute), true).Any());
    
        PropertyInfo @object = properties.FirstOrDefault(x => ((StepAttribute)Attribute
                .GetCustomAttribute(x.PropertyType, typeof(StepAttribute))).Step == wizardTransaction.CurrentStep);
    
    }
    

    这个 PropertyInfo @object PropertyInfo@对象

    编辑#1:

    现有的 PartialFor 这在正常情况下有效。

    public static MvcHtmlString PartialFor<TModel, TProperty>(
        this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
        var name = ExpressionHelper.GetExpressionText(expression);
        var model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
        var viewData = new ViewDataDictionary(helper.ViewData)
        {
            TemplateInfo = new TemplateInfo { HtmlFieldPrefix = name }
        };
        return helper.Partial(partialViewName, model, viewData);
    }
    

    编辑#2:

    值没有被绑定的原因是 var name = ExpressionHelper.GetExpressionText(expression); name

    public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper,
        Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
        var compiled = expression.Compile();
        var result = compiled.Invoke(helper.ViewData.Model);
    
        var name = ExpressionHelper.GetExpressionText(expression); 
        //Should be ExampleWizardTransaction.ClientDetails for this step but is blank
    
        var viewData = new ViewDataDictionary(helper.ViewData)
        {
            TemplateInfo = new TemplateInfo 
            { 
                 //HtmlFieldPrefix = name
                 HtmlFieldPrefix = "ExampleWizardTransaction.ClientDetails" 
            }
            //Hard coded this to ExampleWizardTransaction.ClientDetails and the bindings now work
        };
    
        return helper.Partial(partialViewName, result, viewData);
     }
    

    似乎我需要能够获得向导对象和当前步骤对象的名称作为字符串值传入 TemplateInfo .

    1 回复  |  直到 6 年前
        1
  •  2
  •   Alfredo A.    6 年前

    我要对你的班级结构做个粗略的猜测。假设你的课程是这样的:

    [AttributeUsage(AttributeTargets.Property, AllowMultiple =false)]
    public class StepAttribute: Attribute
    {
        public StepEnum Step { get; set; }
    }
    
    public interface IWizardStep
    {
    
    }
    
    public interface IWizardTransaction
    {
    
    }
    
    public enum StepEnum
    {
        Previous,
        CurrentStep
    }
    
    public class WizardStep: IWizardStep
    {
        public string StepName { get; set; }
    
        public override string ToString()
        {
            return StepName;
        }
    }
    
    public class Wizard : IWizardTransaction
    {
        [Step(Step = StepEnum.Previous)]
        public WizardStep ClientDetails => new WizardStep() { StepName = "ClientDetails" };
        [Step(Step = StepEnum.CurrentStep)]
        public WizardStep ClientQuestions => new WizardStep() { StepName = "ClientQuestions" };
    }
    

    部分

        public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> html, 
                Expression<Func<TModel, TProperty>> expression, string partialViewName)
        {
            var compiled = expression.Compile();
            var result = compiled.Invoke(html.ViewData.Model);
            return html.Partial(partialViewName, result);
        }
    

    GetStepObject对象

        public static TProperty GetStepObject<TProperty>(this IWizardTransaction wizardTransaction)
            where TProperty : class
        {
            var properties = wizardTransaction.GetType().GetProperties()
                    .Where(x => x.GetCustomAttributes(typeof(StepAttribute), true).Any());
            PropertyInfo @object = properties.FirstOrDefault(x => 
                        (x.GetCustomAttributes(typeof(StepAttribute), true).SingleOrDefault()
                                    as StepAttribute).Step == StepEnum.CurrentStep);
            return @object.GetValue(wizardTransaction) as TProperty;
        }
    

    使用名为 _步骤.cshtml 这样地

    @model PartialView.Models.WizardStep
    
    @Model
    

    你的观点可以这样说

    @model PartialView.Models.Wizard
    @using PartialView.Models;
    @{
        ViewBag.Title = "Partial view calling";
    }
    
    @Html.PartialFor(m=>m.GetStepObject<WizardStep>(), "_Step")