Jak przerobić funkcję iterowania TreeView na klasę?

0

Mam problem z tą funkcją
http://msdn.microsoft.com/pl-pl/library/wwc698z7%28v=vs.110%29.aspx

 
private void PrintRecursive(TreeNode treeNode)
{
   // Print the node.
   System.Diagnostics.Debug.WriteLine(treeNode.Text);
   MessageBox.Show(treeNode.Text);
   // Print each node recursively.
   foreach (TreeNode tn in treeNode.Nodes)
   {
      PrintRecursive(tn);
   }
}

// Call the procedure using the TreeView.
private void CallRecursive(TreeView treeView)
{
   // Print each node recursively.
   TreeNodeCollection nodes = treeView.Nodes;
   foreach (TreeNode n in nodes)
   {
      PrintRecursive(n);
   }
}

Potrzebuje z tego zmiennej z nazwą którą mogę użyć w kodzie z nie wyświetlać MessageBox z nią. Przerabiając natrafiłem na problem.

 
    class iterowanie
    {
        ////////iterowanie wszystkich węzłów formantu TreeView
        public void iterowanie(TreeNode treeNode)
        {
            string dana = treeNode.Text;
            return dana;  //dane muszą być przekazane z tego miejsca bo inaczej nie wyświetli wszystkich danych

            foreach (TreeNode tn in treeNode.Nodes)
            {
                iterowanie(tn);
            }
        }
    }

        private void button7_Click(object sender, EventArgs e)
        {
            string zmienna = null;
            iterowanie iter = new iterowanie();
         
            TreeNodeCollection nodes = treeView1.Nodes;
            foreach (TreeNode n in nodes)
            {
                zmienna = iter.iterowanie(n);
            }

            MessageBox.Show(zmienna); //MessageBox tylko przykładowo
        }

błąd w klasie
"Błąd 2 The type or namespace name 'TreeNode' could not be found (are you missing a using directive or an assembly reference?)"
"'iterowanie': member names cannot be the same as their enclosing type"
Jak by było prościej to jak wydobyć interesujące mnie dane z oryginalnej funkcji.

0

Przenieś kursor myszy nad TreeNode, pojawi się taka czerwona kreska pod tym słowem, kliknij i wybierz using cośtam. Lub kliknij na TreeNode i wciśnij Alt+Shift+F10.

Potrzebuje z tego zmiennej z nazwą którą mogę użyć w kodzie z nie wyświetlać MessageBox z nią

Jak by było prościej to jak wydobyć interesujące mnie dane z oryginalnej funkcji.

Zamiast MessageBox.Show() wstawiasz swoją metodę DoWhatYouWant(treeNode.Text) i robisz co tam chcesz. Nie możesz zwrócić returnem zmiennej bo to przerwie metodę.

0

jeszcze mam problem z "'iterowanie': member names cannot be the same as their enclosing type"

0

Nazwa metody nie może być taka sama jak nazwa klasy, to musiałby być konstruktor. Po prostu zmień te nazwy.

0

Już tego próbowałem i mi wyświetla "Ostrzeżenie Unreachable code detected" przez co pomija mi tą część programu.

 
    class iterowanie
    {
        ////////iterowanie wszystkich węzłów formantu TreeView
        public string iterowanieq(TreeNode treeNode)
        {
            string dana = treeNode.Text;
            return dana;  //dane muszą być przekazane z tego miejsca bo inaczej nie wyświetli wszystkich danych

            foreach (TreeNode tn in treeNode.Nodes) //treeNode.Nodes - "Unreachable code detected"
            {
                iterowanieq(tn);
            }
        }
    }

        private void button4_Click(object sender, EventArgs e)
        {
            //treeView1.Nodes[0].Nodes[1].Text = "a";
            //MessageBox.Show(treeView1.Nodes[0].Nodes[1].Text);

            string zmienna = null;
            iterowanie iter = new iterowanie();

            TreeNodeCollection nodes = treeView1.Nodes;
            foreach (TreeNode n in nodes)
            {
                zmienna = iter.iterowanieq(n);
            }

            MessageBox.Show(zmienna); //MessageBox tylko przykładowo
        }
0

A co tam robi return dana;? Tego nie może tam być to przerywa metodę i dalszy kod się nigdy nie wykona. Może powiedz co ty chcesz zrobić.

class Iterowanie
    {
        ////////iterowanie wszystkich węzłów formantu TreeView
        public string Iteruj(TreeNode treeNode)
        {
            RóbCoś(treeNode.Text);
 
            foreach (TreeNode tn in treeNode.Nodes) //treeNode.Nodes - "Unreachable code detected"
            {
                Iteruj(tn);
            }
        }
        void RóbCoś(string str)
        {
             //tu robisz to co chcesz 
        }
    }

Szczerze to ja nie widzę w ogóle potrzeby wydzielania tego do innej klasy.

0

ogólnie to temat zacząłem tu
Automatyczne uzupełnienie treeView za pomocą numerów kategorii nadrzędnych
ale twój kod jest dla mnie trochę nie jasny to męczę się ze swoim pomysłem na rozwiązanie tego problemu.
Pierwsze kategorie zerowe zapisuję w treeView1.
Pobieram Identyfikator kategorii (catParent) i porównuję ją z Identyfikator kategorii (catId) z treeView1. Jeżeli jest równy to zapisuję go jako podkategoria.
Po wczytaniu wszystkich kategorii przelecę jeszcze raz cały treeView zmieniając Identyfikator kategorii (catId) na nazwę.

Kod podany na samym początku działa ale nie wiem jak z niego wydobyć na zewnątrz tę daną.

0

A czy tamten mój kod kod działa? Sprawdzałeś?
Nie musisz wszystkiego rozumieć, ważne że umiesz go użyć.

0

nie działa wyskakują błędy
"The type or namespace name 'Diagnostic' does not exist in the namespace 'System' (are you missing an assembly reference?) "
3x "Cannot apply indexing with [] to an expression of type 'allegro.webapi.CatInfoType'"

0

Pierwszy błąd to jest literówka powinno być Diagnostics, ale tą linijka nie jest potrzebna, to miało tylko wypisać czy wszystkie dane się dodały.
A to drugie to źle zrozumiałem co zwraca doCatsData.
Po prostu dla każdej kategori którą dostaniesz (nie wiem jak to robisz) używaj metody

AddNode(item[2], item[0], item[1], treeView1)

Pierwszy parametr to id parenta, drugi id samej kategorii, trzeci nazwa jaką ma wyświetlić, kolejny twój TreeView.

Może wyjaśnie jak to działa:

TreeNode lastParentNode = null; //zapisuje ostatni parent do jakiego się dodawało item
        bool AddNode(string parentId, string id, string text, TreeView treeView)
        {
            //tworzenie nowego itemu
            var newNode = new TreeNode(text);
            newNode.Tag = id;
 
            if(parentId == "0")//sprawdzanie czy jest to kategoria zerowa
            {
                treeView.Nodes.Add(newNode);
                return true;
            }
            else if(lastParentNode!=null && lastParentNode.Tag.ToString() == parentId) // jeśli nie to sprawdza czy może ostatni parent do jakiego się dodało pasuje też do kolejnego
            {
                lastParentNode.Nodes.Add(newNode);
                return true;
            }
            else // jeśli nie to przeszukuje całe drzewo
            {
                foreach (TreeNode n in treeView.Nodes)// jełśli znajdzie pasujący parent to zapisuje go na lastParentNode i dodaje do niego nowy item
                {
                    lastParentNode = FindById(parentId, n);
                    if (lastParentNode != null) 
                        break;
                    else
                    {
                        lastParentNode.Nodes.Add(newNode);
                        return true;
                    }
 
                }
            }
            return false;
        }
 
        TreeNode FindById(string itemId, TreeNode rootNode)//wyszukwanie po całym drzewie
        {
            foreach (TreeNode node in rootNode.Nodes)
            {
                if (node.Tag.Equals(itemId)) return node;
                TreeNode next = FindById(itemId, node);
                if (next != null) return next;
            }
            return null;
        }
0

w AddNode linijce "lastParentNode.Nodes.Add(newNode);" wystąpił błąd już po skompilowaniu "An unhandled exception of type 'System.NullReferenceException' occurred in allegro.exe"

0

Tu zamień

if (lastParentNode != null) 
                        break;

znak != na ==

0

Coś się już wyświetla w treeView1 a dokładnie wszystkie główne kategorie. Nie dodaje podkategorii. Nie ogarnąłem działania kodu ale trzeba porównać "identyfikator kategorii nadrzędnej" (catParent) z "identyfikatorem kategorii" (catId) już dodanych kategorii do treeView1. Tylko kategorie główne które mają 0 w "identyfikator kategorii nadrzędnej" muszą być dodane bez sprawdzenia.

0

Wiem o tym. Spróbuj w metodzie FindById zamiast

 if (node.Tag.Equals(itemId)) return node;

dać

 if (node.Tag.ToString() == itemId) return node;
0

Nic to nie dało. Dalej tylko główne wyświetla

0

Dobra teraz działa, zastąp te stare metody.

TreeNode lastParentNode = null;
        bool AddNode(string parentId, string id, string text, TreeView treeView)
        {
            var newNode = new TreeNode(text);
            newNode.Tag = id;

            if (parentId == "0")
            {
                treeView.Nodes.Add(newNode);
                return true;
            }
            else
            {
                foreach (TreeNode n in treeView.Nodes)
                {
                    lastParentNode = FindById(parentId, n);
                    if (lastParentNode != null)
                    {
                        lastParentNode.Nodes.Add(newNode);
                        return true;
                    }

                }
            }
            return false;
        }

        TreeNode FindById(string itemId, TreeNode rootNode)
        {
            if (rootNode.Tag.Equals(itemId)) return rootNode;
            foreach (TreeNode node in rootNode.Nodes)
            {
                if (node.Tag.Equals(itemId)) return node;
                TreeNode next = FindById(itemId, node);
                if (next != null) return next;
            }
            return null;
        }
0

działa:) możesz trochę opisać kod żebym mógł go zrozumieć?

 
        private void button4_Click(object sender, EventArgs e)
        {
            foreach (CatInfoType item in ty)
            {
                AddNode(item.catParent.ToString(), item.catId.ToString(), item.catName, treeView1); //przekazanie danych z allegro doGetCatsData do AddNode                 
            }
        }

       TreeNode lastParentNode = null;
        bool AddNode(string parentId, string id, string text, TreeView treeView)
        {
            var newNode = new TreeNode(text); //przypisanie nazwy kategorii
            newNode.Tag = id; //przypisanie id kat - tego nie rozumiem na jakiej zasadzie to ma działać i po co to jest 

            if (parentId == "0") //tu sprawdza główne kat
            {
                treeView.Nodes.Add(newNode); //dodanie kat do treeView1
                return true;
            }
            else
            {
                foreach (TreeNode n in treeView.Nodes) //jeżeli warunek nie jest spełniony to przeszukuje istniejące już kategorie w treeView1
                {
                    lastParentNode = FindById(parentId, n); //przekazanie parentId i nazwy z treeView1
                    if (lastParentNode != null) //sprawdzenie czy można dodać nową kat
                    {
                        lastParentNode.Nodes.Add(newNode);
                        return true;
                    }

                }
            }
            return false;
        }

        TreeNode FindById(string itemId, TreeNode rootNode) //to nie wiem co robi, podejrzewam że wchodzi w podkatalogi
        {
            if (rootNode.Tag.Equals(itemId)) return rootNode; 
            foreach (TreeNode node in rootNode.Nodes)
            {
                if (node.Tag.Equals(itemId)) return node;
                TreeNode next = FindById(itemId, node);
                if (next != null) return next;
            }
            return null;
        }
0
newNode.Tag = id; //przypisanie id kat - tego nie rozumiem na jakiej zasadzie to ma działać i po co to jest 

Wszystkie kontrolki (TreeView, Label, Textbox itp) mają właściwość Tag typu object. Co oznacza że możesz tam wrzucić co chcesz, ja akurat wrzuciłem id.

lastParentNode = FindById(parentId, n); //przekazanie parentId i nazwy z treeView1
                    

FindById przeszukuje rekursywnie treeView (podobnie jak metoda PrintRecursive z pierwszego posta w tym temacie). Wcześniej do każdego nowgo Node dodawało się id do Tag, ta metoda sprawdza każdy Tag czy zawiera take samo id jak przekazane w parametrze jeśli znajdzie to zwraca ten node jeśli nie ma takiego id nigdzie to zwraca null.
Czegoś jeszcze nie rozumiesz?

0

Jest możliwość umieszczenia tego kodu w wątku? Bo pobieranie danych długo trwa i nie mogę w tym czasie nic robić z formą. Wątek uruchamiałby się podczas ładowania Form1 i tylko po kliknięciu wyświetlała by się forma już z wczytanymi danymi w Treeviewe

1
private void FillTreeView()
        {
            foreach (CatInfoType item in ty)
            {
                AddNode(item.catParent.ToString(), item.catId.ToString(), item.catName, treeView1); //przekazanie danych z allegro doGetCatsData do AddNode                 
            }
        }
 
       TreeNode lastParentNode = null;
        bool AddNode(string parentId, string id, string text, TreeView treeView)
        {
            var newNode = new TreeNode(text); //przypisanie nazwy kategorii
            newNode.Tag = id; //przypisanie id kat - tego nie rozumiem na jakiej zasadzie to ma działać i po co to jest 
 
            if (parentId == "0") //tu sprawdza główne kat
            {
                InvokeIfRequired(treeView, new Action(() => treeView.Nodes.Add(newNode) )); //dodanie kat do treeView1
                return true;
            }
            else
            {
                foreach (TreeNode n in treeView.Nodes) //jeżeli warunek nie jest spełniony to przeszukuje istniejące już kategorie w treeView1
                {
                    lastParentNode = FindById(parentId, n); //przekazanie parentId i nazwy z treeView1
                    if (lastParentNode != null) //sprawdzenie czy można dodać nową kat
                    {
                        InvokeIfRequired(treeView, new Action(() => lastParentNode.Nodes.Add(newNode) ));
                        return true;
                    }
 
                }
            }
            return false;
        }
 
        TreeNode FindById(string itemId, TreeNode rootNode) //to nie wiem co robi, podejrzewam że wchodzi w podkatalogi
        {
            if (rootNode.Tag.Equals(itemId)) return rootNode; 
            foreach (TreeNode node in rootNode.Nodes)
            {
                if (node.Tag.Equals(itemId)) return node;
                TreeNode next = FindById(itemId, node);
                if (next != null) return next;
            }
            return null;
        }
        
        public static void InvokeIfRequired(Control control, Action action)
        {
            if (control.InvokeRequired)
                control.Invoke(action);
            else
                action();
        }

I startujesz to przez:

new Thread(FillTreeView).Start();
0

Macie może jakiś przykładowy kod jak obsługiwać lokalną bazę danych? Używam visual studio 2013 dodając bazę do projektu jak powinien wybrać "baza danych oparta o usługi" rozszerzenie .mdf czy "zestaw danych" z .xsd? Dokładnie chodzi o dane ściągnięte z powyższego kodu. Jednak za każdym razem ściągać tyle danych to trochę trwa. Program ściągałby dane tylko za pierwszym uruchomieniem a później sprawdzał czy zmieniła się wersja danych i czy został już ściągnięte dane(jako pierwsze uruchomienie).

0

A skąd będziesz wiedział czy dane się zmieniły bez pobrania ich? I jak długo trwa takie pobieranie?

0

w doGetCatsData jest możliwość pobrania verStr "Wersja komponentu struktury drzewa kategorii odpowiednia dla przekazanego klucza WebAPI."

0

A jesteś pewny że to pobieranie tak długo trwa, a nie przeszukiwanie drzewa? Nie odpowiedziałeś jak długo to trwa.

Zmodyfikowałem tu jedną metodę, podmień ją. Powinno mocno przyśpieszyć.

        bool AddNode(string parentId, string id, string text, TreeView treeView)
        {
            var newNode = new TreeNode(text); //przypisanie nazwy kategorii
            newNode.Tag = id; //przypisanie id kat - tego nie rozumiem na jakiej zasadzie to ma działać i po co to jest 
 
            if (parentId == "0") //tu sprawdza główne kat
            {
                InvokeIfRequired(treeView, new Action(() => treeView.Nodes.Add(newNode) )); //dodanie kat do treeView1
                return true;
            }
            else if (lastParentNode != null && lastParentNode.Tag.ToString() == parentId)
            {
                InvokeIfRequired(treeView, new Action(() => lastParentNode.Nodes.Add(newNode) ));
                return true;
            }
            else
            {
                foreach (TreeNode n in treeView.Nodes) //jeżeli warunek nie jest spełniony to przeszukuje istniejące już kategorie w treeView1
                {
                    lastParentNode = FindById(parentId, n); //przekazanie parentId i nazwy z treeView1
                    if (lastParentNode != null) //sprawdzenie czy można dodać nową kat
                    {
                        InvokeIfRequired(treeView, new Action(() => lastParentNode.Nodes.Add(newNode) ));
                        return true;
                    }
 
                }
            }
            return false;
        }
0

Dokładnie 108,01s (108011ms) liczone za pomocą Stopwatch. Zaraz sprawdzę ten nowy kod.

0

Wynik 105,009s wynik trochę lepszy ale nie zadowalający. Kategorii jest 23816

0

Upewnij się może co zajmuje tyle czasu, bo jeśli nie pobieranie to wrzucenie tego do bazy nic nie da.

0

pobranie to niecałe 50s. Jak byś miał jakieś materiały do tworzenia lokalnej bazy w VS 2013 to pokombinowałbym jutro z tym kodem.

0

Nigdy nic w tym nie robiłem, ale wszystko jest do znalezienia w google.
http://msdn.microsoft.com/en-us/library/ms233763.aspx

Ale pobieranie to nie twoje jedyne zmartwienie. Drugie 50 sekund trwa wrzucanie wszystkiego do treeview. Dlatego ja bym proponował przy uruchamianiu aplikacji wczytywać do treeview tylko kategorie gdzie parentId jest 0. A po kliknięciu na kategorie w treeview pobrać z bazy tylko bezpośrednie podkategorie i dodać do treeview. W ten sposób nie będzie ładowało wszystkiego a tylko to co jest akurat potrzebne.

0

jeszcze mam pytanie co do kodu. Co poniższe fragmenty robią i jak działają? Chciałbym dodać progressBar i pewnie powinien znajdować się w InvokeIfRequired

 
InvokeIfRequired(treeView, new Action(() => lastParentNode.Nodes.Add(newNode)));
//...//
        public static void InvokeIfRequired(Control control, Action action) 
        {
            if (control.InvokeRequired)
                control.Invoke(action);
            else
                action();
        }

1 użytkowników online, w tym zalogowanych: 0, gości: 1