2016-05-27 2 views
2

TL; DR: Я хочу:Реализация отложенной загрузки иерархического StackLayout в Xamarin форм

  1. Сохранить некоторые C# объект в каждом StackLayout
  2. Использование информации из этого объекта, чтобы сделать еще StackLayouts, если пользователь хочет Это.

Детали:

Я хочу, чтобы отобразить все HTML DOM дерево объектов некоторых веб-сайта в виде списка.

Я использую Html Agility Pack для управления загруженным html. Он создает объекты списка HtmlNode, у которых есть некоторые HtmlNodes как дети, у которых есть некоторые HtmlNodes как дети и т. Д. (Как и в HTML DOM).

Это то, что я в настоящее время:

private StackLayout GenerateTreeOfHtmlObjects(HtmlNode htmlNode, int padding) 
    { 
     StackLayout stackLayout = new StackLayout(); 
     stackLayout.Orientation = StackOrientation.Vertical; 
     foreach (var childNode in htmlNode.ChildNodes) 
     { 
      if (childNode.Name != "#text") 
      { 
       Button showMoreButton = new Button { Text = ">", HorizontalOptions = LayoutOptions.Start, }; 

       stackLayout.Children.Add(
        new StackLayout 
        { 
         Children = { 
          showMoreButton, 
          new Label { Text = childNode.Name, FontSize=20 }, 
          new Label { Text = new string(childNode.InnerText.Trim().ToCharArray().Take(30).ToArray()), FontSize=15 }, 
          new Button { Text = "Zaznacz" }, 
          GenerateTreeOfHtmlObjects(childNode, padding+10) //RECURSION, CALL THIS FUNCTION AGAIN AS LONG AS THERE ARE SOME CHILDREN 
         }, 

         Padding = new Thickness(padding, 0, 0, 10) 
        } 
       ); 
      } 
     } 
     return stackLayout; 
    } 

Как вы видите, я создаю StackLayout для каждого HtmlNode и добавить еще StackLayouts для своих детей. Он работает более или менее, как я хотел, но проблема в занимает слишком много памяти и занимает очень много времени, чтобы загрузить.

Так что я хочу, чтобы загрузил детей из некоторых HtmlNode, только если пользователь нажмет на их родителей. Я загружу только те HtmlNodes, которые находятся на вершине дерева и будут последовательно загружать своих детей, если они понадобятся.

Для этого Мне нужно хранить где-нибудь в каждой StackLayout информацию о том, что загрузить, если пользователь нажмет на нее. Каждый загруженный StackLayout должен иметь назначенный класс HtmlNode, который позволит мне загружать дочерние элементы HtmlNode (каждый HtmlNode имеет переменную ChildNodes, и я буду получать информацию оттуда)

+0

Вы можете создать собственный файл stacklayout с определенными атрибутами (например, classname), а затем использовать значения ваших атрибутов, чтобы определить, в какой из них находится stacklayout. –

+0

Используйте шаблон MVVM. Затем у вас будет ViewModel, который содержит всю информацию о представлении. см: https: //developer.xamarin.com/guides/xamarin-forms/user-interface/xaml-basics/data_bindings_to_mvvm/ –

ответ

3

Используйте шаблон MVVM. Затем у вас будет ViewModel, который содержит всю информацию о представлении. см: https://developer.xamarin.com/guides/xamarin-forms/user-interface/xaml-basics/data_bindings_to_mvvm/

 //// MODEL    
     public class HtmlNode 
     { 
      public List<HtmlNode> Children{get; set;} 
     } 

     //// VIEW-MODEL 
     public class HtmlTreeViewModel 
     { 
      public HtmlNode RootNode {get; set;} 

      public List<HtmlNode> TreeItems{get; set;} 
      ICommand ItemClickedCommand; 
      public HtmlTreeViewModel() 
      { 
      // Get Initial Items 
      TreeItems = GenerateTreeOfHtmlObjects(RootNode); 
      ItemClickedCommand = new Command(ItemClickCommadFunc); 
      } 

      private List<HtmlNode> ItemClickCommadFunc(object itemClicked) 
      { 
       // Fill Children for specific node 
       HtmlNode node =(itemClicked as HtmlNode); 
       node.Children = GenerateTreeOfHtmlObjects(node); 
      } 

     } 


     //// VIEW 
    //This is the datatemplate for each item (you can add name and other stuff) 
    //should be defined in resources 
    <DataTemplate x:key="NodeTemplate"> 
     <StackLayout ItemSource="{Binding Children}"> 
     </StackLayout> 
    </DataTemplate> 

    //this is the StackLayout that represent the whole tree 
    <StackLayout ItemsSource="{Binding RootItem.Children}" ItemTemplate=" StaticResource NodeTemplate}"/> 

Это просто чтобы дать вам представление о том, что вам придется соединить точки самостоятельно. Не забудьте назначить BindingContext в StackPanel и при необходимости поднять PropertyChanged.

Смежные вопросы