2014-02-13 38 views
3

我有名字RadioButtonQuestion編輯模板,枚舉字段創建單選按鈕不工作的所有枚舉

@model Enum 

@{ 
    // Looks for a [Display(Name="Some Name")] or a [Display(Name="Some Name", ResourceType=typeof(ResourceFile)] Attribute on your enum 
    Func<Enum, string> getDescription = en => 
    { 
     Type type = en.GetType(); 
     System.Reflection.MemberInfo[] memInfo = type.GetMember(en.ToString()); 

     if (memInfo != null && memInfo.Length > 0) 
     { 

      object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute), 
                  false); 

      if (attrs != null && attrs.Length > 0) 
       return ((System.ComponentModel.DataAnnotations.DisplayAttribute)attrs[0]).GetName(); 
     } 

     return en.ToString(); 
    }; 
    var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e => 
    new SelectListItem() 
    { 
     Text = getDescription(e), 
     Value = e.ToString(), 
     Selected = e.Equals(Model) 
    }); 
    string prefix = ViewData.TemplateInfo.HtmlFieldPrefix; 
    int index = 0; 
    ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty; 

    foreach (var li in listItems) 
    { 
     string fieldName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++); 
     <div class="editor-radio"> 
      @Html.RadioButton(prefix, li.Value, li.Selected, new { @id = fieldName }) 
      @Html.Label(fieldName, li.Text) 
     </div> 
    } 
    ViewData.TemplateInfo.HtmlFieldPrefix = prefix; 
} 

這個編輯器模板下面的模型

public class CreateAppointmentSelectOptions 
{  
    public QuestionStart StartQuestion { get; set; } 

    public QuestionEnd EndQuestion { get; set; } 
} 

public enum QuestionStart 
{ 
    [Display(Name="Repeat till common match is found")] 
    RepeatTillCommonIsFound, 

    [Display(Name="Repeat once")] 
    RepeatOnce,  

    [Display(Name="No repeat")] 
    NoRepeat 

} 

public enum QuestionEnd 
{ 
    [Display(Name="Cancel Invitation")] 
    CancelInvitation, 

    [Display(Name="Plan with participants on first available common date")] 
    FirstAvailableCommon, 

    [Display(Name="Plan with participants on my first available common date")] 
    YourFirstAvailableCommon 
} 

有以下幾種觀點

@model InfoBridgeSmartDatePicker.Models.ViewModels.Appointment.CreateAppointmentSelectOptions 
@{ 
    ViewBag.Title = "Create_WhatIf"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
@using (Html.BeginForm("Create_WhatIf", "Appointment", FormMethod.Post)) 
{  
    <div class="col-md-10"> 
     <div class='well'> 
      <div class="form-group"> 
       <div class="input-group"> 
        @Html.EditorFor(m => m.StartQuestion, "RadioButtonQuestion") &nbsp; &nbsp; 
       </div>    

      </div> 
     </div> 
    </div> 


    <div class="col-md-10"> 
     <div class='well'> 
      <div class="form-group">   
       <div class="input-group"> 
        @Html.EditorFor(m => m.EndQuestion, "RadioButtonQuestion")&nbsp;&nbsp; 
       </div>        

      </div> 
     </div> 
    </div> 

} 
@Scripts.Render("~/bundles/jquery") 
@Scripts.Render("~/bundles/bootstrap") 
@Scripts.Render("~/bundles/jqueryval") 

editortemplate完美工作,它爲每個e字段創建單選按鈕NUM,但對於以下 模型

public class AttendeeResponse 
{ 
    public IsAttending Isattending { get; set; }  
} 

public enum IsAttending 
{ 
    [Display(Name="Attending")] 
    Attending, 

    [Display(Name="Not attending")] 
    NotAttending 
} 

有以下幾種觀點

@model InfoBridgeSmartDatePicker.Models.ViewModels.Response.AttendeeResponse 
@{ 
    ViewBag.Title = "Index"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
@using(Html.BeginForm("Index","Response",FormMethod.Post)) 
{ 
    <div class="col-md-10"> 
     <div class='well'> 
      <div class="form-group"> 
       <div class="input-group"> 
        @Html.EditorFor(m => m.Isattending, "RadioButtonQuestion") &nbsp; &nbsp; 
       </div>    

      </div> 
     </div> 
    </div> 
} 
<div id="provideDateTime"> 
    @{Html.RenderPartial("~/Views/Response/_AttendeeAvailableDateTime.cshtml");} 
</div> 
@Scripts.Render("~/bundles/jquery") 
@Scripts.Render("~/bundles/bootstrap") 
@Scripts.Render("~/bundles/jqueryval") 

我得到的錯誤在這條線的編輯模板

 return en.ToString(); 
Line 21:  }; 
/*error on this line Line*/ 22:  var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e => 
Line 23:  new SelectListItem() 
Line 24:  { 

爲什麼這個編輯器模板不工作的任何想法第二個看法?

堆棧跟蹤:

[NullReferenceException: Object reference not set to an instance of an object.] 
    ASP._Page_Views_Shared_EditorTemplates_RadioButtonQuestion_cshtml.Execute() in c:\Users\userx\Desktop\Git\DatePickerApp\datepicker\DatePicker\Views\Shared\EditorTemplates\RadioButtonQuestion.cshtml:22 
    System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +271 
    System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +120 
    System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +145 
    System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +695 
    System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +382 
    System.Web.Mvc.Html.TemplateHelpers.ExecuteTemplate(HtmlHelper html, ViewDataDictionary viewData, String templateName, DataBoundControlMode mode, GetViewNamesDelegate getViewNames, GetDefaultActionsDelegate getDefaultActions) +1037 
    System.Web.Mvc.Html.TemplateHelpers.TemplateHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName, String templateName, DataBoundControlMode mode, Object additionalViewData, ExecuteTemplateDelegate executeTemplate) +1633 
    System.Web.Mvc.Html.TemplateHelpers.TemplateHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName, String templateName, DataBoundControlMode mode, Object additionalViewData) +94 
    System.Web.Mvc.Html.TemplateHelpers.TemplateFor(HtmlHelper`1 html, Expression`1 expression, String templateName, String htmlFieldName, DataBoundControlMode mode, Object additionalViewData, TemplateHelperDelegate templateHelper) +228 
    System.Web.Mvc.Html.TemplateHelpers.TemplateFor(HtmlHelper`1 html, Expression`1 expression, String templateName, String htmlFieldName, DataBoundControlMode mode, Object additionalViewData) +140 
    System.Web.Mvc.Html.EditorExtensions.EditorFor(HtmlHelper`1 html, Expression`1 expression, String templateName) +94 
    ASP._Page_Views_Response_Index_cshtml.Execute() in c:\Users\userx\Desktop\Git\DatePickerApp\datepicker\DatePicker\Views\Response\Index.cshtml:14 
    System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +271 
    System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +120 
    System.Web.WebPages.StartPage.RunPage() +63 
    System.Web.WebPages.StartPage.ExecutePageHierarchy() +100 
    System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +131 
    System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +695 
    System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +382 
    System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +431 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +39 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +116 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +529 
    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +106 
    System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +321 
    System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +185 
    System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +42 
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +133 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +56 
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +40 
    System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +34 
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70 
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40 
    System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44 
    System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +39 
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +62 
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40 
    System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39 
    System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39 
    System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +39 
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70 
    System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59 
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40 
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40 
    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38 
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9514812 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

PS:我從this github project

+0

你確定這是你使用的代碼嗎?它對我來說工作得很好。但是,如果我將屬性聲明爲可爲空,則在同一行上出現該錯誤:'public IsAttending? Isattending {get;組; }'並且它在傳遞給視圖的模型中爲null –

+0

我發現問題,這是因爲從我的控制器中我沒有傳遞視圖模型類的實例。現在我實例化了我的類的對象並將它發送給模型,然後它工作正常。 – Cybercop

回答

0

這個編輯器模板的問題是我沒有通過控制器的get傳遞的對象(即查看正在使用的型號)方法。一旦我做到了,它的工作。

以前我有

public ActionResult Index() 
{ 

    return View(); 
} 

一旦我做到

public ActionResult Index() 
{ 
    var attendeeresponse = new AttendeeResponse(); 
    return View(attendeeresponse); 
} 

它的工作

3

很高興見到你已經找到了解決辦法。

但是你可以讓編輯模板更強勁,所以它不會破壞如果一個空模型傳遞給視圖,也實在是兼容可空類型一樣IsAttending?

只要改變這個代碼來獲取枚舉值:

var listItems = Enum.GetValues(enumType).OfType<Enum>().Select(e => 
new SelectListItem() 
{ 
    Text = getDescription(e), 
    Value = e.ToString(), 
    Selected = e.Equals(Model) 
}); 

有了這個代碼,不依賴於當前的模型實例:

var enumType = this.ViewData.ModelMetadata.ModelType; 
if (enumType.IsGenericType && enumType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
{ 
    enumType = Nullable.GetUnderlyingType(enumType); 
} 

var listItems = Enum.GetValues(enumType).OfType<Enum>().Select(e => 
new SelectListItem() 
{ 
    Text = getDescription(e), 
    Value = e.ToString(), 
    Selected = e.Equals(Model) 
}); 

編輯 - 代碼用於與傳遞給視圖場景

型號

public class AttendeeResponse 
{ 
    public IsAttending? Isattending { get; set; } 
} 

public enum IsAttending 
{ 
    [Display(Name = "Attending")] 
    Attending, 

    [Display(Name = "Not attending")] 
    NotAttending 
} 

查看

@model MvcApplication1.Models.AttendeeResponse 

@{ 
    ViewBag.Title = "Attendee Response"; 
} 

@using(Html.BeginForm("Index","Response",FormMethod.Post)) 
{ 
    <div class="col-md-10"> 
     <div class='well'> 
      <div class="form-group"> 
       <div class="input-group"> 
        @Html.EditorFor(m => m.Isattending, "RadioButtonQuestion") &nbsp; &nbsp; 
       </div>    

      </div> 
     </div> 
    </div> 
} 

編輯模板

@model Enum 

@{ 
    // Looks for a [Display(Name="Some Name")] or a [Display(Name="Some Name", ResourceType=typeof(ResourceFile)] Attribute on your enum 
    Func<Enum, string> getDescription = en => 
    { 
     Type type = en.GetType(); 
     System.Reflection.MemberInfo[] memInfo = type.GetMember(en.ToString()); 

     if (memInfo != null && memInfo.Length > 0) 
     { 

      object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute), 
                  false); 

      if (attrs != null && attrs.Length > 0) 
       return ((System.ComponentModel.DataAnnotations.DisplayAttribute)attrs[0]).GetName(); 
     } 

     return en.ToString(); 
    }; 

    var enumType = this.ViewData.ModelMetadata.ModelType; 
    if (enumType.IsGenericType && enumType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
    { 
     enumType = Nullable.GetUnderlyingType(enumType); 
    } 

    var listItems = Enum.GetValues(enumType).OfType<Enum>().Select(e => 
    new SelectListItem() 
    { 
     Text = getDescription(e), 
     Value = e.ToString(), 
     Selected = e.Equals(Model) 
    }); 
    string prefix = ViewData.TemplateInfo.HtmlFieldPrefix; 
    int index = 0; 
    ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty; 

    foreach (var li in listItems) 
    { 
     string fieldName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++); 
     <div class="editor-radio"> 
      @Html.RadioButton(prefix, li.Value, li.Selected, new { @id = fieldName }) 
      @Html.Label(fieldName, li.Text) 
     </div> 
    } 
    ViewData.TemplateInfo.HtmlFieldPrefix = prefix; 
} 

控制器可空枚舉類型和空模型

public ActionResult Attendee() 
{ 
    //You can pass null as the view model and the view/editor template won't break 
    return View(); 
    //This would also work, showing that you can have a nullable with null value 
    //return View(new AttendeeResponse()); 
    //If the nullable enum has a value, it would appear as selected: 
    //return View(new AttendeeResponse{Isattending = IsAttending.NotAttending}); 
} 
+0

但它會工作,如果我做了我犯的錯誤,而不通過對象來查看控制器?剛剛嘗試過,但沒有奏效。另外,我們提到它可以是空的,但從前端來看,默認情況下我們會選擇一個放射按鈕,我想我們最終會選擇一個放射按鈕。對不起,如果我錯了。但我喜歡這種方法。 +1 – Cybercop

+0

如果使用可空屬性,默認情況下不會選擇任何值(因爲它可以爲空)。這將允許該字段是強制性的場景或者強制用戶自己選擇一個值。我也試着用一個空模型傳遞給視圖的代碼,它的工作原理,將用我使用的確切代碼進行更新 –

+0

順便說一下,我並不是說你應該將一個空模型傳遞給視圖,或者你應該定義您的枚舉屬性可爲空。只是以這種方式更新編輯器模板將支持這些場景,使其更加靈活/強大:) –