【问题标题】:asp.net mvc multiselect remember state after postback回发后asp.net mvc多选记住状态
【发布时间】:2010-01-17 14:36:16
【问题描述】:

我在我的 asp.net mvc 应用程序上使用 DataAnnotations 进行错误检查,我也在使用强类型 ViewModels。

我的错误检查工作正常,如果字段为空白,则会返回我的视图并显示错误消息。但是,我的表单上有一个 MultiSelect / Listbox,我需要记住它在出错后的状态。

目前我的 ViewModel 看起来像这样(我只包含了相关属性):

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

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


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

这是我在控制器中的操作:

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); 
        }

        . . .

我的 MultiSelect 采用 FavouriteGenreViewModel 的列表来选择 GenresList 中的选项,它在 GET 操作中使用 AutoMapper 执行此操作,但显然我不能在帖子上使用 AutoMapper,因为它会忘记我发布的值。

我考虑过使用逗号分隔的 ID 字符串而不是 FavouriteGenreViewModel 列表,这样我就可以重新使用回传的值...但是我希望有人有更优雅的方式来处理这个问题。

谢谢!

保罗

【问题讨论】:

    标签: asp.net-mvc listbox viewmodel data-annotations multi-select


    【解决方案1】:

    我想我可以在闲逛之后回答我自己的问题。

    在我的 ViewModel 中,我使用字符串数组作为数据类型,如下所示:

    public class ProfilePageViewModel : PageViewModel 
    { 
    [Required(ErrorMessage = "*")] 
    public string[] FavGenres { get; set; } 
    
    public IDictionary<int, string> GenresList { get; set; } 
    } 
    

    在我看来,我可以将选定的值设置为 FavGenres,然后我有一个自定义模型绑定器,可以再次将逗号分隔的字符串转换为有效对象......如果你想知道这里是我的自定义模型绑定器。 .

    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);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2011-01-28
      • 1970-01-01
      • 2017-06-04
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多