Przekaż dodatkowe ViewData do widoku częściowego z silną typizacją

174

Mam mocno wpisany Widok częściowy, który pobiera ProductImage i kiedy jest renderowany, chciałbym również udostępnić mu dodatkowe ViewData, które tworzę dynamicznie na stronie zawierającej. Jak mogę przekazać zarówno mój obiekt o jednoznacznie określonym typie, jak i moje niestandardowe ViewData do widoku częściowego za pomocą wywołania RenderPartial?

var index = 0;
foreach (var image in Model.Images.OrderBy(p => p.Order))
{
  Html.RenderPartial("ProductImageForm", image); // < Pass 'index' to partial
  index++;
}
Nathan Taylor
źródło

Odpowiedzi:

251

RenderPartial przyjmuje inny parametr, który jest po prostu ViewDataDictionary. Już prawie gotowe, po prostu nazwij to tak:

Html.RenderPartial(
      "ProductImageForm", 
       image, 
       new ViewDataDictionary { { "index", index } }
); 

Zwróć uwagę, że spowoduje to przesłonięcie domyślnych ViewData, które domyślnie mają wszystkie inne widoki. Jeśli dodajesz cokolwiek do ViewData, nie będzie to w nowym słowniku, który przekazujesz do widoku częściowego.

womp
źródło
2
Próbuję to zrobić i zwraca „nie można przekształcić void w obiekt”.
programad
4
@programad Spróbuj usunąć @ z @ Html.RenderPartial (), to rozwiązało ten problem, ale wywoływałem RenderPartial () w wierszu wewnątrz bloku kodu @ {}.
danjarvis
5
Polecam sprawdzić odpowiedź ctorx poniżej. Dodaje dodatkowe dane do istniejących ViewData.
raRaRa
162

Aby przedłużyć na co womp pisał, to może przekazać nowy widok danych przy zachowaniu istniejącego widoku danych, jeśli użyć przeciążenie konstruktora ViewDataDictionarytak:

Html.RenderPartial(
      "ProductImageForm", 
       image, 
       new ViewDataDictionary(this.ViewData) { { "index", index } }
); 
ctorx
źródło
3
może to być bardzo przydatne, jeśli chcesz zachować TemplateInfo.HtmlFieldPrefixkontrolę podrzędną, która zostanie zresetowana w przeciwnym razie
Simon_Weaver
12
To zdecydowanie lepsze rozwiązanie. Utrata ViewData oznacza utratę ModelState i wszystkich walidacji. +1
Kevin Farrugia
Wydaje się, że działa to tylko wtedy, gdy nie przekażesz TemplateInfo.HtmlFieldPrefix w swoim ViewDataDictionary. Mogę tylko przekazać zmienną, jak pokazano w odpowiedzi, lub przekazać TemplateInfo.HtmlFieldPrefix, ale nie oba.
Ferox,
45
@Html.Partial("_Header", new ViewDataDictionary { { "HeaderName", "User Management" }, { "TitleName", "List Of Users" } })
or
@{Html.RenderPartial("_Header", new ViewDataDictionary { { "HeaderName", "User Management" }, { "TitleName", "List Of Users" } });}

Częściowa strona (_Header):

<div class="row titleBlock">
    <h1>@ViewData["HeaderName"].ToString()</h1>
    <h5>@ViewData["TitleName"].ToString()</h5>
</div>
muthuvel
źródło
2
Wydaje się, że jest to najbardziej kompletna odpowiedź (chociaż .ToString () jest niepotrzebna).
Colin,
9

Myślę, że to powinno działać, nie?

ViewData["currentIndex"] = index;
Joel Martinez
źródło
6
Chociaż nie jest to zbyt mocny sposób, aby to zrobić, pomógł mi dowiedzieć się, jak odzyskać wartość danych widoku z odpowiedzi Wompa.
Mathias Lykkegaard Lorenzen
6

Utwórz kolejną klasę, która zawiera klasę o jednoznacznie określonym typie.

Dodaj nowe rzeczy do klasy i zwróć je w widoku.

Następnie w widoku upewnij się, że odziedziczyłeś nową klasę i zmień bity kodu, które teraz będą błędne. mianowicie odniesienia do twoich dziedzin.

Mam nadzieję że to pomoże. Jeśli nie, daj mi znać, a prześlę konkretny kod.

griegs
źródło
4

Najłatwiejszym sposobem przekazania dodatkowych danych jest dodanie danych do istniejących ViewData dla widoku jako notatki @Joel Martinez. Jeśli jednak nie chcesz zanieczyszczać swoich ViewData, RenderPartial ma metodę, która przyjmuje trzy argumenty, a także wyświetlaną wersję dwuargumentową. Trzeci argument to ViewDataDictionary. Możesz utworzyć oddzielny ViewDataDictionary tylko dla części zawierającej tylko dodatkowe dane, które chcesz przekazać.

tvanfosson
źródło
1

To też powinno działać.

this.ViewData.Add("index", index);

Html.RenderPartial(
      "ProductImageForm", 
       image, 
       this.ViewData
); 
MithunChopda
źródło
Dzięki! Jest to bardzo przydatne, gdy jesteś rozszerzenie słownika ViewData dla partials dziecko etc
developius
1

Wiem, że to stary post, ale natknąłem się na niego, gdy miałem podobny problem z rdzeniem 3.0, mam nadzieję, że komuś pomoże.

@{
Layout = null;
ViewData["SampleString"] = "some string need in the partial";
}

<partial name="_Partial" for="PartialViewModel" view-data="ViewData" />
Drytin
źródło
0

Możesz użyć dynamicznej zmiennej ViewBag

ViewBag.AnotherValue = valueToView;
Jack1987
źródło