Ok, ho intenzione di provare a ottenere il 90% del modo in cui ci sono. Questa è in realtà una parte enorme e complessa di MVC 2 e quasi impossibile rispondere solo in questa casella di risposta.
Ora per prima cosa dovresti andare al blog di Brad Wilsons e leggere in profondità come personalizzare i modelli MVC 2 predefiniti. Questo dovrebbe darti una comprensione molto più chiara di tutte le parti mobili.
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html
Ora inizierò un semplice esempio di come creare una vista del modello appuntamento artificiosa dove vogliamo assicurarsi che i valori forniti non tornare indietro nel tempo. Non prestare attenzione agli attributi in questo momento, ci arriveremo.
Ecco il ViewModel che sto utilizzando:
public class AppointmentViewModel
{
[Required]
public string Name { get; set; }
[CantGoBackwardsInTime]
public DateRange DateRange { get; set; }
}
public class DateRange
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
[Required]
public int Price { get; set; }
}
E ho aggiunto questo al HomeController default (niente di speciale):
public ActionResult Appointment()
{
return View(new AppointmentViewModel());
}
[HttpPost]
public ActionResult Appointment(AppointmentViewModel appointment)
{
return View(appointment);
}
Ed ecco la mia Vista:
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Appointment
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Add Appointment</h2>
<%= Html.ValidationSummary() %>
<% using(Html.BeginForm()) { %>
<%= Html.EditorForModel() %>
<input type="submit" value="Save Changes" />
<%} %>
</asp:Content>
Passaggio 1: Impostazione dello stage
La prima cosa che vuoi fare è prendere i "modelli predefiniti" dal post di blog. L'importante in questo caso è quello che si troverà in /Views/Shared/EditorTemplates/Object.asxc Object.ascx è la chiave di volta dell'intera operazione. Tutti i metodi Html.Editor ***** lo chiameranno alla fine.
Ora, il primo pezzo di funzionalità predefinita che dobbiamo cambiare è questa linea all'interno del Object.ascx
<% if (ViewData.TemplateInfo.TemplateDepth > 1) { %>
<%= ViewData.ModelMetadata.SimpleDisplayText%>
<% }
cosa thats dicendo è "non presentano tipi complessi annidati" e non vogliamo quella. Cambia quello> 1 in un> 2. Ora i modelli nel tuo oggetto grafico avranno dei modelli creati per loro invece di creare solo testo segnaposto.
Basta mantenere tutto il resto predefinito per ora.
* Fase 2: Modelli di priorità assoluta **
Se leggete le voci di blog Spero che possiate capire ora come l'Editor *** e metodi di visualizzazione chiamerà automaticamente i modelli nella vista/Shared/EditorTemplates e DisplayTemplates . Pensa a loro come se chiamassero Html.RenderPartial ("TYPENAME", MyType) non lo sono, ma è abbastanza vicino nel concetto.
Quindi se si esegue la soluzione fino a questo punto e si passa all'url corretto, si noterà che MVC 2 chiamerà Object.ascx due volte, una volta per AppointmentViewModel e nuovamente per la proprietà DateRange. Immediatamente viene eseguito il rendering della stessa raccolta di campi modulo.
Diciamo che vogliamo far sì che il nostro modello contenga il nostro editor DateRange con una casella bordata di rosso. Quello che vogliamo fare è short circut MVC 2 per chiamare un modello personalizzato DateTime.ascx invece di Object.ascx e questo è facile come aggiungere il nostro modello in View/Shared/EditorTemplates/DateRange.ascx. In questo caso ho appena preso quello che è stato generato da Object.ascx lavorando con il nostro modello DateRange ed appena incollato il codice in un nuovo DateRange.ascx:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<div style="border: 1px solid #900">
<div class="editor-label"><label for="DateRange">DateRange</label></div>
<div class="editor-field">
<div class="editor-label"><label for="DateRange_Start">Start</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="DateRange_Start" name="DateRange.Start" type="text" value="" />
</div>
<div class="editor-label"><label for="DateRange_End">End</label></div>
<div class="editor-field">
<input class="text-box single-line" id="DateRange_End" name="DateRange.End" type="text" value="" />
</div>
<div class="editor-label"><label for="DateRange_Price">Price</label></div>
<div class="editor-field">
<input class="text-box single-line" id="DateRange_Price" name="DateRange.Price" type="text" value="" />
</div>
</div>
</div>
Wala!
Ora quando si esegue la soluzione si dovrebbe vedere una scatola rossa attorno al nostro DateRange. Il resto delle personalizzazioni dipende da te! È possibile aggiungere caselle jQuery DatePicker. Nel tuo caso potresti mettere entrambi i campi in un singolo div in modo che si allineano in orizzontale. Il cielo è il limite a questo punto.
Fase 3: Convalida:
convalida funziona praticamente solo il modo in cui ci si aspetterebbe. Un attributo [obbligatorio] all'interno del tuo tipo DateRange funziona esattamente come qualsiasi altro attributo di convalida.
Ora si vede che non posso tornare indietro nell'attributo time che ho inserito nella proprietà DateRange di AppointmentViewModel. Tutto quello che devi fare per creare questo tipo di convalida attributi specifici è ereditare e implementare la ValidationAttribute di base:
public class CantGoBackwardsInTime : ValidationAttribute
{
public override string FormatErrorMessage(string name)
{
return "Your date range can't go backwards in time";
//return base.FormatErrorMessage(name);
}
public override bool IsValid(object value)
{
if (!(value is DateRange))
throw new InvalidOperationException("This attributes can only be used on DateRange types!");
var dateRange = value as DateRange;
return dateRange.End > dateRange.Start;
}
}
Ora, se si aggiunge questo e decorare la vostra proprietà si dovrebbe vedere il messaggio di errore previsto l'attributo di convalida CantGoBackwardsInTime personalizzato.
Aggiornerò e chiarirò di più se avete qualche problema, ma questo dovrebbe iniziare e arrivare. (pensavo di poterlo scoprire prima di andare a letto) Solo un avvertimento: il nuovo Editor per i pezzi di MVC 2 è la cosa più fantastica del mondo e ha un enorme potenziale per offrire le eccellenti capacità RAD di MVC 2; eppure c'è poco da sapere oltre al blog di Brad Wilsons. Continua a farlo e non aver paura di dare un'occhiata al codice sorgente di MVC 2 se ne hai bisogno.
"ma finora ho avuto poca fortuna nel trovare soluzioni adeguate." Che cosa significa? – jfar
Ciao jfar, sono abbastanza nuovo per C# e mvc e quindi mi sono affidato alle ricerche di google per trovare un buon punto di partenza di una soluzione. Il principale è stato http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx ma non sono riuscito a capire come aggiungere la convalida (lato server o lato client). –
Oh ok, pensavo fosse qualcos'altro. A meno che qualcun altro risponda, invierò una risposta stasera. Faccio questo tipo di cose tutto il tempo. – jfar