C# 如何使用 Windows 窗体使用线条创建和连接自定义用户按钮/控件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15819318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create and connect custom user buttons/controls with lines using windows forms
提问by Eirik
I am trying to create some custom buttons or user controls as shown in the proposed GUI. The functionality should be as follows:
我正在尝试创建一些自定义按钮或用户控件,如建议的 GUI 中所示。功能应该如下:
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 视图 - 带选项的控件:
GUI view - minimized:
GUI 视图 - 最小化:
Which functionality in Windows forms can I use to create the connecting lines ?
我可以使用 Windows 窗体中的哪些功能来创建连接线?
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.
我正在使用 Visual Studio 2010 Express 在 C# 中编程。
采纳答案by Federico Berasategui
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.
我的目的是表明对于任何需要严肃 UI 的人来说,winforms 不再是一个选择。原始样本是在 3 个工时内创建的。
You might be surprised to know that the container that holds all these items (both nodes and connectors) is actually a ListBox
.
您可能会惊讶地发现,包含所有这些项目(节点和连接器)的容器实际上是一个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
anddouble
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.
- “NodeXX”文本包含在一个
Thumb
控件中,允许单击和拖动。 - 还可以选择连接器并在它们选择时显示漂亮的动画。
- 左侧面板允许编辑当前选定对象的值。
- UI 的功能与构成它的数据完全分离。因此,所有这种节点和连接器是简单的类与简单
int
和double
属性可加载/从DB或任何其它数据源保存。 - 如果您不喜欢单击序列的完成方式,请绘制节点和连接器,这可以完全满足您的需求。
- WPF 规则。
Edit:
编辑:
Second version, this time much more similar to your original screenshot:
第二个版本,这次更类似于您的原始屏幕截图:
- 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 theConnector
s are tied to. I also changed the
Connector
DataTemplate to use aQuadraticBezierSegment
based onConnector.Start.Location, Connector.MidPoint, and Connector.End.Location
- 我
SnapSpot
在等式中加入了 的概念。这些是您在节点周围看到的红色小半圆,它们实际上是Connector
s 所绑定的。 我还更改了
Connector
DataTemplate 以使用QuadraticBezierSegment
基于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 aConnector
, (visible in the screenshot) that will allow you to move theMidPoint
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
SnapSpot
s have anOffsetX
OffsetY
between 0 and 1 that corresponds to their position relative to the parentNode
. These are not limited to 4 and could actually be any number of them perNode
. - The
ComboBoxes
andButtons
have no functionality, but it's just a matter of creating the relevant properties and Commandsin theNode
class and bind them to that.
Thumb
当您选择(单击)Connector
, (在屏幕截图中可见)时,会出现一个红色的小方块,允许您移动MidPoint
曲线的 。- 您还可以通过将鼠标悬停
TextBoxes
在左侧面板中的“中点”下方时滚动鼠标滚轮来操纵该值。 - “全部折叠”
CheckBox
允许在完整框和小框之间切换,如屏幕截图所示。 - 所述
SnapSpot
■找一个OffsetX
OffsetY
对应于相对于父它们的位置0和1之间的是Node
。这些不限于 4 个,实际上每个Node
. - 在
ComboBoxes
和Buttons
没有的功能,但它只是创造了相关的性能和问题命令在Node
类并将其绑定到。
Edit2:
编辑2:
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.
编辑 10/16/2014:由于很多人似乎对此感兴趣,我将源上传到GitHub。
回答by Eirik
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...
我猜这是一个图形类型的问题。节点是房间,边是连接房间的线。您可以引入另一个类(比如 Connection 类)来描述节点如何连接到边。例如,您的大厅连接到卧室,不一定使用直线。Graphics.DrawBezier 允许您绘制曲线,但需要一组点。这是 Connection 类的用武之地。一些代码可能会有所帮助...
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.
这是基本方法,可能不是最好的,但可以作为起点。