1

J'utilise les DataAnnotations pour la vérification des erreurs sur mon application asp.net mvc, j'utilise aussi ViewModels fortement typé.asp.net mvc multiselect se souvenir de l'état après la publication

Ma vérification d'erreur fonctionne correctement et affiche à ma vue des messages d'erreur si un champ est vide. Cependant, j'ai une MultiSelect/Listbox sur mon formulaire dont je dois me rappeler qu'il est l'état après une erreur.

Au moment de mon ViewModel ressemble à ceci (je n'ai inclus propriétés pertinentes):

public class ProfilePageViewModel : PageViewModel 
{ 
    public IList<FavouriteGenreViewModel> FavGenres { get; set; } 

    [Required(ErrorMessage = "*")] 
    public string SelectedGenres { get; set; } 


    public IDictionary<int, string> GenresList { get; set; } 
} 

Ceci est mon action dans mon contrôleur:

public ActionResult Profile(ProfilePageViewModel viewModel) 
    { 
     if(!ModelState.IsValid) 
     { 
      viewModel.CountriesList = dropDownTasks.GetCountries(); 
      viewModel.GendersList = dropDownTasks.GetGenders(); 
      viewModel.GenresList = dropDownTasks.GetGenres(); 
      viewModel.TimezonesList = dropDownTasks.GetTimezones(); 
      viewModel.FavGenres = 
      return View(viewModel); 
     } 

     . . . 

Mon MultiSelect prend une liste de FavouriteGenreViewModel de pour sélectionner les options dans GenresList, il le fait en utilisant AutoMapper dans l'action GET, mais évidemment, je ne peux pas utiliser AutoMapper sur le poste parce qu'il va oublier mes valeurs affichées.

J'ai pensé à utiliser une chaîne d'identifiants comma delimmated au lieu d'une liste de FavouriteGenreViewModel, de cette façon je peux réutiliser la valeur une fois posté ... cependant j'espère que quelqu'un a une façon plus élégante de traiter ce problème.

Merci!

Paul

Répondre

2

Je pense que je peux répondre à ma propre question après quelques farfouillé.

Dans mon ViewModel j'utiliser un tableau de chaînes comme le type de données comme ceci:

public class ProfilePageViewModel : PageViewModel 
{ 
[Required(ErrorMessage = "*")] 
public string[] FavGenres { get; set; } 

public IDictionary<int, string> GenresList { get; set; } 
} 

À mon avis, je peux configurer les valeurs sélectionnées pour FavGenres, alors j'ai un liant de modèle personnalisé pour convertir la virgule seperated chaîne dans des objets valables à nouveau ... au cas où vous vous demandez voici mon modèle de liant personnalisé en entier ...

public class AccountCustomModelBinder : DefaultModelBinder 
{ 
    private readonly IGenreRepository genreRepository; 
    private readonly ITimezoneRepository timeZoneRepository; 
    private readonly ICountryRepository countryRepository; 

    public AccountCustomModelBinder() : this(
     ServiceLocator.Current.GetInstance<IGenreRepository>(), 
     ServiceLocator.Current.GetInstance<ITimezoneRepository>(), 
     ServiceLocator.Current.GetInstance<ICountryRepository>()) 
    { 
    } 

    public AccountCustomModelBinder(IGenreRepository genreRepository, ITimezoneRepository timeZoneRepository, 
     ICountryRepository countryRepository) 
    { 
     Check.Require(genreRepository != null, "genreRepository is null"); 
     Check.Require(timeZoneRepository != null, "timeZoneRepository is null"); 
     Check.Require(countryRepository != null, "countryRepository is null"); 

     this.genreRepository = genreRepository; 
     this.timeZoneRepository = timeZoneRepository; 
     this.countryRepository = countryRepository; 
    } 

    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
    { 
     Account account = bindingContext.Model as Account; 

     if (account != null) 
     { 

      // gender 
      if (propertyDescriptor.Name == "Gender") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("Gender")) 
       { 
        account.Gender = bindingContext.ValueProvider["Gender"].AttemptedValue.ToString(); 
        return; 
       } 
      } 

      // TimezoneId 
      if (propertyDescriptor.Name == "TimezoneId") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("TimezoneId")) { 
        account.Timezone = timeZoneRepository.FindOne(Convert.ToInt32(bindingContext.ValueProvider["TimezoneId"].AttemptedValue)); 
        return; 
       } 
      } 

      // CountryId 
      if (propertyDescriptor.Name == "CountryId") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("CountryId")) { 
        account.Country = countryRepository.FindOne(Convert.ToInt32(bindingContext.ValueProvider["CountryId"].AttemptedValue)); 
        return; 
       } 
      } 

      // FavGenres 
      if (propertyDescriptor.Name == "FavGenres") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("FavGenres")) { 
        // remove all existing entries so we can add our newly selected ones 
        account.ClearFavGenres(); 
        string favIds = bindingContext.ValueProvider["FavGenres"].AttemptedValue; 
        foreach (string gId in favIds.Split(',')) { 
         account.AddFavGenre(genreRepository.Get(Convert.ToInt32(gId))); 
        } 
        return; 
       } 
      } 
     } 

     base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
    } 

} 
Questions connexes