Autor Beitrag
lapadula
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Do 08.06.17 21:17 
Hallo, weiss jemand wie man die childnodes innerhalb eines Knotens mit der Maus verschieben kann, sprich die Pätze sollen getauscht werden?

Hab mich ein wenig umgeguckt aber die meisten packen die childnodes in ein anders childnode.

z. B.

Automarken
- Audi
- BMW
- Mercedes

Mercedes soll nun an erster Stelle stehen, dies möchte ich aber mit der Maus verschieben.

Mfg


Zuletzt bearbeitet von lapadula am Fr 09.06.17 15:01, insgesamt 1-mal bearbeitet
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 08.06.17 23:18 
Wenn du dir das angesehen hast weißt du ja ungefähr wie man das Drag&Drop startet.
Um die Reihenfolge der ChildNodes zu ändern mußt du den gedragten Node beim droppen aus der Liste der Childnodes entfernen und wieder in der Liste einfügen und zwar mit dem Index an der der Stelle an der du einfügen willst

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
private void meinLieberTreeView_DragDrop(object sender, DragEventArgs e)
{
    // der gedraggte Node
    var sourceNode = e.Data.GetData(typeof(TreeNode)) as TreeNode; 
    if (sourceNode == null)
        return;

    // der Node über dem gedroppt wurde
    var pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
    var targetNode = ((TreeView)sender).GetNodeAt(pt);
    if (targetNode == null)
        return;

    // nur tauschen wenn beide Node am selben Parent hängen und Quell und Ziel Node nicht der gleiche ist
    if (!sourceNode.Equals(targetNode) && targetNode.Parent == sourceNode.Parent)
    {
        targetNode.Parent.Nodes.RemoveAt(sourceNode.Index);   // Node entfernen 
        targetNode.Parent.Nodes.Insert(targetNode.Index, sourceNode);  // Node wieder einfügen am Index des Ziel Nodes
    }
}

Für diesen Beitrag haben gedankt: lapadula
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Fr 09.06.17 10:28 
Danke aber warum

ausblenden C#-Quelltext
1:
targetNode.Parent.Nodes.RemoveAt(sourceNode.Index);					


Müsste es nicht so richtig sein, weil ich möchte doch das targetNode entfernen und den SourceNode dahin platzieren?

ausblenden C#-Quelltext
1:
targetNode.Parent.Nodes.RemoveAt(targetNode.Parent);					
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 09.06.17 10:38 
Zitat:
Müsste es nicht so richtig sein, weil ich möchte doch das targetNode entfernen und den SourceNode dahin platzieren?

Eigentlich nicht. Du möchtest einen Node an der Stelle des TargetNodes einfügen. Stell dir vor deine 3 ChildNodes haben vollgende Indexe
ausblenden Quelltext
1:
2:
3:
Audi
BMW
Mercedes

jetzt nimmst du den Node mit Index 3 (Mercedes) und droppst in auf den Node mit Index 1(Audi). Der Vorgang wäre

a.) Node 3(Mercedes) entfernen
b.) Und als Node 1 wieder einfügen.

Da es einen Node 1 (Audi) bereits gibt wird dessen Indes weitergeschoben und alle folgenden Nodes auch. So das du im Anschluss
ausblenden Quelltext
1:
2:
3:
Mercedes
Audi
BMW

hast.

Für diesen Beitrag haben gedankt: lapadula
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Fr 09.06.17 10:58 
Ahso

Und wenn ich Mercedes mit Audi tauschen möchte, also

Mercedes
BMW
Audi

zu

Audi
BMW
Mercedes

ohne das sich der Index von BMW sich ändert und weitergeschoben wird.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 09.06.17 13:09 
Oh, ich hatte verschieben verstanden nicht tauschen.

Remove Insert muß man einfach 2 mal machen. Die Reihenfolge könnte etwas difizil sein damit genau das Richtige rauskommt ;)
Das will ich erstmal ausprobieren bevor ich das als Code zeige, ist mir aus dem lameng zu gefährlich ;)

Für diesen Beitrag haben gedankt: lapadula
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Fr 09.06.17 14:48 
Hab mich da wohl wieder undeutlich ausgedrückt, sorry. Das englische wort wäre swap, glaube ich.

Habe das nun soweit, dass die Nodes richtig sortiert in ein Array kommen aber dieses Array mit Nodes kann ich nicht ausgeben und ich weiss echt nicht warum.

Hier mein Code:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
if (!sourceNode.Equals(targetNode) && targetNode.Parent == sourceNode.Parent)
            {
                TreeNode[] newNodes = new TreeNode[sourceNode.Parent.Nodes.Count];
                

                int targetIndex = targetNode.Index;
                int sourceIndex = sourceNode.Index;

                for (int i = 0; i < sourceNode.Parent.Nodes.Count; i++)
                {
                    if (i == targetIndex)
                    {
                        newNodes[i] = sourceNode.Parent.Nodes[sourceIndex];
                    }
                    else if (i == sourceIndex)
                    {
                        newNodes[i] = sourceNode.Parent.Nodes[targetIndex];
                    }
                    else
                    {
                        newNodes[i] = sourceNode.Parent.Nodes[i];
                    }
                }

               
                sourceNode.Parent.Nodes.Clear();

                foreach (TreeNode node in newNodes)
                {
                    sourceNode.Parent.Nodes.Add(node); // Bleibt alles gecleart, es wird nicht hinzugefügt
                    //treeView2.Nodes.Add(node); //Klappt, nur verschwindet das Parent
                }
 
                //sourceNode.Parent.Nodes.AddRange(newNodes); // Bleibt gecleart
            }


Wenn ich mein treeView direkt anspreche, dann klappt das zwar, allerdings verschwindet das Parent. Habe das im Code nochmal zusätzlich kommentiert
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Fr 09.06.17 15:39 
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
if (!sourceNode.Equals(targetNode) && targetNode.Parent == sourceNode.Parent)
            {
                TreeNode[] newNodes = new TreeNode[sourceNode.Parent.Nodes.Count];

                TreeNode parentNode = sourceNode.Parent;


                int targetIndex = targetNode.Index;
                int sourceIndex = sourceNode.Index;

                for (int i = 0; i < sourceNode.Parent.Nodes.Count; i++)
                {
                    if (i == targetIndex)
                    {
                        newNodes[i] = sourceNode.Parent.Nodes[sourceIndex];
                    }
                    else if (i == sourceIndex)
                    {
                        newNodes[i] = sourceNode.Parent.Nodes[targetIndex];
                    }
                    else
                    {
                        newNodes[i] = sourceNode.Parent.Nodes[i];
                    }
                }

                treeView2.Nodes.Clear();
                treeView2.Nodes.Add(parentNode);

                foreach (TreeNode node in newNodes)
                {
                    treeView2.Nodes[0].Nodes.Add(node);
                }
                treeView2.ExpandAll();
            }


Ich versuche nun alles zu clearen, vorher merke ich mir das Parent und möchte es dann wieder hinzufügen + die ganzen childnodes.

Leider bleibt die Reihenfolge gleich. Außer ich füge Parent.Text hinzu, oder "treeView".Nodes.Add("Parent"), dann macht er alles richtig.

Du bist meine letzte Hoffnung Ralf :D
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 09.06.17 19:29 
Das Ganze jetzt mit tauschen anstatt verschieben. Habe die Funktionalität zum tauschen, da wie angenommen etwas komplexer, in eine Extensionmethod ausgelagert.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
private void meinLieberTreeView_DragDrop(object sender, DragEventArgs e)
{
    var sourceNode = e.Data.GetData(typeof(TreeNode)) as TreeNode;
    if (sourceNode == null)
        return;

    var pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
    var targetNode = ((TreeView)sender).GetNodeAt(pt);
    if (targetNode == null)
        return;

    if (!sourceNode.Equals(targetNode) && targetNode.Parent == sourceNode.Parent)
        targetNode.Parent.SwapNodes(sourceNode, targetNode);
}


und hier die Klasse mit der Extensionmethod

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
public static class TreeViewExtensions
{
    public static void SwapNodes(this TreeNode parent, TreeNode first, TreeNode second)
    {
        if (parent == null)
            throw new ArgumentNullException(nameof(parent));
        if (first == null)
            throw new ArgumentNullException(nameof(first));
        if (second == null)
            throw new ArgumentNullException(nameof(second));
        if (!parent.Nodes.Contains(first) || !parent.Nodes.Contains(second))
            throw new InvalidOperationException("To swap, both nodes have to be in the parent collection.");

        if (first.Index > second.Index)
            Swap(ref first, ref second);

        int firstIndex = first.Index;
        int secondIndex = second.Index;

        first.Remove();
        second.Remove();

        parent.Nodes.Insert(firstIndex, second);
        parent.Nodes.Insert(secondIndex, first);
    }

    private static void Swap<T>(ref T first, ref T second)
    {
        T temp = first;
        first = second;
        second = temp;
    }
}


Edit : Text der Fehlermeldung geändert.


Zuletzt bearbeitet von Ralf Jansen am Sa 10.06.17 14:46, insgesamt 2-mal bearbeitet

Für diesen Beitrag haben gedankt: lapadula
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 09.06.17 20:25 
- Nachträglich durch die Entwickler-Ecke gelöscht -

Für diesen Beitrag haben gedankt: lapadula, Ralf Jansen
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Sa 10.06.17 10:38 
Ohje, vielen Dank dafür!

Ich teste es im Laufe des Tages mal.

Bin bei meiner Lösung nicht weitergekommen.

Sowas müsste die Treeview eig standardmäßig können.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 10.06.17 12:11 
Zitat:
Bin bei meiner Lösung nicht weitergekommen.

In deiner gezeigten Lösung schreib mal hinter
ausblenden C#-Quelltext
1:
treeView1.Nodes.Clear();					

auch
ausblenden C#-Quelltext
1:
parentNode.Nodes.Clear();					

Du dachtest wohl das ein Clear am Treeview alle Nodes löscht aber übersehen das an dem gemerkten ParentNode den du wieder anhängst auch weiterhin ChildNodes hängen.
Der
ausblenden C#-Quelltext
1:
treeView1.Nodes.Add(parentNode);					

fügst alle Nodes wieder hinzu weil die ja alle noch am Parentnode hängen. Clear+Add hat dann nichts am Inhalt des TreeView geändert falls der ParentNode der einzige Node in der ersten Ebene des TreeViews war. Danach weitere sortierte Nodes an den Parentnode hängen geht nicht weil die ja immer noch dran hängen und das ein Node zweimal im TreeView hängt ist logischerweise nicht erlaubt ;)

Wenn du zu Übungszwecken deine Lösung zum fliegen bringen willst fehlt nicht viel. Du solltest versuchen den TreeView selbst aus der Logik herauszuhalten und dich nur auf die Nodes (insbesondere ParentNode anstatt TreeView) zu beziehen. Ist eigentlich einfacher und die Lösung ist generischer da egal ist wo genau sich der relevante Node im Baum steckt. Deine Lösung funktioniert nur (mit kleiner Korrektur) wenn der ParentNode auch der erste (einzige) Node in der Root des TreeViews ist.

Für diesen Beitrag haben gedankt: lapadula
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: So 11.06.17 14:55 
Danke für die Erklärung und nun funktioniert auch meine Lösung (nur wie du sagst, wenn es nur ein Parent gibt)