19

I am trying to create some custom buttons or user controls as shown in the proposed GUI. The functionality should be as follows:

The graphs or configurations are created graphically.

The controls can be dragged from a toolbar or inserted by right mouse click/dropdown

By dragging from one control to another, they should be connected by lines

A toggle should shift the view from controls with options to a simple view

GUI view - controls with options: GUI view controls with options

GUI view - minimized: enter image description here

Which functionality in Windows forms can I use to create the connecting lines ?

If they are created by using functionality to draw lines, how can I make sure the controls snap to the line? ..

I am programming in C# with Visual Studio 2010 Express.

Eirik
  • 649
  • 2
  • 5
  • 13
  • the different colours for the lines indicates different relationships. They could probably be create with a CTRL + Drag ? – Eirik Apr 04 '13 at 18:50
  • You really have 2 questions going on. First, use `UserControl` as a platform for your custom controls. The second part is about how to use GDI to draw the lines. :) – IAbstract Apr 04 '13 at 18:52
  • sorry.. I guess I saw them as related and the question was more: how can I achieve "all of this" .. thanks for the tip about UserControl - I'll look into that. Can they be toggled to allow for a minimized version? ... – Eirik Apr 04 '13 at 18:58
  • 2
    Dude, your are setting yourself for a lot of pain. Why do you want to do this in winforms? have you considered using any of the current (<10 years old), faster, more scalable, vector, based, XAML-based windows UI technologies instead? I can create that with WPF in 20 minutes. – Federico Berasategui Apr 04 '13 at 19:05
  • well, the rest of my application (a plugin running in Rhino CAD) is controlled via a Windowsforms Form. Is there a way to integrate newer technologies in a winform application? .. I really don't need the pain, it is just the front for a GA generating architecture and it is difficult enough ... Rhino is built on dotnet, so I can run dotnet stuff in the plugin... – Eirik Apr 04 '13 at 19:13
  • Yep, you can integrate WPF content in an existing winforms application via the `ElementHost`. – Federico Berasategui Apr 04 '13 at 19:22
  • ok. And does that make sense? Or should I try to create the whole front for my GA in WPF? .. The GUI looks something like this at the moment [link](http://s8.postimg.org/85efn158l/space_configuration_SPEA.jpg) and the Room configuration in question would be on a tab section of this ... – Eirik Apr 04 '13 at 19:27
  • 1
    If you ask ME... precisely... I tend to tell everyone that winforms is completely useless and it doesn't support anything, and that it is never an option for any projects, no matter the scale or the features needed. Take a look at [this](http://stackoverflow.com/a/15580293/643085) sample I made in 3 hours – Federico Berasategui Apr 04 '13 at 19:35
  • ok. sold : ) .. is there a WYSIWYG editor in Visual Studio 2010 Express for this stuff? could you Answer this question with an approach how to solve this in WPF? – Eirik Apr 04 '13 at 19:37
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27589/discussion-between-highcore-and-eirik) – Federico Berasategui Apr 04 '13 at 21:00

2 Answers2

33

Ok. This is a slight modification of the example I created for A similar requirement

My intention is to show that winforms is no longer an option for anyone who needs a serious UI. The original sample was created in 3 man hours.

You might be surprised to know that the container that holds all these items (both nodes and connectors) is actually a ListBox.

Things worth noting:

  • The "NodeXX" text is contained within a Thumb control, which enables clicking and dragging.
  • The connectors can also be selected and show a nice animation when they are.
  • The left panel allows edition of the currently selected object's values.
  • The functionality of the UI is completely decoupled from the data that comprises it. Therefore all this nodes and connectors are simple classes with simple int and double properties that can be loaded/saved from a DB or whatever other data source.
  • If you dislike the way click sequences are done do draw nodes and connectors, that can be perfectly adapted to your needs.
  • WPF rules.

Edit:

Second version, this time much more similar to your original screenshot:

enter image description here

enter image description here

  • I added the concept of SnapSpot into the equation. These are the little red semi-circles you see around the nodes, which are actually what the Connectors are tied to.
  • I also changed the Connector DataTemplate to use a QuadraticBezierSegment based on

    Connector.Start.Location,
    Connector.MidPoint, and 
    Connector.End.Location 
    

This allows curved lines to be used as connectors, not just straight lines.

  • There's a little red-square-shaped Thumb that will appear when you select (click) on a Connector, (visible in the screenshot) that will allow you to move the MidPoint of the curve.
  • You can also manipulate that value by rolling the mouse wheel when hovering the TextBoxes under "Mid Point" in the left panel.
  • The "Collapse All" CheckBox allows to toggle between full and small boxes, as shown in the screenshot.
  • The SnapSpots have an OffsetX OffsetY between 0 and 1 that corresponds to their position relative to the parent Node. These are not limited to 4 and could actually be any number of them per Node.
  • The ComboBoxes and Buttons have no functionality, but it's just a matter of creating the relevant properties and Commands in the Node class and bind them to that.

Edit2:

Updated download link with a much nicer version.

Edit 10/16/2014: Since a lot of people seem to be interested in this, I uploaded the source to GitHub.

Community
  • 1
  • 1
Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154
  • 1
    Three hours?! I don't really see how that's an argument in favor of WPF. It would take me less than an hour to write code that draws Bezier curves between two points in the `Paint` event handler. Maybe I didn't read the question carefully enough, but it looks like that's all that would be required here. Where shall I send my address to receive my refund check? :-p – Cody Gray - on strike Apr 05 '13 at 05:23
  • I guess the preference with WPF is more about the possibilities than the developing time? .. Anyway - thanks for the working example in WPF, looks exactly as what I need. The collapse all function is awesome. I hope I can work it into my plugin. Cheers – Eirik Apr 05 '13 at 08:22
  • 2
    @CodyGray did you open the zip file with the example? please run it and then tell me that you can do the same in less time in winforms. I will send you my whole salary if you do (which isn't that much btw). – Federico Berasategui Apr 05 '13 at 13:03
  • @CodyGray each of these squares has variable `Height` and `Width` properties, they support being "collapsed" to look like the second picture, all while retaining the relative positions of the "SnapSpots" (the red semi-circles to which the Connectors are tied). Also they can be clicked and dragged in the canvas, While they can also be selected (it's a `ListBox`), and the currently selected item is shown in the left (with edition capabilities). Finally, the squares are painted with a LinearGradientBrush and the connectors are animated when selected. I would **LOVE** to see your winforms version. – Federico Berasategui Apr 05 '13 at 14:56
  • @CodyGray and to top it all, I added an additional `Thumb` (the red little square at the right) that allows to move the MidPoint of the curve. Again, I would **REALLY LOVE** to see you winforms version of this. – Federico Berasategui Apr 05 '13 at 14:59
  • @CodyGray did I mention that the currently selected item in the `ListBox` is decorated with a nice `DropShadowEffect`? – Federico Berasategui Apr 05 '13 at 15:05
  • @CodyGray could it be that a limited winforms mindset can't even fathom the spectacularity of a WPF UI? Oh, and a last thing, there's NO FLICKER anywhere in my example. – Federico Berasategui Apr 05 '13 at 15:10
  • 1
    @HighCore Nice project. I also like your other project. Pretty cool stuff. :o) – DHN May 27 '13 at 17:37
  • 4
    +1 This is a great example of why WPF > WinForms. Awesome work @HighCore! – René Jun 22 '13 at 08:51
  • 1
    Unfortnatelly the link above is dead. May I ask you to upload it again? – Rolfi Jul 16 '13 at 11:57
  • @Rolfi sorry dude I didn't see your comment before. Just checked and the link is working. – Federico Berasategui Sep 06 '13 at 17:48
  • +1 Very very nice, not for example itself but to show how things should be done in _pure_ WPF-way! – Adriano Repetti Jan 09 '14 at 10:12
  • @HighCore: can your drawing be extended with pan/zoom functions - I mean in principle? Or do you need a canvas for that? – Gerard Feb 04 '14 at 08:22
  • @Gerard [this](http://stackoverflow.com/a/16947081/643085) is a modification of this project, made for another question, which supports pan and zoom, without using `RenderTransform`s. I think there was a bug, which the OP managed to resolve and posted in the comments of the answer. – Federico Berasategui Feb 04 '14 at 10:39
  • I concur with @Rolfi, the link seems dead. I can see it points to a rar file (https://cdn.anonfiles.com/1365195880585.rar) but the file doesn't ever download (0 bytes), not to mention the site takes you to a bunch of other malware sites. – safejrz Oct 07 '14 at 01:22
  • Any GitHub link if the code sample still exists? :( – safejrz Oct 14 '14 at 13:14
  • @Rolfi see my edit. Just uploaded the source to GitHub. – Federico Berasategui Oct 16 '14 at 16:08
  • Update the link as the GitHub repo has been reorganised. :-) https://github.com/High-Core/WPFSamples/tree/master/src/WPFSamples/Samples/HousePlan seem right – rozon Oct 30 '16 at 13:05
  • Plus 1 for the "WPF rules" bullet. – Click Ok Dec 10 '16 at 20:35
0

I'm guessing this is a graph type problem. The nodes are the rooms and the edges are the lines that connect the rooms. You can introduce another class (say Connection class) that describes how nodes are connected to edges. For example, your hall connects to a bedroom, not necessarily using a straight line. The Graphics.DrawBezier allows you to draw curved lines, but requires an array of points. This is where the the Connection class comes in. Some code may help...

   class Room
   {
     public Room(String name, Point location);
     public void Draw(Graphics g);
   }

   class Connection
   {
     public void Add(Point ptConnection);
     public void Add(Point[] ptConnection);

     // Draw will draw a straight line if only two points or will draw a bezier curve
     public void Draw(Graphics g);
   }

   class House // basically a graph
   {
     public void Add(Room room);
     public void AddRoomConnection(Room r1, Room r2, Connection connector);

     // draw, draw each room, then draw connections.
     public void Draw(Graphics g);
   }

   void Main()
   {
      House myHouse = new House();
      Room hall = new Room("Hall", new Point(120,10);
      Room bedroom1 = new Room("Bedroom1", Point(0, 80));
      Connection cnHallBedroom = new Connection();
      cn.Add(new Point());  // add two points to draw a line, 3 or more points to draw a curve.
      myHouse.AddRoomConnection(hall, bedroom1, cnHallBedroom);
   }

This is basic approach, maybe not the best but might serve as a starting point.

  • Hi Karl. Thanks for the code. It's sort of a graph type, or a space syntax. I've implemented it as a class which holds a list of itself as children, and the connections to other nodes are also in lists. recursive functions traverse the children if there are any. works great. Now I am looking for a way to graphically represent these graphs or to create them graphically. how can I drag these controls to a canvas and create/drag line connections between them. – Eirik Apr 04 '13 at 19:35
  • 1
    Hi Erik, I'm only guessing here so forgive me if I am wrong. 1. Have a sidebar containing rooms that you can use. 2. Allow a user to click on first then second room, this is where you can set connection parameters. 3. If a user clicks on a room and a second room create a single waypoint (draws a straight line) 4. Maybe allow a user to click on a connection to add additional waypoints. This would draw a bezier curve. –  Apr 04 '13 at 19:59
  • Thanks for guessing Karl : ) .. I guess I would like the rooms to be dragged onto a canvas, freely moved around and then connected by dragging lines between them. this could also be rearranged by dragging lines elsewhere. for instance how it works with Lucidcharts, have a look [here] (www.lucidchart.com). Therefore it is difficult to create the graph by first clicking on one room, then the next, etc. It would work to create an initial graph, but not to rearrange it. The rooms could also just be one control, with a editable Textinput as its title? .. – Eirik Apr 04 '13 at 20:13
  • I'm good at guesswork as a rule :-) Yes, I would make rooms a single user control, where you specify a name. You could of course subclass the user control for different rooms. I think the secret here is to create new rooms and add them to the "house class". How a user connect them is totally open-ended. Single line, bezier curve etc. That's where the connection class fits in. Two points is a single line, more than two points is a curve. Like I say, it's a basic approach. –  Apr 04 '13 at 20:22