MVC UpdateModel checkbox sąrašui

įvertino 0 Atsakyta (Patvirtinta) Ši žinutė turi 2 patvirtinti atsakymai | 5 Atsakymai | 2 Šalininkai

Top 10 autorių
Vyras
21 Žinutės
Taškai 405
mipi3 parašyta 05-23-2009 0:09

Sveiki,

neseniai pradėjau žiūrinėti ASP.NET MVC ir susidūriau su viena problema, nežinau, kaip ją čia gražiai išspręst.

View'e checkbox'ai sugeneruojami iš Model sąrašo (pvz Model.Users[]). Generuoju juos per foreach, pavadinu kiekvieną "chk"+i. Papostinus formą su tais checkbox'ais norėtusi, kad pažymėtų checkbox'ų pavadinimai būtų (kažkokiu būdu) priskirti atgal Model.Users[] per UpdateModel metodą. Ar yra koks būdas kaip tai būtų galima atlikti iškvietus tik UpdateModel() metodą? Ar reikės ieškoti savo checkbox'ų FormCollection sąraše, tai yra UpdateModel šiuo atveju teks pamiršt? Ar gal yra koks kitas būdas kaip postint čekboksų sarašus (mano atveju medžius)?

Ačiū :)

Atsakyta (Patvirtinta) Patvirtinti atsakymai

Top 10 autorių
Vyras
59 Žinutės
Taškai 1,255
Verified by mipi3

Sveikas,

Jeigu gerai supratau, realiai tau užteks savo checkbox elementams priskirti name='Users[0]', sekančiam - name='Users[1]' ir pan. Daugiau info - http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx.

Tikiuosi padės ;)

Top 10 autorių
Vyras
21 Žinutės
Taškai 405
Verified by Sergejus

taip, tai beveik veikia (uždėti interfeisą tik su get Name User klasei?). Vietoj interfeiso turi būti klasė, nes parametrai yra uždedami per Reflection'ą. Bet toks būdas man nelabai tinka, nes tenka koreguot dalykinę klasę.

Suradau, kad tokiais atvejais rekomenduoja naudotis IModelBinder. Padariau štai taip, nežinau ar korektiškai, bet veikia lyg gerai.

[ModelBinder(typeof(UserViewModelBinder))]
class UsersViewModel

{
    public string Title { get; set; }
    public User[] Users { get; set; }
}

 

public class UserViewModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext,
        System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.DisplayName == "Users")
        {
             var model = (UserViewModel)bindingContext.Model;
             for (int i = 0; i < model.Users.Count; i++)
             {
                 model.Users[i].IsChecked =
                         (from v in bindingContext.ValueProvider
                          where v.Key.StartsWith("Users[" + i + "]")
                          select (string)v.Value.ConvertTo(typeof(string)) != "false")
                          .SingleOrDefault();
              }
        }
        else
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
    }
}

 

  • | Žinučių taškai: 40

Visi atsakymai

Top 10 autorių
Vyras
59 Žinutės
Taškai 1,255
Verified by mipi3

Sveikas,

Jeigu gerai supratau, realiai tau užteks savo checkbox elementams priskirti name='Users[0]', sekančiam - name='Users[1]' ir pan. Daugiau info - http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx.

Tikiuosi padės ;)

Top 10 autorių
Vyras
21 Žinutės
Taškai 405

super! Kaip tik tai ko man reikėjo.

Bet pritaikęs tą metodą iškilo kita problema. Yra tokios klasės:

class UsersViewModel
{
    public string Title { get; set; }
    public User[] Users { get; set; }
}

User
{
    public string Name { get; set; }
    public bool IsChecked { get; set; }
}

puslapyje iš UsersViewModel.Users generuoju tų checkbox elementų sąrašą. Ir man reikia, kad bindintų ne visą User objektą o tiktai IsChecked parametrą. Bandau tai padaryti UpdateModel pateikiant bindinamų parametrų sąrašą, bet čia susiduriu su problema - šitas parametras yra pats parametro dalis, be to dar ir sąrašo.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection formCollection)
{
    UpdateModel(_usersViewModel, new string[] { "Title", "Users.IsChecked" /* tai nepraeina :( */ } );
    return View(_usersViewModel);
}

gal yra koks sprendimas čia? Pats nesugalvoju ir google nepadeda :)

  • | Žinučių taškai: 20
Top 10 autorių
Vyras
59 Žinutės
Taškai 1,255

Praktikoje nesu bandęs, bet teoriškai turėtų suveikti toks dalykas:

interface IUserUpdate
{
    string Name { get; }
    bool IsCheked { get; set; }
}

interface IUsersUpdate
{
    string Title { get; set; }
    UpdateUser[] Users { get; set; }
}

Ir tada:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection formCollection)
{
    UpdateModel<IUsersUpdate>(_usersViewModel);
    return View(_usersViewModel);
}

Dar kartą, čia tik teoriniai pamąstymai...

Top 10 autorių
Vyras
21 Žinutės
Taškai 405
Verified by Sergejus

taip, tai beveik veikia (uždėti interfeisą tik su get Name User klasei?). Vietoj interfeiso turi būti klasė, nes parametrai yra uždedami per Reflection'ą. Bet toks būdas man nelabai tinka, nes tenka koreguot dalykinę klasę.

Suradau, kad tokiais atvejais rekomenduoja naudotis IModelBinder. Padariau štai taip, nežinau ar korektiškai, bet veikia lyg gerai.

[ModelBinder(typeof(UserViewModelBinder))]
class UsersViewModel

{
    public string Title { get; set; }
    public User[] Users { get; set; }
}

 

public class UserViewModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext,
        System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.DisplayName == "Users")
        {
             var model = (UserViewModel)bindingContext.Model;
             for (int i = 0; i < model.Users.Count; i++)
             {
                 model.Users[i].IsChecked =
                         (from v in bindingContext.ValueProvider
                          where v.Key.StartsWith("Users[" + i + "]")
                          select (string)v.Value.ConvertTo(typeof(string)) != "false")
                          .SingleOrDefault();
              }
        }
        else
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
    }
}

 

  • | Žinučių taškai: 40
Top 10 autorių
Vyras
59 Žinutės
Taškai 1,255

Atrodo visai neblogas sprendimo variantas.

  • | Žinučių taškai: 5
Puslapis 1 iš 1 (6) | RSS
DotNetGroup.LT, 2009
Sprendimas