2013-01-08 10 views
6

Ho una pagina MVC4 con un modulo con una raccolta di caselle di controllo, pulsanti di opzione e caselle di testo utilizzate come campi di ricerca. Al post vengono analizzate le selezioni e la griglia dei risultati inferiore viene aggiornata con nuovi risultati. Al momento tutti i valori del modulo vengono cancellati al momento del ritorno e i nuovi risultati vengono visualizzati nella griglia - solo la griglia è parte del modello.Mantenimento dei valori dei moduli dopo la posta (non fa parte del modello)

Desidero che tutte le selezioni del modulo mantengano i loro valori dopo la postazione in modo che l'utente possa vedere (e modificare) le selezioni per il prossimo post/ricerca. Il modulo è popup con viewbags.

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "searchform" })) 
{ 
    @Html.ValidationSummary("Please correct the following errors") 

<div style="float:left;"> 

    <div style="float:left;"> 
    <label>Name:</label> 
    @Html.TextBox("name") 
    </div> 

    <div style="float:left; margin-left:15px"> 
    <label>Company:</label> 
    @Html.TextBox("company") 
    </div> 

    <div style="float:left; margin-left:65px"> 
    <label>Date Range:</label> 
    @Html.TextBox("dateStart", "", new { @class = "datefield", type = "date" }) 
    &nbsp;to&nbsp; 
    @Html.TextBox("dateEnd", "", new { @class = "datefield", type = "date" }) 
    </div> 

</div> 

<div style="clear: both;"> 
    Match Any Categories? <input type="radio" name="categoryMatchAll" value="false" checked="checked" />&nbsp;&nbsp;&nbsp; 
    Match All Categories? <input type="radio" name="categoryMatchAll" value="true" /> 
</div> 

<div style="float:left;"> 

    <div id="searchform-categories" style="float:left;"> 
     <div class="scroll_checkboxes"> 
      <label>Categories</label> 
      <ul> 
      @foreach (var x in ViewBag.Categories) 
      { 
        <li> 
         <input type="checkbox" name="categories" value="@x.Id"/> 

         @x.Name 

        </li> 
      } 
      </ul> 
     </div> 
    </div> 

    <div id="searchform-diversity" style="float:left; margin-left:30px">  
     <div class="search-selection" style="float:left;"> 
      <label>Minority Owned</label> 
      <ul> 
       @foreach (var x in ViewBag.Minorities) 
       { 
        <li> 
         @Html.RadioButton("minorities", (String)x.Id.ToString()) 
         @x.Name 
        </li> 
       } 
      </ul> 
     </div> 
     <div class="search-selection" style="float:left;"> 
      <label>Diversity Class</label> 
      <ul> 
      @foreach (var x in ViewBag.Classifications) 
      { 
       <li> 
        @Html.RadioButton("classifications", (String)x.Id.ToString()) 
        @x.Name 
       </li> 
      } 
     </ul> 
     </div>  
    </div> 

</div>  

<div style="clear: both;"> 
    <input type="submit" value="Search Profiles" /> 
    <input type="submit" value="Reset" /> 
    </div>  
} 

la griglia di dati è destinato a modello come

@model IEnumerable<VendorProfileIntranet.Models.VendorProfile> 

<table id="VendorTable" width="100%" class="gradeA"> 
<thead> 
    <tr> 
    <th> 
     @Html.DisplayNameFor(model => model.Name) 
    </th> 
    <th> 
     @Html.DisplayNameFor(model => model.CompanyName) 
    </th> 
    <th> 
     @Html.DisplayNameFor(model => model.City) 
    </th> 
    <th> 
     @Html.DisplayNameFor(model => model.State) 
    </th> 
    <th> 
     @Html.DisplayNameFor(model => model.DateCreated) 
    </th> 
    <th>Actions</th> 
    </tr> 
</thead> 
<tbody> 

@foreach (var item in Model) 
{ 
<tr> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.Name) 
    </td> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.CompanyName) 
    </td> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.City) 
    </td> 
    <td> 
     @Html.DisplayFor(modelItem => item.State) 
    </td> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.DateCreated) 
    </td> 
    <td class="list-field"> 
     @Html.ActionLink("Edit", "Edit", new { id = item.ProfileID }) | 
     @Html.ActionLink("View", "View", new { id = item.ProfileID }) | 
     @Html.ActionLink("Delete", "Delete", new { id = item.ProfileID }, new { onclick = " return DeleteConfirm()" }) 
    </td> 
</tr> 

} 

</tbody> 
<tfoot> 
    <tr> 
     <td>&nbsp;</td> 
    </tr> 
</tfoot> 

risposta

1

Quindi ecco come risolvo questo problema in genere. Le mie note sono puramente la mia opinione (religiosa?) Sulle classi di nominazione in un progetto MVC per mantenere chiaro il loro scopo.

Coppia di interfacce per mantenerlo estendibile:

// be specific about what type of results, both in the name of the 
// interface and the property needed, you don't want to have overlapping 
// properies on your classes, I like suffixing interfaces that are specific 
// to a View or Partial View with View 
public interface IPersonSearchResultsView 
{ 
    IEnumerable<EFPerson> PersonSearchResults { get; } 
} 

public interface IPersonSearchCriteriaView 
{ 
    PersonSearchCriteriaModel PersonSearchModel { get; } 
} 

paio di classi

// I like suffixing classes that I only use for MVC with Model 
public PersonSearchCriteriaModel 
{ 
    public string Name {get; set;} 
    public string Company {get; set;} 
    public string DateStart {get; set;} 
    public string DateEnd {get; set;} 
} 

// I like suffixing classes that I used passed to a View/Partial View 
// with ViewModel  
public class PersonSearchViewModel : IPersonSearchResultsView, 
            IPersonSearchCriteriaView 
{ 
    public IEnumerable<EFPerson> PersonSearchResults { get; set; } 
    public PersonSearchCriteriaModel PersonSearchModel { get; set; } 
} 

Ora, per i controller, io configurarli in modo che consentirebbe anche di fare Ajax in futuro.

public PersonController : Controller 
{ 
    public ActionResult Search() 
    { 
    var model = new PersonSearchViewModel(); 
    // make sure we don't get a null reference exceptions 
    model.PersonSearchModel = new PersonSearchCriteriaModel(); 
    model.PersonSearchResults = new List<EFPerson>(); 
    return this.View(model); 
    } 

    [HttpPost] 
    public ActionResult Search(PersonSearchViewModel model) 
    { 
    model.PersonSearchResults = this.GetPersonResults(model.PersonSearchModel); 

    return this.View(model) 
    } 

    // You could use this for Ajax 
    public ActionResult Results(PersonSearchViewModel model) 
    { 
    model.PersonSearchResults = this.GetPersonResults(model.PersonSearchModel); 

    return this.Partial("Partial-SearchResults", model) 
    } 

    private GetPersonResults(PersonSearchCriteriaModel criteria) 
    { 
    return DbContext.GetPersonResults(criteria) 
    } 
} 

Creare un paio di viste parziali.

/Views/Person/Partial-SearchCriteria.cshtml

@model IPersonSearchCriteriaView 

// the new part is for htmlAttributes, used by Ajax later 
@using (Html.BeginForm(..., new { id="searchCriteria" })) 
{ 
    // Here is were the magic is, if you use the @Html.*For(m=>) 
    // Methods, they will create names that match the model 
    // and you can back back to the same model on Get/Post 

    <label>Name:</label> 
    @Html.TextBoxFor(m => Model.PersonSearchModel.Name) 

    // or let mvc create a working label automagically 

    @Html.EditorFor(m => Model.PersonSearchModel.Name) 

    // or let mvc create the entire form.. 

    @Html.EditorFor(m => Model.PersonSearchModel) 
} 

/Views/Person/Partial-SearchResults.cshtml

@model IPersonSearchResultsView 

@foreach (var person in Model.PersonSearchResults) 
{ 
    <tr> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => person.Name) 
    </td> 

    // etc 
    </tr> 
} 

e, infine, la vista:

/Viste/Persona/Ricerca.cshtml

@model PersonSearchViewModel 

@Html.Partial("Partial-SearchCriteria", Model) 

// easily change the order of these 

<div id="searchResults"> 
@Html.Partial("Partial-SearchResults", Model); 
</div> 

Ora abilitazione Ajax è abbastanza pazzo facile (semplificato e il mio non essere esattamente a destra):

$.Ajax({ 
    url: '/Person/Results', 
    data: $('#searchCriteria').serialize(), 
    success: function(jsonResult) 
    { 
    $('#searchResults').innerHtml(jsonResult); 
    }); 
+0

grazie per aver fornito tutto ciò, tenterò la tua soluzione. – SQLGrinder

1

Quello che di solito faccio è passare il modello pubblicato di nuovo nel panorama. In questo modo i valori non vengono cancellati.

Il codice dovrebbe essere simile a questa:

<div style="float:left;"> 

    <div style="float:left;"> 
    <label>Name:</label> 
    @Html.TextBox("name", Model.Name) 
    </div> 

<div style="float:left; margin-left:15px"> 
<label>Company:</label> 
@Html.TextBox("company", Model.Company) 
</div> 

<div style="float:left; margin-left:65px"> 
<label>Date Range:</label> 
@Html.TextBox("dateStart", Model.DateStart, new { @class = "datefield", type = "date" }) 
&nbsp;to&nbsp; 
@Html.TextBox("dateEnd", Model.DateEnd, new { @class = "datefield", type = "date" }) 
</div> 

Quando inizialmente ricevendo il modulo, dovrete creare un nuovo Model, altrimenti la Model sarà nullo e un'eccezione quando le proprietà sono chiamate esso.

modello del campione

public class SearchModel 
{ 

    public SearchModel() 
    { 
     Results = new List<Result>(); 
    } 

    public string Name {get; set;} 

    public string Company {get; set;} 

    public string DateStart {get; set;} 

    public string DateEnd {get; set;} 

    public List<Result> Results {get; set;} 
} 


@foreach (var item in Model.Results) 
{ 
<tr> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.Name) 
    </td> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.CompanyName) 
    </td> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.City) 
    </td> 
    <td> 
     @Html.DisplayFor(modelItem => item.State) 
    </td> 
    <td class="list-field"> 
     @Html.DisplayFor(modelItem => item.DateCreated) 
    </td> 
    <td class="list-field"> 
     @Html.ActionLink("Edit", "Edit", new { id = item.ProfileID }) | 
     @Html.ActionLink("View", "View", new { id = item.ProfileID }) | 
     @Html.ActionLink("Delete", "Delete", new { id = item.ProfileID }, new { onclick = " return DeleteConfirm()" }) 
    </td> 
</tr> 

} 

Ecco una link sulla creazione di modelli per una vista in MVC.

+0

La mia comprensione è che si può avere un solo modello e che è già occupato dalla griglia di dati, quindi non sono sicuro di come incorporare ciò che si sta suggerendo. (vedi aggiornato sopra) – SQLGrinder

+0

@Vic Sì, è vero, ma un modello è semplicemente una classe. Puoi avere qualsiasi cosa nella classe. –

+0

@Vic su GET, i risultati saranno vuoti - nessuna riga verrà visualizzata. Al termine della ricerca, vengono visualizzati i risultati e i criteri di ricerca. –

1

se si utilizza HTML in MVC quindi controllare soluzione 2 da here, value="@Request["txtNumber1"]" funzionato bene per me,

<input type="text" id="txtNumber1" name="txtNumber1" value="@Request["txtNumber1"]"/> 

la speranza aiuta qualcuno.

+0

Perché giù voto? per favore spiega di aggiungere una risposta migliore in futuro. – stom

Problemi correlati