Ich versuche, den Standardgraphenbetrachter der Graph#-Bibliothek zu ändern, weil seine Benutzeroberfläche schrecklich ist (versuchen Sie einfach, einen Knoten außerhalb der Grenzen zu ziehen, Sie werden sehen!)
Das grundlegende Setup ist dies: Es gibt ein GraphCanvas-Steuerelement (geerbt von Panel), die Kinder von Vertex und Edge-Steuerelement-Typen hat. Was ich erreichen möchte, ist:
- GraphCanvas hat Bildlaufleisten, wenn der Inhalt nicht auf den Bildschirm passt;
- GraphCanvas kann auch durch "Ziehen" gescrollt werden (einfach auf eine leere Stelle klicken und ziehen);
- GraphCanvas kann vergrößert und verkleinert werden (über CTRL+Mausrad);
- Scheitelpunkte können verschoben werden. Wenn ein Scheitelpunkt außerhalb der aktuellen Grenzen von GraphCanvas gezogen wird, werden die Grenzen vergrößert. Die Bildlaufleisten sollten dies widerspiegeln, aber das aktuelle Ansichtsfenster sollte nicht wegrollen, während der Scheitelpunkt gezogen wird. Dasselbe gilt, wenn das Ziehen eines Scheitelpunktes die Grenzen des GraphCanvas verkleinert - der GraphCanvas sollte die gleiche Größe beibehalten, bis der Ziehvorgang beendet ist, und erst dann seine Größe ändern. Das automatische Scrollen des Ansichtsfensters während eines Ziehvorgangs ist furchtbar verwirrend und führt leicht zu Ziehfehlern. Sehen Sie sich die ursprüngliche Implementierung an, wenn Sie wissen wollen, was ich meine.
Obwohl ich ein gutes Stück Erfahrung mit .NET habe, bin ich immer noch ein kompletter Anfänger in WPF. Mein derzeitiger Versuch ist (in der messen/anordnen-Layout-Phase) zu geben, jeder vertext die XY-Koordinate, die es wünscht (auch wenn negativ) und implementieren Zoomen/Scrollen durch die Behandlung von Mausereignissen auf der GraphCanvas und Ändern der RenderTransform-Eigenschaft. Durch Ziehen werden lediglich die XY-Koordinaten des jeweiligen Vertexes geändert (was wahrscheinlich ein Neulayout des gesamten Objekts zur Folge hat, was ebenfalls zu vermeiden wäre). Scrollbars werden implementiert, indem der GraphCanvas innerhalb eines ScrollViewers platziert und IScrollInfo auf dem GraphCanvas implementiert wird.
Leider scheint es ein Problem zu geben: Ich kann Mausereignisse auf dem GraphCanvas selbst nur erhalten, wenn es einen Hintergrund an der Stelle hat. Das wäre OK, ich will sowieso einen weißen Hintergrund, aber in den negativen Koordinaten des GraphCanvas wird der Hintergrund nicht gezeichnet - und reagiert somit auch nicht auf Mausereignisse.
Ich frage mich auch, ob ich das Richtige tue, indem ich allen meinen untergeordneten Steuerelementen (Eckpunkte und Kanten) erlaube, in negative Koordinaten zu gehen. Wie würden Sie dies implementieren?
Añadido: Zur Verdeutlichung des Hintergrundproblems sehen Sie sich den folgenden Screenshot an:
(Quelle: <a href="http://valts.21.lv/problem/GraphCanvas.png" rel="nofollow noreferrer">valts.21.lv </a>)
Was Sie hier sehen, ist ein einfaches Windows Forms-Formular mit einem WPF-Host-Steuerelement darauf. Das hat einen ScrollViewer in ihm, und der ScrollViewer hat die GraphCanvas in ihm. Der GraphCanvas enthält 4 Scheitelpunkte und 6 Kanten.
Der GraphCanvas wird gestreckt, um den ScrollViewer zu füllen. Da aber einige der Eckpunkte negative Koordinaten haben, wird eine RenderTransform angewendet, die einfach alles nach rechts verschiebt (TranslateTransform). Es hat auch einen weißen Hintergrundpinsel.
Beachten Sie den grauen Bereich auf der linken Seite. Das ist immer noch ein Teil der GraphCanvas, aber der Hintergrund-Pinsel irgendwie nicht dort exted. Wenn ich dort mit der linken Maustaste klicke (nicht auf einen Knoten, sondern auf die graue Fläche), erhalte ich außerdem NICHT ein Ereignis erhalten. Wenn ich mit der linken Maustaste auf den weißen Bereich klicke, erhalte ich alle Ereignisse problemlos.