Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση

Îåêßíçóå áðü ôï ìÝëïò mclisme. Τελευταία δημοσίευση από το μέλος mclisme στις 16-12-2008, 15:38. Υπάρχουν 10 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  13-12-2008, 14:18 46887

    Η 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 46916 σε απάντηση της 46887

    Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση

    Χωρίς να έχω καταλάβει τι θες να κάνεις και με τον κώδικά που βλέπω είναι λογικό να μην βλέπεις τίποτα στο TreeView.

    Η Clone δημιουργεί ένα καινούριο TreeNode. Τι θα το κάνεις αυτό; Θα το προσθέσεις στο TreeView; Αν ναι γράψε απλά TreeView1.Nodes.Add(n) αμέσως μετά το Clone και θα το δεις.

  •  15-12-2008, 21:26 46917 σε απάντηση της 46887

    Απ: Η 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 46920 σε απάντηση της 46917

    Απ: Η 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 46921 σε απάντηση της 46916

    Απ: Η 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 46922 σε απάντηση της 46920

    Απ: Η 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 46923 σε απάντηση της 46921

    Απ: Η 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 46924 σε απάντηση της 46922

    Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση

    Ναι, είχα διαβάσει την διαφορά αυτή, δεν ήξερα όμως τι ακριβώς μπορούσες να αλλαξεις και τι όχι. Αποδεικνύεται όμως πως μπορείς να αλλάξεις τις ιδιοτητές του όπως το κείμενο, τα περιεχόμενά του ή ακομα και να το σβήσεις! Το μόνο που δεν γίνεται είναι να το θέσεις εξαρχής = κάτι άλλο. Έτσι καταλήγουμε ότι φταίει το ByVal. Δεν ξέρω όμως αν διάβασες στο αρχικό ποστ μου, ότι δοκίμασα ακριβώς αυτό, να αλλάξω το ByVal σε ByRef αλλά και πάλι το ίδιο αποτέλεσμα είχα. Αρα κάτι άλλο φταίει που δεν βλέπω την αλλαγή, παρόλο που το n, αν το ελεγξω μέσα από τον debugger αμέσως μετα το cloning, δείχνει να έχει αλλάξει και όνομα (text) και περιεχόμενα.
  •  16-12-2008, 00:30 46925 σε απάντηση της 46924

    Απ: Η 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 46929 σε απάντηση της 46924

    Απ: Η 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 46932 σε απάντηση της 46929

    Απ: Η Clone Method δεν δουλεύει πάνω σε αντικείμενο που καλείται απο συνάρτηση

    Δεδομένο νο.1 = Άκυρο! Το αποτέλεσμα της εντολής αυτής είναι να προστεθεί ένα νέο treenode στη θεση 0. Ψάχνοντας όλο το project μου απο την αρχή ανακάλυψα (ενάντια σε ότι ισχυριζόμουν ως τώρα) ότι σε όλες τις περιπτώσεις που χρησιμοποιούσα την .Clone, αριστερά του = είχα πάντα ένα ανεξάρτητο treenode object, και μόνο δεξιά έκανα απυθείας αναφορές σε κάποιο υπαρκτό node του δένδρου (Treeview1.Nodes(2)) Zip it! θα έβαζα στοίχημα ότι είχα καταφέρει να το κάνω και στα αριστερά αν δεν με διέψευδε η αναζήτηση.... Οπότε πήρα την απάντηση μου γιατί δεν έβλεπα αποτέλεσμα είτε byref είτε byval. Δεν συμφωνείς όμως ότι είναι περίεργο το ότι η συγκεκριμένη εντολή εκτελείται με επιτυχία μονοσήμαντα? Δηλαδή έχοντας ως πηγή ένα οποιοδήποτε treenode (μέλος κάποιου δένδρου ή όχι) αλλά ως στόχο ή αλλιώς δέκτη της κλωνοποίησης μόνο κάποιο ξεχωριστό treenode object και όχι κάποιο μέλους υπαρκτού treeview? Γιατί δηλαδή όταν έχεις ως δέκτη ενα ξεχωριστό treenode object, δε χρειάζεται να κάνεις add ή insert και βλέπεις το αποτέλεσμα απευθείας, ενώ σε μέλη ενταγμένα σε υπάρχον δένδρο όχι? Φυσικά δεν μιλάμε για bug απλά για την λογική της VB...
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems