|
Îåêßíçóå áðü ôï ìÝëïò mclisme. Τελευταία δημοσίευση από το μέλος mclisme στις 16-12-2008, 15:38. Υπάρχουν 10 απαντήσεις.
-
13-12-2008, 14:18
|
-
mclisme
-
-
-
Μέλος από τις 13-11-2008
-
-
Δημοσιεύσεις 23
-
-
|
Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Το πρόβλημα που αντιμετωπίζω είναι το εξής: Έχω ένα treeview με treenodes καθώς και παιδιά treenodes που περιέχονται σε αυτά κτλ. κτλ. Σε κάποιο σημείο θέλω να ελέγχω τις τιμές της ιδιότητας .text όλων των treenodes μου, (Παιδιά και Γονείς) και το κάνω χρησιμοποιώντας μια απλή συνάρτηση και την λογική της αναγωγής (recursion), η συνάρτηση μου δουλεύει μια χαρά και αυτό γιατί έχω διαπιστώσει ότι περνά από όλα τα treenodes του δένδρου μου και εκτελεί επιτυχημένα όποια διαδικασία ορίζω κάθε φορά. Εκτός απο μία! Αυτήν της αντιγραφής-κλωνοποίησης με την μέθοδο Clone. Και γίνομαι ευθύς πιο συγκεκριμένος, η αναγωγική διαδικασία μέσω της οποίας περνώ από όλα τα treenodes είναι η ακόλουθη:
For Each n As TreeNode In TreeView1.Nodes foo(n, testname) Next
Private Sub foo(ByVal n As TreeNode, ByVal name As String) If n.Text = name Then n.Nodes.Clear() ' <--- προστέθηκε μόνο για δοκιμή n = TreeView1.Nodes(2).Clone Exit Sub End If For Each nc As Treenode In n.Nodes foo(nc, name) Next End Sub
Δηλαδή για κάθε treenode που βρίσκεται στο 1ο επίπεδο του δένδρου καλείται η foo(n, name) και αν το .text του συγκεκριμένου node είναι ίσο με την name που έχει δηλωθεί πιο πριν θέλω το συγκεκριμένο treenode να γίνεται πιστό αντίγραφο του τρίτου treenode (το index ξεκινά απο 0) και να σταματά για το συγκεκριμένο treenode ο περαιτέρω έλεγχος, αλλιώς να καλείται εκ νέου η foo για όλα τα παιδιά του. Όσον αφορά την λογική είναι σωστή γιατί την έχω χρησιμοποιήσει αυτούσια πολλές φορές όταν θέλω να περάσω από όλα τα treenodes και να κάνω κάτι σε αυτά. Στην συγκεκριμένη περίπτωση όμως γίνεται το εξής: Όταν το κείμενο ενός treenode βρεθεί ίσο με την name ΔΕΝ πραγματοποιείται η επόμενη γραμμή με την εντολή Clone χωρίς να εμφανίζεται κάποιο μήνυμα λάθους. Επειδή αρχικά νόμισα ότι υπάρχει πρόβλημα στη συνθήκη και δεν μπαίνει καν στο If προσέθεσα την εντολή n.Nodes.Clear() . Το αποτέλεσμα ήταν η εντολή αυτή να πραγματοποιείται κανονικά! αρα μπαίνει στην συνθήκη, σβήνει όλα τα Nodes του συγκεκριμένου treenode, δεν πραγματοποιεί ομως την επόμενη εντολή που θέλω ουσιαστικά. Για κάποιο λόγο η Clone εδώ αφήνει το treenode ανεπηρρέαστο εντελώς. Αντίθετα οποιαδήποτε άλλη εντολή όπως να προσθέσω ένα στοιχείο στο συγκεκριμενο treenode, να το μετονομάσω, να το σβήσω εντελώς, πραγματοποιείται κανονικά! Ακόμα και στο debugging όταν βλέπω τα περιεχόμενα του treenode αμέσως μετά την Clone, μου δείχνει ότι έχει τα σωστά περιεχόμενα (αυτά του TreeView1.Nodes(2)) !!! όμως στο δένδρο εγώ δεν βλέπω τίποτα.
ΥΓ1. Δοκίμασα την TreeView1.Update() στην έξοδο της foo() αλλά και πάλι τίποτα... ΥΓ2. Δοκίμασα να αλλάξω τον τρόπο που περνά το όρισμα n στην foo απο ByVal σε ByRef αλλά και πάλι τίποτα...
|
|
-
15-12-2008, 19:05
|
-
infoCENTER
-
-

-
Μέλος από τις 15-01-2006
-
Αθήνα
-
Δημοσιεύσεις 280
-
-
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Χωρίς να έχω καταλάβει τι θες να κάνεις και με τον κώδικά που βλέπω είναι λογικό να μην βλέπεις τίποτα στο TreeView.
Η Clone δημιουργεί ένα καινούριο TreeNode. Τι θα το κάνεις αυτό; Θα το προσθέσεις στο TreeView; Αν ναι γράψε απλά TreeView1.Nodes.Add(n) αμέσως μετά το Clone και θα το δεις.
|
|
-
15-12-2008, 21:26
|
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Με όλα αυτά περί recursion, μάλλον χάνεται το τί θέλεις να κάνεις. Αν σκοπός σου είναι να επιστρέψεις το Node που ψάχνεις μέσω της παραμέτρου n θα αποτύχεις επειδή η n περνιέται ByVal και η τιμή της δεν αλλάζει. Με άλλα λόγια, στο n = TreeView1.Nodes(2).Clone δημιουργείς ένα αντίγραφου του 2ου κόμβου στη λίστα (γιατί άραγε) και μετά το πετάς στα ... σκουπίδια.
Όπως και να έχει, όλη η φασαρία είναι περιττή γιατί η TreeView.Nodes έχει τη μέθοδο Find η οποία ψάχνει και subnodes.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
15-12-2008, 22:33
|
-
mclisme
-
-
-
Μέλος από τις 13-11-2008
-
-
Δημοσιεύσεις 23
-
-
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Αυτό που θέλω να κάνω είναι να ψάξω όλα τα treenodes του δένδρου μου, και όταν βρω αυτό του οποίου το text είναι ίσο με μια τιμή (name) να το αντικαταστήσω απευθείας με ένα άλλο treenode (και όλα τα παιδιά του και τα παιδιά των παιδιών του), που για παράδειγμα στην συγκεκριμένη περίπτωση το έθεσα ίσο με το Treeview1.Nodes(2), θα μπορόυσε να είναι ένα οποιοδήποτε treenode object. Η διαδικασία επιτυγχάνεται με έμμεσο τρόπο, σβήνοντας το n και εισάγοντας στην θέση του ένα άλλο το οποίο έχει προηγουμένως κλωνοποιηθεί και περιέχει τα treenodes που θέλω όμως η ερώτηση μου είναι ακριβώς αυτή: Γιατί το n δέχεται να του αλλάξεις το .text, ή να του προσθέσεις ενα treenode και αυτή η αλλαγή να έχει αποδέκτη τα treenodes του δένδρου, παρόλο που είναι ByVal, σε αντίθεση με αυτό που γράφει ο Κύριος Κανναβός και θα περίμενα και εγώ, αλλά δεν δέχεται την Clone Method.
|
|
-
15-12-2008, 22:58
|
-
mclisme
-
-
-
Μέλος από τις 13-11-2008
-
-
Δημοσιεύσεις 23
-
-
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Συγγνώμη αλλά απο το MSDN διαβάζω οτι η Clone αντιγράφει πλήρως ενα treenode σε ένα υπάρχον και έτσι ακριβώς την έχω χρησιμοποιήσει στο πρόγραμμα μου ως τώρα με επιτυχία. Δηλαδή αν γράψω: Treeview1.Nodes(0) = Treeview1.Nodes(2).Clone, το node 0 θα γίνει ακιρβές αντίγραφο του 2, με ολά τα παιδιά και τα υπο-παιδιά του 2 κτλ. και θα εμφανιστεί κανονικά. Μέσα στη συνάρτηση foo το n όρισμα ουσιαστικά βλέπει κάθε φορά ένα υπαρκτό treenode αντικείμενο του δένδρου, και όποια αλλαγή υφίσταται το n, περνά σε κάποιο υπαρκτό treenode του δένδρου. Η λογική της αναγωγής την οποία προτείνει και η Microsoft για χειρισμό των treeviews με πολλά επίπεδα βάθους, είναι δοκιμασμένη με επιτυχία σε πολλές άλλες διαδικασίες που έχω κάνει ως τώρα στο πρόγραμμα εκτός της συγκεκριμένης. Εκτός αυτών, η εντολή που αναφέρεις δεν μπορεί να δουλέψει σωστά, πολύ απλά γιατί κάνει απευθείας αναφορά στο treenode, και που σημαίνει ότι αυτό πρέπει να βρίσκεται στο πρώτο επίπεδο, σαν παιδί του συνολικού treeview. Αν το n είναι παιδί ενός παιδιού, τότε δεν το βρίσκει, γιαυτό και πρέπει να περάσεις από όλα τα treenodes αναγκαστικά μέσω αναγωγής.
|
|
-
15-12-2008, 22:59
|
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Μάλλον δεν έχεις καταλάβει τί ακριβώς κάνει το ByVal. Το ByVal δεν σημαίνει ότι δεν μπορείς να αλλάξεις το n. Σημαίνει ότι δεν μπορείς να αντικαταστήσεις το αντικείμενο n με κάτι άλλο. Άνετα μπορείς να πειράξεις το κείμενο ή τα children του n γιατί το ίδιο το αντικείμενο n δεν παύει να υπάρχει. Όταν όμως πάς να κάνεις n = οτιδήποτε προσπαθείς να σβήσεις την τιμή του n και να την αντικαταστήσεις με κάτι άλλο. Αυτό απαγορεύεται να γίνει όταν δίνεις ByVal. Για να το κάνεις αυτό θα πρέπει να ορίσεις το n ByRef.
Τα ByVal και ByRef σημαίνουν By Value και By Reference αντίστοιχα. By Value σημαίνει ότι οτιδήποτε περνάς στο function περνάει ως τιμή και οποιαδήποτε τροποποίηση της τιμής χάνεται όταν επιστρέψεις. By Reference σημαίνει ότι περνάει όχι μόνο η τιμή αλλά και το ίδιο το variable που την περιέχει. Έτσι μπορείς να τροποποιήσεις το n και οι αλλαγές σου θα επιστρέψουν μετά το τέλος της μεθόδου.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
15-12-2008, 23:14
|
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
mclisme:Συγγνώμη αλλά απο το MSDN διαβάζω οτι η Clone αντιγράφει πλήρως ενα treenode σε ένα υπάρχον και έτσι ακριβώς την έχω χρησιμοποιήσει στο πρόγραμμα μου ως τώρα με επιτυχία.
Δεν λέει αυτό. Λέει ότι δημιουργεί ένα αντίγραφο. Όταν κάνεις εσύ το = αντικαθιστάς το node στα αριστερά του operator = με αυτό που υπάρχει δεξιά. Απλά κάνε μία δοκιμή. Πέρνα το n ByRef.
Σκέψου ότι αφού δεν δουλεύει ο κώδικας σου, κι ας είναι φαινομενικά τόσο απλός, κάτι θα γίνεται λάθος. Προφανώς δεν πρόκειται για bug του .NET ή της VB.NET ή του TreeView, αλλιώς θα είχε διορθωθεί 6 χρόνια τώρα.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
15-12-2008, 23:23
|
-
mclisme
-
-
-
Μέλος από τις 13-11-2008
-
-
Δημοσιεύσεις 23
-
-
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Ναι, είχα διαβάσει την διαφορά αυτή, δεν ήξερα όμως τι ακριβώς μπορούσες να αλλαξεις και τι όχι. Αποδεικνύεται όμως πως μπορείς να αλλάξεις τις ιδιοτητές του όπως το κείμενο, τα περιεχόμενά του ή ακομα και να το σβήσεις! Το μόνο που δεν γίνεται είναι να το θέσεις εξαρχής = κάτι άλλο. Έτσι καταλήγουμε ότι φταίει το ByVal. Δεν ξέρω όμως αν διάβασες στο αρχικό ποστ μου, ότι δοκίμασα ακριβώς αυτό, να αλλάξω το ByVal σε ByRef αλλά και πάλι το ίδιο αποτέλεσμα είχα. Αρα κάτι άλλο φταίει που δεν βλέπω την αλλαγή, παρόλο που το n, αν το ελεγξω μέσα από τον debugger αμέσως μετα το cloning, δείχνει να έχει αλλάξει και όνομα (text) και περιεχόμενα.
|
|
-
16-12-2008, 00:30
|
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Μπορεί να έχεις δημιουργήσει ένα αντίγραφο του Node, δεν το έχεις προσθέσει όμως πουθενά. Αν δεν καλέσεις την Add ή την Insert της Nodes δεν μπορείς να προσθέσεις το νέο Node. Το For loop σου επιστρέφει ένα-ένα τα αντικείμενα του Nodes, δεν σου παρέχει κάποιο set για να τα αλλάξεις. Μπορείς να κάνεις αυτό που θέλεις άνετα με τον παρακάτω κώδικα:
Dim results As TreeNode() = TreeView1.Nodes.Find("Node3", True) If results.Length > 0 Then Dim targetNode As TreeNode = results(0) Dim clonedNode As TreeNode = targetNode.Clone() Dim parentNode As TreeNode = targetNode.Parent clonedNode.Text = "New " & clonedNode.Text Dim index As Integer = targetNode.Index If Not parentNode Is Nothing Then parentNode.Nodes.Insert(index, clonedNode) parentNode.Nodes.RemoveAt(index + 1) Else TreeView1.Nodes.Insert(index, clonedNode) TreeView1.Nodes.RemoveAt(index + 1) End If End If
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
16-12-2008, 11:06
|
-
mclisme
-
-
-
Μέλος από τις 13-11-2008
-
-
Δημοσιεύσεις 23
-
-
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Αρχικά σε ευχαριστώ για τον χρόνο που διέθεσες για να γράψεις το παραπάνω κομμάτι κώδικα. Πρέπει να αναφέρω πως κ εγώ είχα σκεφτεί μια λύση που δημιουργούσε το αντικείμενο που θέλω με επιτυχία, αλλά μέσω μιας μεγαλύτερης διαδικασίας από μια απλή εντολή Clone, παρόμοια με αυτήν που περιγράφεις. Θα ήθελα όμως να με διαφωτίσεις στο εξής, καθότι και η ίδια η ερώτηση μου ήταν εξαρχής θεωρητικού υποβάθρου. Έχουμε τα εξής δεδομένα: 1) Γράφοντας την εντολή: TreeView1.Nodes(0) = myTreenode πχ. σε ενα button handler, παρατηρούμε το treenode 0 του treeview να γίνεται πιστό αντίγραφο του myTreenode (χάνει ότι περιείχε προηγουμένως) και όχι να προσθέτει στα παιδιά του, την οικογένεια του myTreenode. Επίσης η αλλαγή γίνεται με την συγκεκριμένη γραμμή και μόνο, χωρίς περαιτέρω κώδικα. 2) Παρατηρούμε ότι μέσω μιας αναγωγικής συνάρτησης όπως η foo, προσπελαύνεται με επιτυχία κάθε ένα υπαρκτό treenode ενός treeview σαν το όρισμα n της foo, και οποιαδήποτε αλλαγή κάνουμε σε ιδιότητα του n, όπως name, text, nodes.add, remove, περνά, έχει αντίκτυπο σε κάποιο υπαρκτό treenode του treeview.
3) Γιατί λοιπόν (συνδυάζοντας τα 2 παραπάνω), ενώ η Clone όταν εφαρμόζεται απευθείας σε ενα treenode (δεδομένο νο.1) κάνει αυτό που πρέπει με άμεσο και ορατό αντίκτυπο σε κάποιο treenode του δένδρου, αδυνατεί να το κάνει όταν καλεί το ίδιο treenode μέσω του n, παρόλο που μπορεί να κάνει επιτυχώς πολλά άλλα πράγματα στο n και αυτά να περάσουν επιτυχώς σε κάποιο υπαρκτό treenode (δεδομένο νο.2) ?
|
|
-
16-12-2008, 15:38
|
-
mclisme
-
-
-
Μέλος από τις 13-11-2008
-
-
Δημοσιεύσεις 23
-
-
|
Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση
Δεδομένο νο.1 = Άκυρο! Το αποτέλεσμα της εντολής αυτής είναι να προστεθεί ένα νέο treenode στη θεση 0. Ψάχνοντας όλο το project μου απο την αρχή ανακάλυψα (ενάντια σε ότι ισχυριζόμουν ως τώρα) ότι σε όλες τις περιπτώσεις που χρησιμοποιούσα την .Clone, αριστερά του = είχα πάντα ένα ανεξάρτητο treenode object, και μόνο δεξιά έκανα απυθείας αναφορές σε κάποιο υπαρκτό node του δένδρου (Treeview1.Nodes(2))  θα έβαζα στοίχημα ότι είχα καταφέρει να το κάνω και στα αριστερά αν δεν με διέψευδε η αναζήτηση.... Οπότε πήρα την απάντηση μου γιατί δεν έβλεπα αποτέλεσμα είτε byref είτε byval. Δεν συμφωνείς όμως ότι είναι περίεργο το ότι η συγκεκριμένη εντολή εκτελείται με επιτυχία μονοσήμαντα? Δηλαδή έχοντας ως πηγή ένα οποιοδήποτε treenode (μέλος κάποιου δένδρου ή όχι) αλλά ως στόχο ή αλλιώς δέκτη της κλωνοποίησης μόνο κάποιο ξεχωριστό treenode object και όχι κάποιο μέλους υπαρκτού treeview? Γιατί δηλαδή όταν έχεις ως δέκτη ενα ξεχωριστό treenode object, δε χρειάζεται να κάνεις add ή insert και βλέπεις το αποτέλεσμα απευθείας, ενώ σε μέλη ενταγμένα σε υπάρχον δένδρο όχι? Φυσικά δεν μιλάμε για bug απλά για την λογική της VB...
|
|
|
|
|