8

Mam częściowy widok w projekcie MVC 4, który jest silnie wpisany. Wymaga zbioru IEnumerable zbioru bazy danych. W tej tabeli znajdują się identyfikatory, nazwy i identyfikatory ParentID do przechowywania hierarchicznego połączenia między rekordami. Pogląd, że wywołuje częściowy widok jest również silnie wpisane, trwa całą bazę danych jako modelu i przekazuje tabelę kategorię do częściowego widzenia, jako przeliczalnego kolekcji:ASP.NET MVC 4 generowanie widoku drzewa z rekurencyjnym widokiem częściowym

@Html.Partial("_TreeCategories", @Model.Categories.ToList()) 

I częściowego widzenia, chcę najpierw wziąć węzły główne, więc mogę rozciągnąć całe drzewo w sposób rekursywny. W tabeli bazy danych wszystkie rekordy są uważane za węzły główne z ParentID == null.
Więc ogólnie, moim sposobem na to będzie wyglądać:

@model IEnumerable<TreeCollections.OpenAccess.Category> 

@if (Model.ToList().Count >= 0) 
    { 
    @if (Model.ToList()[0].Parent_id == null) 
    { 
     <text><ul id="navigation"></text> 
    } 

    @foreach (var node in @Model) 
    { 
     <li><a href="[email protected]">@node.Name</a> 
      @foreach (var subNode in @Model.Where(s => s.Parent_id == node.Id)) 
      { 
       @Html.Partial("_TreeCategories", subNode) 
      } 
     </li> 
    } 
    @if (Model.ToList()[0].Parent_id == null) 
    { 
     </ul> 
    } 
} 

więc sprawdzić, czy pierwszy element w ParentID modelu jest null, a jeśli tak, to należy go utworzyć < ul> tag id "navigation", więc plugin jquery może rozpoznać, że ma to być kontrola widoku drzewa. Następnie tworzy tag listy z wywołaniem rekurencyjnym wewnątrz. Wywoływany rekursywnie widok częściowy uwzględnia dzieci węzła jako model. I na koniec, jeśli doszliśmy do końca renderowania częściowego widoku, a my jesteśmy na "poziomie głównym", powinno się napisać zamykający ul> tag
Jednak są pewne problemy. Po pierwsze, na końcu, że zamknięcie nieuporządkowanego tagu listy jest błędne, VS nie może odnaleźć pasującego do niego znacznika początkowego. Po drugie, nie wiem dlaczego, ale na górze mogę wstawić tag startowy < między tagami i nie mogę tego zrobić na poniższym tagu zamykającym. Ale nie jestem pewien na temat tych tagów ul> <, też uważam, że są one błędne.
Proszę, pomóżcie mi, utknąłem z tym od wielu dni.

Odpowiedz

15

Człowieku, masz tu trochę wygranych. Czuję twój ból na utknięciu.

Sprawdź, czy to pływa po twojej łodzi.

potrzebujesz wartości początkowej, aby śledzić, czego szukasz w aukcji, gdy wykonujesz rekursję na tej samej liście. lepiej jest zrobić mapowanie dzieci rodziców w klasie, ale to było fajne do zrobienia ze względu na twoją strukturę i powinno załatwić sprawę.

modele

namespace trash.Models 
{ 
    public class Category 
    { 
     public int ID { get; set; } 
     public int? Parent_ID { get; set; } 
     public string Name {get; set;} 
    } 

    public class SeededCategories 
    { 
     public int? Seed { get; set; } 
     public IList<Category> Categories { get; set; } 
    } 
} 

Controller (UWAGA: uruchomić łańcuch rekurencji poprzez ustawienie właściwości Seed null który będzie zebrać wszystkie zerowe rodziców)

namespace trash.Controllers 
{ 
    public class HomeController : Controller 
    { 
     public ActionResult Index() 
     { 
      IList<trash.Models.Category> categories = new List<trash.Models.Category>(); 
      categories.Add(new trash.Models.Category { ID = 1, Parent_ID = null, Name = "Top1" }); 
      categories.Add(new trash.Models.Category { ID = 2, Parent_ID = null, Name = "Top2" }); 
      categories.Add(new trash.Models.Category { ID = 3, Parent_ID = 1, Name = "Top1Ring1" }); 
      categories.Add(new trash.Models.Category { ID = 4, Parent_ID = 1, Name = "Top1Ring2" }); 

      trash.Models.SeededCategories model = new Models.SeededCategories { Seed = null, Categories = categories }; 
      return View(model); 
     } 
    } 
} 

Odwiedzin Index

@model trash.Models.SeededCategories 

Here's a list 
@Html.Partial("_TreeCategories", Model) 

Częściowa (twoje _TreeCategories.) UWAGA: ustaw Nasiono na prąd ID węzła i Volia rekurencji)

@model trash.Models.SeededCategories 

@if (Model.Categories.Where(s => s.Parent_ID == Model.Seed).Any()) 
{ 
    <ul> 
     @foreach (var node in Model.Categories) 
     { 
      if (node.Parent_ID == Model.Seed) 
      { 
       trash.Models.SeededCategories inner = new trash.Models.SeededCategories { Seed = node.ID, Categories = Model.Categories }; 
      <li><a href="[email protected]">@node.Name</a> 
       @Html.Partial("_TreeCategories", inner) 
      </li> 
      } 
     } 
    </ul> 
} 
+0

Dziękuję, to jest tak oczywiste, a jednak przez kilka dni nie mogłem się z tym pogubić ... Właśnie przeinstalowałem cały system na moim komputerze, to zajmuje trochę czasu, zanim ponownie pobiorę i zainstaluję Visual Studio, aby spróbować ale przynajmniej teraz widzę ten wzór! Dziękuję bardzo! – user2082422

+0

w większości przypadków, z przyjemnością pomogę –

+0

Przy okazji, jaki rodzaj mapowania rodzic-dziecko polecacie? Wybrałem tę metodę "ID - ParentID", ponieważ jest to jeden ze sposobów implementacji hierarchicznej struktury danych w relacyjnym kodzie danych, takim jak baza danych. W tabeli ID kategorii jest klucz podstawowy, ParentID to klucz obcy, który odnosi się do Categories.ID. – user2082422

1

Można spróbować Tarcza UI rekurencyjne TreeView for ASP.NET MVC.

Umożliwia określenie wszystkich elementów TreeView za pomocą obiektu RecursiveDataSource, który można skonfigurować do pobierania danych dla elementu drzewa ze zdalnego punktu końcowego lub lokalnego źródła "leniwie", za każdym razem, gdy element jest rozwijany.

RecursiveDataSource jest opakowaniem wokół widgetu JavaScript DS, który wprowadza potrzebę kodu JS, a także aktualizację kodu serwera, który dostarczy dane (wdrożenie usługi sieciowej lub umieszczenie danych w JS) zmienna w twoim widoku).

+0

Link do potencjalnego rozwiązania jest zawsze mile widziany, ale proszę [dodaj kontekst związany z linkiem] (// meta.stackoverflow.com/a/8259), aby inni użytkownicy mieli pojęcie, co to jest i dlaczego tam jest. Zawsze podawaj najważniejszą część ważnego linku, na wypadek, gdyby strona docelowa była nieosiągalna lub stała w trybie offline. Weź pod uwagę, że bycie "stanowiącym coś więcej niż link do strony zewnętrznej" jest możliwym powodem [Dlaczego i jak niektóre odpowiedzi zostały usunięte?] (// stackoverflow.com/help/deleted-answers). – FrankerZ

+0

Zaktualizowano odpowiedź –