MVC i Entity Framework Html.DisplayNameFor z Composite ViewModel
Jestem całkiem zadowolony z MVVM przy użyciu WPF / Silverlight, ale jest to moja pierwsza próba aplikacji sieciowej MVC… tylko fyi dla mojego tła.
Stworzyłem kontroler o nazwie TestSitesController, który został automatycznie wygenerowany z klasy modelu „Site” w moim modelu Entity Framework Model (szablon generujący akcje i widoki odczytu / zapisu). Jedyną rzeczą, którą zmodyfikowałem, było 3 miejsca, dla niektórych metod był domyślny parametr Guid id = null. Właśnie pozbyłem się „= null”, wszystko działa poprawnie. Oto przykład tego, co zmieniłem
public ActionResult Delete(Guid id = null)
{
//....
}
To zostało zmienione na
public ActionResult Delete(Guid id)
{
//....
}
Model witryny nie jest niczym szczególnym SiteId, skrótem i DisplayName… starając się, aby to pytanie było jak najprostsze. Ok, więc uruchamiam stronę i htpp: //.../TestSites/ i wszystko działa idealnie.
Zauważyłem, że wszystkie moje widoki (Create, Delete, Details i Edit) używają @model MVCWeb.MyEntities.Site, z którym teraz jestem w pełni zadowolony; ale w widoku Index.cshtml zauważyłem, że używa
@model IEnumerable<MVCWeb.MyEntities.Site>
Działa to dobrze dla wygenerowanego szablonu, ale chciałbym użyć „Composite View Model” i być może właśnie tam próbuję połączyć moją wiedzę o MVVM, ale pozostanę przy tym, jeśli to możliwe. Moim zdaniem model widoku złożonego jest tylko modelem specyficznym dla widoku, który składa się z 1 lub więcej modeli jednostek wraz z dodatkowymi właściwościami, takimi jak SelectedSiteId itp.
Dlatego stworzyłem bardzo prosty ViewModel o nazwie TestSitesViewModel
public class TestSitesViewModel
{
//Eventually this will be added to a base ViewModel to get rid
//of the ViewBag dependencies
[Display(Name = "Web Page Title")]
public string WebPageTitle;
public IEnumerable<MVCWeb.MyEntities.Site> Sites;
//Other Entities, IEnumberables, or properties go here
//Not important for this example
}
Następnie w moim kontrolerze dodałem metodę akcji o nazwie IndexWithViewModel
public ActionResult IndexWithViewModel()
{
var vm = new TestSitesViewModel();
vm.WebPageTitle = "Sites With Composite View Model";
vm.Sites = db.Sites.ToList();
return View(vm);
}
Następnie zrobiłem kopię Index.cshtml i nazwałem ją IndexWithModel.cshtml, aby pasowała do mojej nowej nazwy metody ActionResult. Zmieniłem górną linię
@model IEnumerable<MVCWeb.MyEntities.Site>
Do
@model MVCWeb.Models.TestSitesViewModel
Dodałem to przed sekcją tabeli, aby przetestować DisplayNameFor i DisplayFor
@Html.DisplayNameFor(model => model.WebPageTitle)
@Html.DisplayFor(model => model.WebPageTitle)
<br />
Zmieniłem
@foreach (var item in Model) {
Do
@foreach (var item in Model.Sites) {
I skomentował sekcję tr, która na razie zawiera wszystkie nagłówki tabeli. Wszystko działa doskonale, z wyjątkiem tego, że @ Html.DisplayNameFor wyświetla nazwę zmiennej „WebPageTitle” zamiast „Tytuł strony sieci Web”, jak wskazano w atrybucie Wyświetlanie adnotacji danych w
[Display(Name = "Web Page Title")]
public string WebPageTitle;
Również jeśli komentuję z powrotem w sekcji tr zawierającej informacje nagłówka tabeli. Nie mogę przez całe życie dowiedzieć się, co włożyć Próbowałem modelu.Sites.Abbreviation, model.Sites [0]. Skrót i różne inne kombinacje, ale pojawiają się błędy.
<tr>
<th>
@Html.DisplayNameFor(model => model.Abbreviation)
</th>
<th>
@Html.DisplayNameFor(model => model.DisplayName)
</th>
<th></th>
</tr>
Co więc powinienem tam wykorzystać? Nie jestem pewien, dlaczego model.Sites.Abbreviation nie działa, ponieważ Sites to dokładnie ten sam typ, który był używany jako model w oryginalnym Index.cshtml